@jxsuite/studio 1.4.0 → 1.5.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.
package/index.html ADDED
@@ -0,0 +1,4631 @@
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" />
6
+ <title>Jx Studio</title>
7
+ <link rel="stylesheet" href="./dist/studio.css" />
8
+ <style>
9
+ /* Jx brand mono font, vendored in ./fonts (SIL OFL 1.1, see fonts/OFL.txt).
10
+ Latin subset only; the stack falls back to SF Mono / Fira Code for
11
+ other scripts. Monaco remeasures after load (src/services/monaco-setup.ts). */
12
+ @font-face {
13
+ font-family: "JetBrains Mono";
14
+ font-style: normal;
15
+ font-weight: 400;
16
+ font-display: swap;
17
+ src: url("./fonts/jetbrains-mono-400.woff2") format("woff2");
18
+ }
19
+ @font-face {
20
+ font-family: "JetBrains Mono";
21
+ font-style: normal;
22
+ font-weight: 500;
23
+ font-display: swap;
24
+ src: url("./fonts/jetbrains-mono-500.woff2") format("woff2");
25
+ }
26
+ @font-face {
27
+ font-family: "JetBrains Mono";
28
+ font-style: normal;
29
+ font-weight: 700;
30
+ font-display: swap;
31
+ src: url("./fonts/jetbrains-mono-700.woff2") format("woff2");
32
+ }
33
+ *,
34
+ *::before,
35
+ *::after {
36
+ box-sizing: border-box;
37
+ margin: 0;
38
+ }
39
+ sp-tab:not(:first-of-type) {
40
+ margin-inline-start: var(--mod-tabs-item-horizontal-spacing, 8px);
41
+ }
42
+ html,
43
+ body {
44
+ height: 100%;
45
+ overflow: hidden;
46
+ /* html/body sit outside <sp-theme>, so the --spectrum-* tokens are not
47
+ in scope here; the hex fallback is the intentional pre-theme backdrop
48
+ shown behind the app before sp-theme fills the viewport. */
49
+ background: var(--spectrum-background-layer-1-color, #111111);
50
+ }
51
+ /* Panel layout widths. These must live on :root (the <html> element),
52
+ not on sp-theme or #app, because the resize logic in
53
+ src/ui/panel-resize.ts reads and writes them as inline styles on
54
+ document.documentElement. A definition on any closer ancestor of #app
55
+ (sp-theme or body) would shadow that inline override and freeze the
56
+ sidebars. The #app.left/right-collapsed rules override per instance. */
57
+ :root {
58
+ --panel-w-left: 240px;
59
+ --panel-w-right: 280px;
60
+ --panel-w-chat: 320px;
61
+ }
62
+ /* Studio semantic token layer.
63
+ Declared on sp-theme — not :root — so each var(--spectrum-*) reference
64
+ resolves against the tokens sp-theme exposes via its :host rules. At
65
+ :root (the <html> ancestor of sp-theme) every --spectrum-* is undefined,
66
+ so these would silently collapse to the hex fallback and the app would
67
+ never respond to the Spectrum theme. All studio chrome, including the
68
+ #layer-* overlay hosts, lives inside <sp-theme>. */
69
+ sp-theme {
70
+ display: block;
71
+ height: 100%;
72
+ /* Surfaces. The hex fallbacks mirror the Jx brand ramp installed by
73
+ the 'app' theme fragment (src/ui/jx-theme.ts). */
74
+ --bg: var(--spectrum-background-layer-1-color, #111111);
75
+ --bg-panel: var(--spectrum-background-layer-2-color, #1a1a1a);
76
+ --bg-input: var(--spectrum-gray-100, #1a1a1a);
77
+ --border: var(--spectrum-gray-200, #222222);
78
+ /* Text */
79
+ --fg: var(--spectrum-neutral-content-color-default, #e4e4e7);
80
+ --fg-dim: var(--spectrum-gray-600, #a1a1aa);
81
+ /* Accent and status. Under the brand ramp (src/ui/jx-theme.ts),
82
+ accent-color-700 is the exact Jx brand blue and 900 is the soft
83
+ on-dark tint. */
84
+ --accent: var(--spectrum-accent-color-700, #3b82f6);
85
+ --accent-fg: var(--spectrum-white, #ffffff);
86
+ --danger: var(--spectrum-negative-color-900, #f44747);
87
+ --success: var(--spectrum-positive-color-900, #89d185);
88
+ --tag: var(--spectrum-informative-color-900, #93c5fd);
89
+ --signal: var(--spectrum-notice-color-900, #dcdcaa);
90
+ --handler: var(--spectrum-purple-900, #c586c0);
91
+ --warning: var(--spectrum-orange-900, #c5a332);
92
+ --map: var(--spectrum-indigo-900, #5b4fc7);
93
+ --slot-c: var(--spectrum-seafoam-900, #1a8a7a);
94
+ --switch-c: var(--danger);
95
+ --case-c: var(--spectrum-informative-color-800, #60a5fa);
96
+ /* Corner radius */
97
+ --radius: var(--spectrum-corner-radius-100, 3px);
98
+ /* Monospace stack for code/source chrome. JetBrains Mono is the Jx
99
+ brand mono (vendored in ./fonts); SF Mono / Fira Code remain as
100
+ system fallbacks ahead of the Spectrum stack (Source Code Pro /
101
+ Monaco). The brand fragment sets the same order on
102
+ --spectrum-code-font-family-stack for SWC components. */
103
+ --font-mono:
104
+ "JetBrains Mono", "SF Mono", "Fira Code",
105
+ var(--spectrum-code-font-family-stack, monospace);
106
+ /* Hover wash and accent tints */
107
+ --hover-bg: rgba(255, 255, 255, 0.04);
108
+ --accent-8: color-mix(in srgb, var(--accent) 8%, transparent);
109
+ --accent-10: color-mix(in srgb, var(--accent) 10%, transparent);
110
+ --accent-15: color-mix(in srgb, var(--accent) 15%, transparent);
111
+ --accent-20: color-mix(in srgb, var(--accent) 20%, transparent);
112
+ --accent-50: color-mix(in srgb, var(--accent) 50%, transparent);
113
+ /* Light canvas palette (stylebook, block/element previews, content
114
+ mode). These surfaces always render as a light "document" regardless
115
+ of the app chrome, so the ramp is derived from the theme-independent
116
+ Spectrum white/black tokens via color-mix rather than hard-coded hex.
117
+ The percentage is the black (foreground) or white (background) blend
118
+ of each step; this keeps the canvas light even in the dark chrome
119
+ while still being Spectrum-sourced. */
120
+ --canvas-fg: color-mix(
121
+ in srgb,
122
+ var(--spectrum-black, #000) 90%,
123
+ var(--spectrum-white, #fff)
124
+ );
125
+ --canvas-fg-2: color-mix(
126
+ in srgb,
127
+ var(--spectrum-black, #000) 80%,
128
+ var(--spectrum-white, #fff)
129
+ );
130
+ --canvas-fg-3: color-mix(
131
+ in srgb,
132
+ var(--spectrum-black, #000) 67%,
133
+ var(--spectrum-white, #fff)
134
+ );
135
+ --canvas-dim: color-mix(
136
+ in srgb,
137
+ var(--spectrum-black, #000) 47%,
138
+ var(--spectrum-white, #fff)
139
+ );
140
+ --canvas-muted: color-mix(
141
+ in srgb,
142
+ var(--spectrum-black, #000) 40%,
143
+ var(--spectrum-white, #fff)
144
+ );
145
+ --canvas-light: color-mix(
146
+ in srgb,
147
+ var(--spectrum-black, #000) 27%,
148
+ var(--spectrum-white, #fff)
149
+ );
150
+ --canvas-border: color-mix(
151
+ in srgb,
152
+ var(--spectrum-black, #000) 13%,
153
+ var(--spectrum-white, #fff)
154
+ );
155
+ --canvas-rule: color-mix(
156
+ in srgb,
157
+ var(--spectrum-black, #000) 7%,
158
+ var(--spectrum-white, #fff)
159
+ );
160
+ --canvas-bg-1: color-mix(
161
+ in srgb,
162
+ var(--spectrum-white, #fff) 96%,
163
+ var(--spectrum-black, #000)
164
+ );
165
+ --canvas-bg-2: color-mix(
166
+ in srgb,
167
+ var(--spectrum-white, #fff) 94%,
168
+ var(--spectrum-black, #000)
169
+ );
170
+ --canvas-track: color-mix(
171
+ in srgb,
172
+ var(--spectrum-white, #fff) 88%,
173
+ var(--spectrum-black, #000)
174
+ );
175
+ /* Data explorer syntax colors (mapped to nearest Spectrum hues) */
176
+ --data-key: var(--spectrum-blue-700, #3b82f6);
177
+ --data-string: var(--spectrum-orange-700, #ce9178);
178
+ --data-number: var(--spectrum-celery-700, #b5cea8);
179
+ --data-boolean: var(--tag);
180
+ /* Typography — align the chrome with the Spectrum sans stack used by
181
+ the SWC components; 12px maps exactly to font-size-75. line-height
182
+ stays 1.5 (a deliberate reading height; the Spectrum body token is
183
+ 1.3, which would tighten the whole UI). */
184
+ color: var(--fg);
185
+ background: var(--bg);
186
+ font-family: var(
187
+ --spectrum-sans-font-family-stack,
188
+ -apple-system,
189
+ BlinkMacSystemFont,
190
+ "Segoe UI",
191
+ system-ui,
192
+ sans-serif
193
+ );
194
+ font-size: var(--spectrum-font-size-75, 12px);
195
+ line-height: 1.5;
196
+ }
197
+
198
+ /* ─── Layout ─────────────────────────────────── */
199
+ #app {
200
+ display: grid;
201
+ grid-template-rows: 36px auto auto auto minmax(0, 1fr) 24px;
202
+ grid-template-columns: 48px var(--panel-w-left) 1fr var(--panel-w-right) var(
203
+ --panel-w-chat
204
+ );
205
+ height: 100%;
206
+ }
207
+ #toolbar {
208
+ grid-column: 1 / -1;
209
+ display: flex;
210
+ align-items: center;
211
+ gap: 6px;
212
+ padding: 0 8px;
213
+ background: var(--bg);
214
+ border-bottom: 1px solid var(--border);
215
+ overflow: hidden;
216
+ min-width: 0;
217
+ /* Drive the responsive collapse below off the toolbar's own width. */
218
+ container-type: inline-size;
219
+ container-name: toolbar;
220
+ }
221
+ #toolbar > :not(.window-controls) {
222
+ min-width: 0;
223
+ flex-shrink: 1;
224
+ overflow: hidden;
225
+ }
226
+ #toolbar > .tb-spacer {
227
+ flex-shrink: 999;
228
+ }
229
+ #toolbar.electrobun-webkit-app-region-drag {
230
+ -webkit-app-region: drag;
231
+ }
232
+ #toolbar sp-action-group,
233
+ #toolbar sp-action-button,
234
+ #toolbar .breadcrumb {
235
+ -webkit-app-region: no-drag;
236
+ }
237
+ .window-controls {
238
+ margin-left: auto;
239
+ flex-shrink: 0;
240
+ }
241
+ .window-controls .csd-close:hover {
242
+ background: var(--spectrum-negative-background-color-default, #e34850);
243
+ color: white;
244
+ }
245
+ /* macOS traffic-light buttons */
246
+ .window-controls.mac {
247
+ margin-left: 0;
248
+ margin-right: 8px;
249
+ order: -1;
250
+ gap: 8px;
251
+ }
252
+ .window-controls.mac sp-action-button {
253
+ /* explicit min/max needed: as a flex item the button's auto min-width
254
+ is the inner shadow-DOM button's min-content size (~28px), which
255
+ would override width and squash the circle into an oval */
256
+ --spectrum-actionbutton-min-width: 12px;
257
+ --mod-actionbutton-min-width: 12px;
258
+ --mod-actionbutton-height: 12px;
259
+ --mod-actionbutton-edge-to-text: 0px;
260
+ --mod-actionbutton-edge-to-visual-only: 0px;
261
+ width: 12px;
262
+ min-width: 12px;
263
+ max-width: 12px;
264
+ height: 12px;
265
+ min-height: 12px;
266
+ max-height: 12px;
267
+ border-radius: 50%;
268
+ overflow: hidden;
269
+ border: none;
270
+ padding: 0;
271
+ }
272
+ .window-controls.mac .csd-close {
273
+ background: #ff5f57;
274
+ }
275
+ .window-controls.mac .csd-minimize {
276
+ background: #febc2e;
277
+ }
278
+ .window-controls.mac .csd-maximize {
279
+ background: #28c840;
280
+ }
281
+ .window-controls.mac sp-action-button:hover {
282
+ filter: brightness(0.85);
283
+ }
284
+ .window-controls.mac sp-action-button sp-icon-remove,
285
+ .window-controls.mac sp-action-button sp-icon-rectangle,
286
+ .window-controls.mac sp-action-button sp-icon-close {
287
+ display: none;
288
+ }
289
+ .window-controls.mac:hover sp-action-button sp-icon-remove,
290
+ .window-controls.mac:hover sp-action-button sp-icon-rectangle,
291
+ .window-controls.mac:hover sp-action-button sp-icon-close {
292
+ display: inline-flex;
293
+ color: rgba(0, 0, 0, 0.5);
294
+ width: 8px;
295
+ height: 8px;
296
+ }
297
+ /* Resize edge zones */
298
+ .resize-edge {
299
+ position: fixed;
300
+ z-index: 9999;
301
+ -webkit-app-region: no-drag;
302
+ }
303
+ .resize-edge.top {
304
+ top: 0;
305
+ left: 6px;
306
+ right: 6px;
307
+ height: 4px;
308
+ cursor: ns-resize;
309
+ }
310
+ .resize-edge.bottom {
311
+ bottom: 0;
312
+ left: 6px;
313
+ right: 6px;
314
+ height: 4px;
315
+ cursor: ns-resize;
316
+ }
317
+ .resize-edge.left {
318
+ left: 0;
319
+ top: 6px;
320
+ bottom: 6px;
321
+ width: 4px;
322
+ cursor: ew-resize;
323
+ }
324
+ .resize-edge.right {
325
+ right: 0;
326
+ top: 6px;
327
+ bottom: 6px;
328
+ width: 4px;
329
+ cursor: ew-resize;
330
+ }
331
+ .resize-edge.top-left {
332
+ top: 0;
333
+ left: 0;
334
+ width: 6px;
335
+ height: 6px;
336
+ cursor: nwse-resize;
337
+ }
338
+ .resize-edge.top-right {
339
+ top: 0;
340
+ right: 0;
341
+ width: 6px;
342
+ height: 6px;
343
+ cursor: nesw-resize;
344
+ }
345
+ .resize-edge.bottom-left {
346
+ bottom: 0;
347
+ left: 0;
348
+ width: 6px;
349
+ height: 6px;
350
+ cursor: nesw-resize;
351
+ }
352
+ .resize-edge.bottom-right {
353
+ bottom: 0;
354
+ right: 0;
355
+ width: 6px;
356
+ height: 6px;
357
+ cursor: nwse-resize;
358
+ }
359
+
360
+ #tab-strip {
361
+ grid-row: 2;
362
+ grid-column: 3;
363
+ min-height: 0;
364
+ min-width: 0;
365
+ }
366
+ #tab-strip:empty {
367
+ display: none;
368
+ }
369
+ #tab-bar {
370
+ grid-row: 3;
371
+ grid-column: 3;
372
+ min-width: 0;
373
+ }
374
+ #tab-bar:empty {
375
+ display: none;
376
+ }
377
+ /* Above-canvas frontmatter Properties panel (content-collection docs, edit mode) */
378
+ #frontmatter-panel {
379
+ grid-row: 4;
380
+ grid-column: 3;
381
+ overflow-y: auto;
382
+ max-height: 40vh;
383
+ background: var(--bg);
384
+ border-bottom: 1px solid var(--border);
385
+ }
386
+ #frontmatter-panel sp-accordion {
387
+ border: none;
388
+ }
389
+ #frontmatter-panel sp-accordion-item {
390
+ --spectrum-accordion-item-header-font-size: var(--spectrum-font-size-50, 11px);
391
+ }
392
+ #frontmatter-panel[hidden] {
393
+ display: none;
394
+ }
395
+ .fm-panel-body {
396
+ max-width: 760px;
397
+ margin: 0 auto;
398
+ padding: 2px 12px 8px;
399
+ }
400
+ .fm-panel-body .style-row > sp-textfield,
401
+ .fm-panel-body .style-row > .media-picker {
402
+ width: 100%;
403
+ }
404
+ #activity-bar {
405
+ grid-row: 2 / 6;
406
+ grid-column: 1;
407
+ display: flex;
408
+ flex-direction: column;
409
+ background: var(--bg);
410
+ border-right: 1px solid var(--border);
411
+ }
412
+ #left-panel {
413
+ grid-row: 2 / 6;
414
+ grid-column: 2;
415
+ overflow-y: auto;
416
+ background: var(--bg-panel);
417
+ border-right: 1px solid var(--border);
418
+ }
419
+ #canvas-wrap {
420
+ grid-row: 5;
421
+ grid-column: 3;
422
+ position: relative;
423
+ overflow: auto;
424
+ background: var(--bg-panel);
425
+ }
426
+ #right-panel {
427
+ grid-row: 2 / 6;
428
+ grid-column: 4;
429
+ overflow-y: auto;
430
+ background: var(--bg);
431
+ border-left: 1px solid var(--border);
432
+ }
433
+ /* Persistent AI chat sidebar — always a flex column (the chat UI owns its
434
+ own scrolling), unlike #right-panel which scrolls the whole panel. */
435
+ #chat-panel {
436
+ grid-row: 2 / 6;
437
+ grid-column: 5;
438
+ display: flex;
439
+ flex-direction: column;
440
+ overflow: hidden;
441
+ background: var(--bg);
442
+ border-left: 1px solid var(--border);
443
+ }
444
+ #chat-panel .panel-body {
445
+ flex: 1;
446
+ min-height: 0;
447
+ display: flex;
448
+ flex-direction: column;
449
+ overflow: hidden;
450
+ }
451
+
452
+ /* ─── Collapsed sidebars ──────────────────────── */
453
+ #app.left-collapsed {
454
+ --panel-w-left: 0px;
455
+ }
456
+ #app.left-collapsed #left-panel,
457
+ #app.left-collapsed #resize-left {
458
+ display: none;
459
+ }
460
+ #app.right-collapsed {
461
+ --panel-w-right: 0px;
462
+ }
463
+ #app.right-collapsed #right-panel,
464
+ #app.right-collapsed #resize-right {
465
+ display: none;
466
+ }
467
+ #app.chat-collapsed {
468
+ --panel-w-chat: 0px;
469
+ }
470
+ #app.chat-collapsed #chat-panel,
471
+ #app.chat-collapsed #resize-chat {
472
+ display: none;
473
+ }
474
+
475
+ /* ─── AI Panel Chat UI ──────────────────────────── */
476
+ .ai-tab-body {
477
+ display: flex;
478
+ flex-direction: column;
479
+ flex: 1;
480
+ min-height: 0;
481
+ overflow: hidden;
482
+ }
483
+ .ai-chat-header {
484
+ flex-shrink: 0;
485
+ display: flex;
486
+ align-items: center;
487
+ gap: 4px;
488
+ padding: 4px 6px;
489
+ min-width: 0;
490
+ border-bottom: 1px solid var(--border);
491
+ font-size: var(--spectrum-font-size-75, 12px);
492
+ }
493
+ .ai-chat-title {
494
+ min-width: 0;
495
+ overflow: hidden;
496
+ text-overflow: ellipsis;
497
+ white-space: nowrap;
498
+ font-weight: 600;
499
+ }
500
+ .ai-header-spacer {
501
+ flex: 1;
502
+ }
503
+ /* THE chat scroller — bounded by min-height:0 at every flex level above. */
504
+ .ai-chat-messages {
505
+ flex: 1 1 0;
506
+ min-height: 0;
507
+ overflow-y: auto;
508
+ overscroll-behavior: contain;
509
+ display: flex;
510
+ flex-direction: column;
511
+ gap: 8px;
512
+ padding: 8px;
513
+ font-size: var(--spectrum-font-size-75, 12px);
514
+ line-height: 1.5;
515
+ }
516
+ .ai-chat-empty {
517
+ color: var(--fg-dim);
518
+ text-align: center;
519
+ padding: 24px 12px;
520
+ }
521
+ .ai-msg-user {
522
+ align-self: flex-end;
523
+ max-width: 85%;
524
+ background: var(--accent-15);
525
+ border-radius: 8px 8px 2px 8px;
526
+ padding: 6px 10px;
527
+ }
528
+ .ai-msg-user-body {
529
+ white-space: pre-wrap;
530
+ overflow-wrap: anywhere;
531
+ }
532
+ .ai-msg-assistant {
533
+ align-self: stretch;
534
+ min-width: 0;
535
+ }
536
+ .ai-msg-md {
537
+ overflow-wrap: anywhere;
538
+ }
539
+ .ai-msg-md > *:first-child {
540
+ margin-top: 0;
541
+ }
542
+ .ai-msg-md > *:last-child {
543
+ margin-bottom: 0;
544
+ }
545
+ .ai-msg-md code {
546
+ background: rgba(0, 0, 0, 0.3);
547
+ padding: 1px 4px;
548
+ border-radius: var(--radius);
549
+ font-size: var(--spectrum-font-size-50, 11px);
550
+ font-family: var(--font-mono);
551
+ }
552
+ .ai-msg-md pre {
553
+ background: rgba(0, 0, 0, 0.3);
554
+ padding: 8px;
555
+ border-radius: var(--radius);
556
+ overflow-x: auto;
557
+ margin: 6px 0;
558
+ }
559
+ .ai-msg-md pre code {
560
+ background: none;
561
+ padding: 0;
562
+ }
563
+ .ai-msg-md table {
564
+ border-collapse: collapse;
565
+ margin: 6px 0;
566
+ }
567
+ .ai-msg-md th,
568
+ .ai-msg-md td {
569
+ border: 1px solid var(--border);
570
+ padding: 2px 6px;
571
+ }
572
+ .ai-msg-streaming {
573
+ white-space: pre-wrap;
574
+ overflow-wrap: anywhere;
575
+ }
576
+ .ai-msg-streaming::after {
577
+ content: "▋";
578
+ color: var(--accent);
579
+ animation: ai-cursor-blink 1s steps(2) infinite;
580
+ }
581
+ @keyframes ai-cursor-blink {
582
+ 50% {
583
+ opacity: 0;
584
+ }
585
+ }
586
+ .ai-msg-typing {
587
+ display: flex;
588
+ gap: 4px;
589
+ padding: 4px 2px;
590
+ }
591
+ .ai-msg-typing span {
592
+ width: 6px;
593
+ height: 6px;
594
+ border-radius: 50%;
595
+ background: var(--fg-dim);
596
+ animation: ai-typing-bounce 1.2s infinite;
597
+ }
598
+ .ai-msg-typing span:nth-child(2) {
599
+ animation-delay: 0.2s;
600
+ }
601
+ .ai-msg-typing span:nth-child(3) {
602
+ animation-delay: 0.4s;
603
+ }
604
+ @keyframes ai-typing-bounce {
605
+ 0%,
606
+ 60%,
607
+ 100% {
608
+ opacity: 0.3;
609
+ }
610
+ 30% {
611
+ opacity: 1;
612
+ }
613
+ }
614
+ .ai-msg-tools {
615
+ display: flex;
616
+ flex-direction: column;
617
+ gap: 4px;
618
+ margin-top: 6px;
619
+ }
620
+ .ai-tool-chip {
621
+ display: inline-flex;
622
+ align-items: center;
623
+ gap: 6px;
624
+ align-self: flex-start;
625
+ max-width: 100%;
626
+ overflow: hidden;
627
+ text-overflow: ellipsis;
628
+ white-space: nowrap;
629
+ background: var(--hover-bg);
630
+ border-left: 2px solid var(--accent);
631
+ border-radius: var(--radius);
632
+ padding: 3px 8px;
633
+ font-size: var(--spectrum-font-size-50, 11px);
634
+ color: var(--fg-dim);
635
+ font-family: var(--font-mono);
636
+ }
637
+ .ai-msg-tool-error {
638
+ background: var(--hover-bg);
639
+ border-left: 2px solid var(--danger);
640
+ border-radius: var(--radius);
641
+ padding: 4px 8px;
642
+ font-size: var(--spectrum-font-size-50, 11px);
643
+ color: var(--fg-dim);
644
+ }
645
+ .ai-msg-error {
646
+ border-left: 2px solid var(--danger);
647
+ border-radius: var(--radius);
648
+ background: var(--hover-bg);
649
+ padding: 6px 8px;
650
+ color: var(--danger);
651
+ }
652
+ .ai-msg-error-advice {
653
+ margin-top: 4px;
654
+ color: var(--fg-dim);
655
+ }
656
+ .ai-msg-context-chips {
657
+ display: flex;
658
+ flex-wrap: wrap;
659
+ gap: 4px;
660
+ margin-top: 6px;
661
+ }
662
+ .ai-context-chip {
663
+ display: inline-flex;
664
+ align-items: center;
665
+ gap: 2px;
666
+ max-width: 100%;
667
+ overflow: hidden;
668
+ text-overflow: ellipsis;
669
+ white-space: nowrap;
670
+ background: var(--bg-input);
671
+ border: 1px solid var(--border);
672
+ border-radius: var(--radius);
673
+ padding: 1px 6px;
674
+ font-size: var(--spectrum-font-size-50, 11px);
675
+ color: var(--fg-dim);
676
+ }
677
+ /* Sticky composer */
678
+ .ai-composer {
679
+ flex-shrink: 0;
680
+ display: flex;
681
+ flex-direction: column;
682
+ gap: 6px;
683
+ padding: 8px;
684
+ border-top: 1px solid var(--border);
685
+ }
686
+ .ai-composer-chips {
687
+ display: flex;
688
+ flex-wrap: wrap;
689
+ gap: 4px;
690
+ }
691
+ .ai-composer-input {
692
+ width: 100%;
693
+ box-sizing: border-box;
694
+ resize: none;
695
+ min-height: 30px;
696
+ max-height: 120px;
697
+ overflow-y: auto;
698
+ background: var(--bg-input);
699
+ color: var(--fg);
700
+ border: 1px solid var(--border);
701
+ border-radius: var(--radius);
702
+ padding: 6px 8px;
703
+ font-size: var(--spectrum-font-size-75, 12px);
704
+ font-family: inherit;
705
+ line-height: 1.4;
706
+ }
707
+ .ai-composer-input:focus {
708
+ border-color: var(--accent);
709
+ outline: none;
710
+ }
711
+ .ai-composer-row {
712
+ display: flex;
713
+ align-items: center;
714
+ gap: 4px;
715
+ min-width: 0;
716
+ }
717
+ .ai-model-picker {
718
+ max-width: 140px;
719
+ min-width: 0;
720
+ }
721
+ /* Sessions list */
722
+ .ai-sessions {
723
+ flex: 1 1 0;
724
+ min-height: 0;
725
+ overflow-y: auto;
726
+ font-size: var(--spectrum-font-size-75, 12px);
727
+ }
728
+ .ai-sessions-empty {
729
+ color: var(--fg-dim);
730
+ text-align: center;
731
+ padding: 24px 12px;
732
+ }
733
+ .ai-session-row {
734
+ display: flex;
735
+ align-items: center;
736
+ gap: 4px;
737
+ padding: 6px 8px;
738
+ cursor: pointer;
739
+ border-bottom: 1px solid var(--border);
740
+ min-width: 0;
741
+ }
742
+ .ai-session-row:hover {
743
+ background: var(--hover-bg);
744
+ }
745
+ .ai-session-text {
746
+ flex: 1;
747
+ min-width: 0;
748
+ }
749
+ .ai-session-title {
750
+ font-weight: 600;
751
+ overflow: hidden;
752
+ text-overflow: ellipsis;
753
+ white-space: nowrap;
754
+ }
755
+ .ai-session-meta {
756
+ color: var(--fg-dim);
757
+ font-size: var(--spectrum-font-size-50, 11px);
758
+ }
759
+ .ai-session-delete {
760
+ visibility: hidden;
761
+ }
762
+ .ai-session-row:hover .ai-session-delete {
763
+ visibility: visible;
764
+ }
765
+ .ai-status-center {
766
+ display: flex;
767
+ flex-direction: column;
768
+ align-items: center;
769
+ justify-content: center;
770
+ flex: 1;
771
+ gap: 12px;
772
+ padding: 24px;
773
+ text-align: center;
774
+ color: var(--fg-dim);
775
+ font-size: var(--spectrum-font-size-75, 12px);
776
+ }
777
+ .ai-code-snippet {
778
+ background: var(--bg-input);
779
+ padding: 4px 8px;
780
+ border-radius: var(--radius);
781
+ font-size: var(--spectrum-font-size-50, 11px);
782
+ }
783
+ .ai-managed-connect {
784
+ display: flex;
785
+ flex-direction: column;
786
+ align-items: center;
787
+ gap: 10px;
788
+ width: 100%;
789
+ }
790
+ .ai-managed-connect-error {
791
+ color: var(--danger);
792
+ font-size: var(--spectrum-font-size-50, 11px);
793
+ max-width: 260px;
794
+ }
795
+ .ai-managed-connect-divider {
796
+ color: var(--fg-dim);
797
+ font-size: var(--spectrum-font-size-50, 11px);
798
+ margin-top: 6px;
799
+ }
800
+ #statusbar {
801
+ grid-row: 6;
802
+ grid-column: 1 / -1;
803
+ display: flex;
804
+ align-items: center;
805
+ padding: 0 8px;
806
+ font-size: var(--spectrum-font-size-50, 11px);
807
+ color: var(--fg-dim);
808
+ background: var(--bg);
809
+ border-top: 1px solid var(--border);
810
+ }
811
+ #statusbar .sb-path-seg {
812
+ cursor: pointer;
813
+ border-radius: var(--spectrum-corner-radius-75, 2px);
814
+ padding: 0 2px;
815
+ }
816
+ #statusbar .sb-path-seg:hover {
817
+ color: var(--fg);
818
+ background: var(--hover-bg);
819
+ text-decoration: underline;
820
+ }
821
+ #statusbar .sb-path-sep {
822
+ color: var(--fg-dim);
823
+ }
824
+
825
+ /* ─── Tab strip ───────────────────────────────── */
826
+ .tab-strip {
827
+ display: flex;
828
+ align-items: stretch;
829
+ gap: 0;
830
+ padding: 0 8px;
831
+ background: var(--bg-panel);
832
+ border-bottom: 1px solid var(--border);
833
+ overflow-x: auto;
834
+ overflow-y: hidden;
835
+ scrollbar-width: none;
836
+ }
837
+ .tab-strip::-webkit-scrollbar {
838
+ display: none;
839
+ }
840
+ .tab-strip-tab {
841
+ display: flex;
842
+ align-items: center;
843
+ gap: 4px;
844
+ padding: 4px 8px;
845
+ font-size: var(--spectrum-font-size-50, 11px);
846
+ color: var(--fg-dim);
847
+ cursor: pointer;
848
+ white-space: nowrap;
849
+ border-bottom: 2px solid transparent;
850
+ user-select: none;
851
+ flex-shrink: 0;
852
+ }
853
+ .tab-strip-tab:hover {
854
+ color: var(--fg);
855
+ background: var(--hover-bg);
856
+ }
857
+ .tab-strip-tab.active {
858
+ color: var(--fg);
859
+ border-bottom-color: var(--accent);
860
+ }
861
+ .tab-strip-label {
862
+ max-width: 140px;
863
+ overflow: hidden;
864
+ text-overflow: ellipsis;
865
+ }
866
+ .tab-strip-dirty {
867
+ color: var(--accent);
868
+ font-size: 8px;
869
+ line-height: 1;
870
+ }
871
+ .tab-strip-close {
872
+ display: flex;
873
+ align-items: center;
874
+ justify-content: center;
875
+ width: 16px;
876
+ height: 16px;
877
+ padding: 0;
878
+ border: none;
879
+ background: none;
880
+ color: var(--fg-dim);
881
+ font-size: var(--spectrum-font-size-100, 14px);
882
+ line-height: 1;
883
+ border-radius: var(--radius);
884
+ cursor: pointer;
885
+ opacity: 0;
886
+ }
887
+ .tab-strip-tab:hover .tab-strip-close,
888
+ .tab-strip-tab.active .tab-strip-close {
889
+ opacity: 1;
890
+ }
891
+ .tab-strip-close:hover {
892
+ background: var(--hover-bg);
893
+ color: var(--fg);
894
+ }
895
+
896
+ /* ─── Resize handles ─────────────────────────── */
897
+ .resize-handle {
898
+ grid-row: 5;
899
+ width: 5px;
900
+ margin-left: -3px;
901
+ margin-right: -2px;
902
+ cursor: col-resize;
903
+ z-index: 10;
904
+ position: relative;
905
+ }
906
+ .resize-handle:hover,
907
+ .resize-handle.dragging {
908
+ background: var(--accent, #3b82f6);
909
+ opacity: 0.5;
910
+ }
911
+ #resize-left {
912
+ grid-column: 3;
913
+ justify-self: start;
914
+ }
915
+ #resize-right {
916
+ grid-column: 4;
917
+ justify-self: start;
918
+ }
919
+ #resize-chat {
920
+ grid-column: 5;
921
+ justify-self: start;
922
+ }
923
+
924
+ /* ─── Canvas (multi-panel) ────────────────────── */
925
+ #canvas-wrap {
926
+ display: flex;
927
+ gap: 24px;
928
+ align-items: flex-start;
929
+ }
930
+ .panzoom-wrap {
931
+ display: inline-flex;
932
+ gap: 24px;
933
+ align-items: flex-start;
934
+ transform-origin: 0 0;
935
+ margin-block: auto;
936
+ }
937
+ .canvas-panel {
938
+ flex-shrink: 0;
939
+ }
940
+ .source-wrap {
941
+ display: flex;
942
+ flex-direction: column;
943
+ width: 100%;
944
+ height: 100%;
945
+ flex: 1;
946
+ min-width: 0;
947
+ }
948
+ .tab-bar {
949
+ display: flex;
950
+ align-items: center;
951
+ gap: 8px;
952
+ padding: 4px 8px;
953
+ border-bottom: 1px solid var(--border);
954
+ background: var(--bg-panel);
955
+ }
956
+ .tab-bar .tb-spacer {
957
+ flex: 1;
958
+ }
959
+ .tab-bar sp-picker.tab-bar-param {
960
+ max-width: 200px;
961
+ }
962
+ /* Zoom widget label: fixed floor so the row doesn't jitter as the % digits change. */
963
+ .tab-bar .tb-zoom-label {
964
+ min-width: 48px;
965
+ font-family: var(--font-mono);
966
+ }
967
+ .source-editor {
968
+ flex: 1;
969
+ min-height: 0;
970
+ }
971
+ /* ─── Content edit mode canvas ─────────────── */
972
+ .content-edit-canvas {
973
+ width: 100%;
974
+ height: 100%;
975
+ overflow-y: auto;
976
+ overflow-x: hidden;
977
+ display: flex;
978
+ justify-content: center;
979
+ padding: 32px 0;
980
+ }
981
+ .content-edit-column {
982
+ width: 100%;
983
+ min-height: 100%;
984
+ }
985
+ /* A content PAGE fills the viewport (a document-like surface you can click into below the
986
+ text). A component DEFINITION is a fragment — flooring its column to the viewport and letting
987
+ the flex parent vertical-stretch it leaves dead scrollable space below a short component.
988
+ `is-component` (set by renderCanvas when the doc root is a custom element) makes the column
989
+ hug its iframe and sit at the top instead. */
990
+ .content-edit-column.is-component {
991
+ min-height: 0;
992
+ align-self: flex-start;
993
+ }
994
+ .content-edit-column .canvas-panel.full-width {
995
+ flex: 1;
996
+ min-width: 0;
997
+ }
998
+ .content-edit-column .canvas-panel-viewport {
999
+ border: none;
1000
+ background: transparent;
1001
+ }
1002
+ .function-editor-header {
1003
+ display: flex;
1004
+ align-items: center;
1005
+ justify-content: space-between;
1006
+ padding: 4px 8px;
1007
+ background: var(--bg-panel);
1008
+ border-bottom: 1px solid var(--border);
1009
+ font-size: var(--spectrum-font-size-75, 12px);
1010
+ color: var(--fg);
1011
+ font-family: var(--font-mono);
1012
+ }
1013
+ .canvas-panel-header {
1014
+ padding: 4px 8px;
1015
+ font-size: var(--spectrum-font-size-50, 11px);
1016
+ color: var(--fg-dim);
1017
+ background: var(--bg-panel);
1018
+ border: 1px solid var(--border);
1019
+ border-bottom: none;
1020
+ border-radius: var(--radius) var(--radius) 0 0;
1021
+ text-align: center;
1022
+ cursor: pointer;
1023
+ user-select: none;
1024
+ font-family: var(--font-mono);
1025
+ }
1026
+ .canvas-panel-header.active {
1027
+ color: var(--accent);
1028
+ border-color: var(--accent);
1029
+ }
1030
+ .canvas-panel-viewport {
1031
+ position: relative;
1032
+ background: var(--spectrum-white, #fff);
1033
+ border: 1px solid var(--border);
1034
+ /* The viewport is a light document surface, so pin a light color-scheme
1035
+ for native form controls and scrollbars rendered inside it. */
1036
+ color-scheme: light;
1037
+ }
1038
+ .canvas-panel-header.active + .canvas-panel-viewport {
1039
+ border-color: var(--accent);
1040
+ }
1041
+ .canvas-panel-canvas {
1042
+ isolation: isolate;
1043
+ }
1044
+ .canvas-panel-canvas * {
1045
+ cursor: default;
1046
+ }
1047
+ .canvas-panel-canvas slot:empty {
1048
+ display: block;
1049
+ min-height: 3rem;
1050
+ border: 2px dashed var(--spectrum-gray-400, #999);
1051
+ border-radius: var(--radius);
1052
+ position: relative;
1053
+ background: repeating-linear-gradient(
1054
+ 45deg,
1055
+ transparent,
1056
+ transparent 10px,
1057
+ rgba(128, 128, 128, 0.03) 10px,
1058
+ rgba(128, 128, 128, 0.03) 20px
1059
+ );
1060
+ }
1061
+ .canvas-panel-canvas slot:empty::before {
1062
+ content: "slot";
1063
+ position: absolute;
1064
+ top: 50%;
1065
+ left: 50%;
1066
+ transform: translate(-50%, -50%);
1067
+ font-size: 0.75rem;
1068
+ color: var(--spectrum-gray-500, #888);
1069
+ font-family: var(--font-mono);
1070
+ pointer-events: none;
1071
+ }
1072
+ /* Single-canvas fallback (no $media) */
1073
+ .canvas-panel.full-width {
1074
+ min-width: 0;
1075
+ }
1076
+ .overlay-box {
1077
+ position: absolute;
1078
+ pointer-events: none;
1079
+ }
1080
+ .overlay-selection {
1081
+ border: 2px solid var(--accent);
1082
+ }
1083
+ .overlay-hover {
1084
+ border: 1px solid var(--accent-50);
1085
+ }
1086
+ .overlay-layout {
1087
+ border-style: dashed !important;
1088
+ border-color: var(--spectrum-purple-600, #9256d9) !important;
1089
+ }
1090
+ .overlay-layout-badge {
1091
+ position: absolute;
1092
+ top: -16px;
1093
+ left: 0;
1094
+ font-size: 9px;
1095
+ padding: 1px 5px;
1096
+ background: var(--spectrum-purple-600, #9256d9);
1097
+ color: white;
1098
+ border-radius: var(--radius);
1099
+ text-transform: uppercase;
1100
+ letter-spacing: 0.5px;
1101
+ pointer-events: none;
1102
+ }
1103
+ .overlay-label {
1104
+ position: absolute;
1105
+ top: -20px;
1106
+ left: -2px;
1107
+ padding: 1px 5px;
1108
+ font-size: 10px;
1109
+ background: var(--accent);
1110
+ color: var(--accent-fg);
1111
+ border-radius: var(--spectrum-corner-radius-75) var(--spectrum-corner-radius-75) 0 0;
1112
+ white-space: nowrap;
1113
+ pointer-events: none;
1114
+ }
1115
+
1116
+ /* ─── Unified block action bar ─────────────── */
1117
+ .block-action-bar {
1118
+ position: fixed;
1119
+ pointer-events: auto;
1120
+ display: flex;
1121
+ align-items: center;
1122
+ gap: 2px;
1123
+ background: var(--bg-panel);
1124
+ border: 1px solid var(--border);
1125
+ border-radius: var(--radius);
1126
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
1127
+ padding: 2px 4px;
1128
+ white-space: nowrap;
1129
+ z-index: 100;
1130
+ }
1131
+ .block-action-bar .bar-tag {
1132
+ font-size: 10px;
1133
+ padding: 0 4px;
1134
+ border-radius: var(--spectrum-corner-radius-75, 2px);
1135
+ color: var(--accent-fg);
1136
+ background: var(--tag);
1137
+ max-width: 140px;
1138
+ overflow: hidden;
1139
+ text-overflow: ellipsis;
1140
+ }
1141
+ .block-action-bar .bar-tag--interactive {
1142
+ cursor: pointer;
1143
+ }
1144
+ .block-action-bar .bar-tag--interactive:hover {
1145
+ background: var(--accent);
1146
+ color: var(--bg);
1147
+ }
1148
+ .block-action-bar .bar-drag-handle {
1149
+ cursor: grab;
1150
+ font-size: var(--spectrum-font-size-100, 14px);
1151
+ padding: 0 4px;
1152
+ opacity: 0.7;
1153
+ user-select: none;
1154
+ display: inline-flex;
1155
+ align-items: center;
1156
+ line-height: 1;
1157
+ transform: translateY(1px);
1158
+ }
1159
+ .block-action-bar .bar-drag-handle:hover {
1160
+ opacity: 1;
1161
+ }
1162
+ .block-action-bar .bar-drag-handle:active {
1163
+ cursor: grabbing;
1164
+ }
1165
+ .block-action-bar sp-divider {
1166
+ height: 20px;
1167
+ margin: 0 2px;
1168
+ }
1169
+
1170
+ .link-popover {
1171
+ display: flex;
1172
+ gap: 4px;
1173
+ align-items: center;
1174
+ padding: 8px;
1175
+ background: var(--bg-panel);
1176
+ border: 1px solid var(--border);
1177
+ border-radius: var(--radius);
1178
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
1179
+ }
1180
+
1181
+ /* ─── Activity bar (vertical icon tabs) ──────── */
1182
+ #activity-bar sp-tabs {
1183
+ --mod-tabs-item-horizontal-spacing: 0px;
1184
+ --mod-tabs-start-to-tab-item: 0px;
1185
+ --mod-tabs-color: var(--fg-dim);
1186
+ --mod-tabs-color-selected: var(--fg);
1187
+ }
1188
+ #activity-bar sp-tab {
1189
+ position: relative;
1190
+ width: 48px;
1191
+ height: 48px;
1192
+ display: flex;
1193
+ align-items: center;
1194
+ justify-content: center;
1195
+ color: var(--fg-dim);
1196
+ opacity: 0.6;
1197
+ margin: 0;
1198
+ }
1199
+ .activity-badge {
1200
+ position: absolute;
1201
+ top: 6px;
1202
+ right: 4px;
1203
+ min-width: 16px;
1204
+ height: 16px;
1205
+ padding: 0 4px;
1206
+ border-radius: var(--spectrum-corner-radius-200, 8px);
1207
+ background: var(--accent);
1208
+ color: var(--spectrum-white);
1209
+ font-size: 9px;
1210
+ font-weight: 700;
1211
+ display: flex;
1212
+ align-items: center;
1213
+ justify-content: center;
1214
+ pointer-events: none;
1215
+ }
1216
+ #activity-bar sp-tab:hover {
1217
+ opacity: 1;
1218
+ }
1219
+ #activity-bar sp-tab[selected] {
1220
+ color: var(--fg);
1221
+ opacity: 1;
1222
+ }
1223
+
1224
+ /* ─── Panel tabs (right: horizontal icon tabs) ── */
1225
+ .panel-tabs {
1226
+ border-bottom: 1px solid var(--border);
1227
+ }
1228
+ .panel-tabs sp-tabs {
1229
+ --mod-tabs-item-horizontal-spacing: 0px;
1230
+ --mod-tabs-start-to-tab-item: 0px;
1231
+ --mod-tabs-color: var(--fg-dim);
1232
+ --mod-tabs-color-selected: var(--fg);
1233
+ --spectrum-tabs-top-to-text: 0px;
1234
+ --spectrum-tabs-bottom-to-text: 0px;
1235
+ }
1236
+ .panel-tabs sp-tab {
1237
+ padding: 4px 10px;
1238
+ color: var(--fg-dim);
1239
+ opacity: 0.7;
1240
+ min-block-size: unset;
1241
+ block-size: 36px;
1242
+ box-sizing: border-box;
1243
+ }
1244
+ .panel-tabs sp-tab:hover {
1245
+ opacity: 1;
1246
+ }
1247
+ .panel-tabs sp-tab[selected] {
1248
+ color: var(--fg);
1249
+ opacity: 1;
1250
+ }
1251
+ .panel-body {
1252
+ padding: 0;
1253
+ }
1254
+
1255
+ /* ─── File tree ──────────────────────────────── */
1256
+ .files-toolbar {
1257
+ display: flex;
1258
+ gap: 4px;
1259
+ padding: 4px 8px;
1260
+ border-bottom: 1px solid var(--border);
1261
+ align-items: center;
1262
+ }
1263
+ .files-toolbar sp-search {
1264
+ flex: 1;
1265
+ --spectrum-textfield-height: 24px;
1266
+ }
1267
+ .file-tree {
1268
+ overflow-y: auto;
1269
+ }
1270
+ .file-tree-item {
1271
+ display: flex;
1272
+ align-items: center;
1273
+ gap: 6px;
1274
+ padding: 3px 8px;
1275
+ cursor: pointer;
1276
+ font-size: var(--spectrum-font-size-75, 12px);
1277
+ color: var(--fg);
1278
+ user-select: none;
1279
+ }
1280
+ .file-tree-item:hover {
1281
+ background: var(--hover-bg);
1282
+ }
1283
+ .file-tree-item.selected {
1284
+ background: var(--accent-20);
1285
+ }
1286
+ .file-tree-item.dragging {
1287
+ opacity: 0.4;
1288
+ }
1289
+ .file-tree-item.drag-over {
1290
+ background: var(--accent-20);
1291
+ outline: 1px solid var(--accent);
1292
+ outline-offset: -1px;
1293
+ }
1294
+ .file-tree.drag-over-root {
1295
+ background: var(--hover-bg);
1296
+ }
1297
+ .file-tree-toggle {
1298
+ width: 14px;
1299
+ text-align: center;
1300
+ font-size: 8px;
1301
+ color: var(--fg-dim);
1302
+ flex-shrink: 0;
1303
+ cursor: pointer;
1304
+ }
1305
+ .file-tree-toggle.empty {
1306
+ visibility: hidden;
1307
+ }
1308
+ .file-tree-icon {
1309
+ flex-shrink: 0;
1310
+ display: flex;
1311
+ align-items: center;
1312
+ }
1313
+ .file-tree-icon sp-icon-folder,
1314
+ .file-tree-icon sp-icon-folder-open,
1315
+ .file-tree-icon sp-icon-document,
1316
+ .file-tree-icon sp-icon-file-code,
1317
+ .file-tree-icon sp-icon-file-txt,
1318
+ .file-tree-icon sp-icon-file-css,
1319
+ .file-tree-icon sp-icon-image {
1320
+ --spectrum-icon-size-100: 16px;
1321
+ }
1322
+ .file-tree-name {
1323
+ overflow: hidden;
1324
+ text-overflow: ellipsis;
1325
+ white-space: nowrap;
1326
+ flex: 1;
1327
+ }
1328
+ .file-tree-empty {
1329
+ padding: 24px;
1330
+ text-align: center;
1331
+ color: var(--fg-dim);
1332
+ font-size: var(--spectrum-font-size-75, 12px);
1333
+ }
1334
+ .project-header {
1335
+ display: flex;
1336
+ align-items: center;
1337
+ padding: 6px 12px;
1338
+ border-bottom: 1px solid var(--border);
1339
+ gap: 6px;
1340
+ }
1341
+ .project-name {
1342
+ font-size: var(--spectrum-font-size-75, 12px);
1343
+ font-weight: 600;
1344
+ overflow: hidden;
1345
+ text-overflow: ellipsis;
1346
+ white-space: nowrap;
1347
+ }
1348
+
1349
+ /* ─── Layers ─────────────────────────────────── */
1350
+ .layer-row {
1351
+ display: flex;
1352
+ align-items: center;
1353
+ gap: 4px;
1354
+ padding: 3px 8px;
1355
+ cursor: grab;
1356
+ white-space: nowrap;
1357
+ user-select: none;
1358
+ border-left: 2px solid transparent;
1359
+ transition: transform 150ms ease;
1360
+ }
1361
+ .layer-row:hover {
1362
+ background: var(--hover-bg);
1363
+ }
1364
+ .layer-row.selected {
1365
+ background: var(--accent-20);
1366
+ border-left-color: var(--accent);
1367
+ }
1368
+ .layer-row.dragging {
1369
+ opacity: 0.4;
1370
+ transition: none;
1371
+ }
1372
+ .layer-row.drop-target {
1373
+ background: var(--accent-15);
1374
+ outline: 1px dashed var(--accent);
1375
+ outline-offset: -1px;
1376
+ }
1377
+ .layer-indent {
1378
+ flex-shrink: 0;
1379
+ }
1380
+ .layer-actions {
1381
+ display: none;
1382
+ align-items: center;
1383
+ gap: 0;
1384
+ }
1385
+ .layer-row:hover .layer-actions {
1386
+ display: flex;
1387
+ }
1388
+ .layer-row:has(.layer-title-input) .layer-actions {
1389
+ display: none;
1390
+ }
1391
+ .layer-drag-handle {
1392
+ color: var(--fg-dim);
1393
+ opacity: 0.6;
1394
+ font-size: var(--spectrum-font-size-50, 11px);
1395
+ cursor: grab;
1396
+ padding: 0 4px 0 0;
1397
+ }
1398
+ .layer-toggle {
1399
+ width: 14px;
1400
+ text-align: center;
1401
+ font-size: 9px;
1402
+ color: var(--fg-dim);
1403
+ cursor: pointer;
1404
+ flex-shrink: 0;
1405
+ }
1406
+ .layer-tag {
1407
+ padding: 0 4px;
1408
+ font-size: 10px;
1409
+ border-radius: var(--spectrum-corner-radius-75, 2px);
1410
+ color: var(--accent-fg);
1411
+ background: var(--tag);
1412
+ flex-shrink: 0;
1413
+ }
1414
+ .layer-label {
1415
+ overflow: hidden;
1416
+ text-overflow: ellipsis;
1417
+ white-space: nowrap;
1418
+ min-width: 24px;
1419
+ flex: 1;
1420
+ }
1421
+ .layer-title-input {
1422
+ width: 100%;
1423
+ background: var(--bg);
1424
+ color: inherit;
1425
+ border: 1px solid var(--accent, #3b82f6);
1426
+ border-radius: var(--spectrum-corner-radius-75, 2px);
1427
+ font: inherit;
1428
+ font-size: inherit;
1429
+ padding: 0 2px;
1430
+ outline: none;
1431
+ }
1432
+ .layer-dot {
1433
+ font-size: 9px;
1434
+ flex-shrink: 0;
1435
+ }
1436
+ .layer-delete {
1437
+ color: var(--danger);
1438
+ }
1439
+ .map-tag {
1440
+ background: var(--map) !important;
1441
+ color: var(--accent-fg) !important;
1442
+ font-size: 9px;
1443
+ letter-spacing: 0.5px;
1444
+ }
1445
+ .repeater-perimeter {
1446
+ border: 1px dashed color-mix(in srgb, var(--map) 25%, transparent);
1447
+ border-radius: var(--radius);
1448
+ padding: 4px;
1449
+ min-height: 24px;
1450
+ position: relative;
1451
+ }
1452
+ .repeater-perimeter::before {
1453
+ content: "↻ Repeater";
1454
+ position: absolute;
1455
+ top: -9px;
1456
+ left: 6px;
1457
+ font-size: 9px;
1458
+ color: color-mix(in srgb, var(--map) 50%, transparent);
1459
+ background: var(--spectrum-white, #fff);
1460
+ padding: 0 3px;
1461
+ font-family: var(--font-mono);
1462
+ pointer-events: none;
1463
+ }
1464
+ /* Empty element placeholders (design/edit mode only) */
1465
+ .empty-media-placeholder {
1466
+ display: inline-block;
1467
+ min-width: 120px;
1468
+ min-height: 80px;
1469
+ border: 1px dashed color-mix(in srgb, var(--fg-dim, #808080) 30%, transparent);
1470
+ border-radius: var(--radius);
1471
+ background: color-mix(in srgb, var(--fg-dim, #808080) 5%, transparent)
1472
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40' fill='none'%3E%3Crect x='4' y='8' width='32' height='24' rx='2' stroke='%23808080' stroke-opacity='.4' stroke-width='1.5'/%3E%3Ccircle cx='13' cy='16' r='3' stroke='%23808080' stroke-opacity='.4' stroke-width='1.5'/%3E%3Cpath d='M8 28l8-8 5 5 4-4 7 7' stroke='%23808080' stroke-opacity='.4' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E")
1473
+ center / 40px no-repeat;
1474
+ color: transparent;
1475
+ font-size: 0;
1476
+ overflow: hidden;
1477
+ }
1478
+ .empty-text-placeholder:not([contenteditable])::after {
1479
+ content: "Click here to add text...";
1480
+ color: color-mix(in srgb, var(--fg-dim, #808080) 40%, transparent);
1481
+ font-style: italic;
1482
+ font-size: 13px;
1483
+ pointer-events: none;
1484
+ }
1485
+ .empty-container-placeholder {
1486
+ border: 1px dashed color-mix(in srgb, var(--fg-dim, #808080) 25%, transparent);
1487
+ border-radius: var(--radius);
1488
+ min-height: 32px;
1489
+ position: relative;
1490
+ }
1491
+ .empty-container-placeholder::after {
1492
+ content: "Drag elements here...";
1493
+ position: absolute;
1494
+ top: 50%;
1495
+ left: 50%;
1496
+ transform: translate(-50%, -50%);
1497
+ color: color-mix(in srgb, var(--fg-dim, #808080) 40%, transparent);
1498
+ font-style: italic;
1499
+ font-size: var(--spectrum-font-size-50, 11px);
1500
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
1501
+ pointer-events: none;
1502
+ white-space: nowrap;
1503
+ }
1504
+ [contenteditable="plaintext-only"]:focus {
1505
+ outline: 1px solid var(--accent) !important;
1506
+ outline-offset: -1px;
1507
+ }
1508
+ .switch-tag {
1509
+ background: var(--switch-c) !important;
1510
+ color: var(--accent-fg) !important;
1511
+ }
1512
+ .case-tag {
1513
+ background: var(--case-c) !important;
1514
+ color: var(--accent-fg) !important;
1515
+ font-style: italic;
1516
+ font-size: 9px;
1517
+ max-width: 60px;
1518
+ overflow: hidden;
1519
+ text-overflow: ellipsis;
1520
+ }
1521
+ .slot-tag {
1522
+ background: var(--slot-c) !important;
1523
+ color: var(--accent-fg) !important;
1524
+ }
1525
+ .component-row {
1526
+ opacity: 0.9;
1527
+ cursor: grab;
1528
+ }
1529
+ .component-row.available {
1530
+ opacity: 0.6;
1531
+ }
1532
+ .component-row.available:hover {
1533
+ opacity: 0.8;
1534
+ }
1535
+ .component-tag {
1536
+ font-size: 9px;
1537
+ width: 18px;
1538
+ text-align: center;
1539
+ }
1540
+ .components-section {
1541
+ padding: 0 0 2px;
1542
+ }
1543
+ .imports-panel {
1544
+ overflow-y: auto;
1545
+ padding: 4px;
1546
+ }
1547
+ .imports-section {
1548
+ margin-bottom: 12px;
1549
+ }
1550
+ .imports-section-header {
1551
+ display: flex;
1552
+ align-items: center;
1553
+ gap: 6px;
1554
+ padding: 6px 8px 2px;
1555
+ font-size: var(--spectrum-font-size-50, 11px);
1556
+ font-weight: 600;
1557
+ color: var(--fg-dim);
1558
+ text-transform: uppercase;
1559
+ letter-spacing: 0.5px;
1560
+ }
1561
+ .imports-count {
1562
+ font-weight: 400;
1563
+ color: var(--text-hint);
1564
+ }
1565
+ .imports-list {
1566
+ padding: 0 4px;
1567
+ }
1568
+ .import-row {
1569
+ display: flex;
1570
+ align-items: center;
1571
+ gap: 4px;
1572
+ padding: 3px 4px;
1573
+ font-size: var(--spectrum-font-size-50, 11px);
1574
+ border-radius: var(--radius);
1575
+ }
1576
+ .import-row:hover {
1577
+ background: var(--hover-bg);
1578
+ }
1579
+ .import-name {
1580
+ font-weight: 500;
1581
+ white-space: nowrap;
1582
+ }
1583
+ .import-path {
1584
+ color: var(--fg-dim);
1585
+ overflow: hidden;
1586
+ text-overflow: ellipsis;
1587
+ flex: 1;
1588
+ white-space: nowrap;
1589
+ font-family: var(--font-mono, monospace);
1590
+ font-size: 10px;
1591
+ }
1592
+ .import-mono {
1593
+ font-family: var(--font-mono, monospace);
1594
+ }
1595
+ .imports-empty {
1596
+ padding: 8px 12px;
1597
+ font-size: var(--spectrum-font-size-50, 11px);
1598
+ color: var(--text-hint);
1599
+ font-style: italic;
1600
+ }
1601
+ .import-add-form {
1602
+ display: flex;
1603
+ align-items: center;
1604
+ gap: 4px;
1605
+ padding: 4px;
1606
+ }
1607
+ .import-add-form sp-textfield {
1608
+ flex: 1;
1609
+ }
1610
+ .import-picker {
1611
+ width: 100%;
1612
+ }
1613
+ /* Head panel */
1614
+ .head-section-body {
1615
+ padding: 0 4px;
1616
+ }
1617
+ .head-section-body .style-row > sp-textfield,
1618
+ .head-section-body .style-row > .media-picker {
1619
+ width: 100%;
1620
+ }
1621
+ .head-add-form {
1622
+ display: flex;
1623
+ align-items: center;
1624
+ gap: 4px;
1625
+ padding: 4px;
1626
+ }
1627
+ .head-add-form sp-textfield {
1628
+ flex: 1;
1629
+ }
1630
+ .head-add-form sp-picker {
1631
+ min-width: 70px;
1632
+ }
1633
+ .breadcrumb {
1634
+ display: flex;
1635
+ align-items: center;
1636
+ gap: 2px;
1637
+ font-size: var(--spectrum-font-size-50, 11px);
1638
+ margin-left: 8px;
1639
+ }
1640
+ .breadcrumb-item {
1641
+ color: var(--fg-dim);
1642
+ cursor: default;
1643
+ white-space: nowrap;
1644
+ }
1645
+ .breadcrumb-item.clickable {
1646
+ cursor: pointer;
1647
+ }
1648
+ .breadcrumb-item.clickable:hover {
1649
+ color: var(--fg);
1650
+ text-decoration: underline;
1651
+ }
1652
+ .breadcrumb-item.current {
1653
+ color: var(--fg);
1654
+ font-weight: 600;
1655
+ }
1656
+ .breadcrumb-sep {
1657
+ color: var(--fg-dim);
1658
+ }
1659
+ .element-card {
1660
+ cursor: grab;
1661
+ display: flex;
1662
+ flex-direction: column;
1663
+ width: 100%;
1664
+ border: 1px solid var(--border);
1665
+ border-radius: var(--radius);
1666
+ overflow: hidden;
1667
+ margin-bottom: 6px;
1668
+ }
1669
+ .element-card:hover {
1670
+ border-color: var(--accent);
1671
+ }
1672
+ .element-card-preview {
1673
+ background: var(--spectrum-white, #fff);
1674
+ padding: 6px 8px;
1675
+ min-height: 32px;
1676
+ max-height: 120px;
1677
+ display: flex;
1678
+ align-items: center;
1679
+ overflow: hidden;
1680
+ pointer-events: none;
1681
+ }
1682
+ .element-card-preview > * {
1683
+ max-width: 100%;
1684
+ color: var(--canvas-fg-2);
1685
+ margin: 0;
1686
+ padding: 0;
1687
+ }
1688
+ .element-card-preview > hr {
1689
+ width: 100%;
1690
+ border: none;
1691
+ border-top: 1px solid var(--canvas-muted);
1692
+ }
1693
+ .element-card-preview > input,
1694
+ .element-card-preview > textarea,
1695
+ .element-card-preview > select,
1696
+ .element-card-preview > button,
1697
+ .element-card-preview > progress,
1698
+ .element-card-preview > meter {
1699
+ font-size: 10px;
1700
+ }
1701
+ .element-card-label {
1702
+ padding: 2px 6px;
1703
+ font-size: 10px;
1704
+ color: var(--fg-dim);
1705
+ background: var(--bg-input);
1706
+ text-align: center;
1707
+ font-family: var(--font-mono);
1708
+ }
1709
+ .elements-list {
1710
+ border: none;
1711
+ }
1712
+ .elements-list sp-accordion-item {
1713
+ --spectrum-accordion-item-header-font-size: var(--spectrum-font-size-50, 11px);
1714
+ border-bottom: 1px solid var(--border);
1715
+ }
1716
+
1717
+ /* ─── Drop indicator ──────────────────────────── */
1718
+ .drop-indicator {
1719
+ display: none;
1720
+ position: absolute;
1721
+ height: 2px;
1722
+ background: var(--accent);
1723
+ z-index: 5;
1724
+ pointer-events: none;
1725
+ }
1726
+
1727
+ /* ─── Canvas drop indicator ───────────────────── */
1728
+ .canvas-drop-indicator {
1729
+ position: absolute;
1730
+ pointer-events: none;
1731
+ z-index: 11;
1732
+ }
1733
+ .canvas-drop-indicator.line {
1734
+ height: 2px;
1735
+ background: var(--accent);
1736
+ }
1737
+ .canvas-drop-indicator.inside {
1738
+ border: 2px dashed var(--accent);
1739
+ background: var(--accent-8);
1740
+ }
1741
+
1742
+ /* ─── Git diff highlighting ──────────────────── */
1743
+ .element-diff-added {
1744
+ background-color: color-mix(in srgb, var(--success) 15%, transparent);
1745
+ outline: 1px solid var(--success);
1746
+ }
1747
+ .element-diff-removed {
1748
+ background-color: color-mix(in srgb, var(--danger) 15%, transparent);
1749
+ outline: 1px solid var(--danger);
1750
+ }
1751
+ .element-diff-modified {
1752
+ background-color: color-mix(in srgb, var(--signal) 15%, transparent);
1753
+ outline: 1px solid var(--signal);
1754
+ }
1755
+
1756
+ /* ─── Insertion helper ─────────────────────────── */
1757
+ .insertion-helper {
1758
+ position: absolute;
1759
+ position-anchor: --jx-insert;
1760
+ z-index: 12;
1761
+ pointer-events: auto;
1762
+ width: 20px;
1763
+ height: 20px;
1764
+ border-radius: 50%;
1765
+ border: 1.5px solid var(--accent);
1766
+ background: var(--bg-panel);
1767
+ color: var(--accent);
1768
+ font-size: var(--spectrum-font-size-100, 14px);
1769
+ font-weight: 500;
1770
+ line-height: 1;
1771
+ cursor: pointer;
1772
+ display: none;
1773
+ place-items: center;
1774
+ padding: 0;
1775
+ opacity: 0;
1776
+ transition: opacity 0.15s ease;
1777
+ }
1778
+ .insertion-helper.visible {
1779
+ display: grid;
1780
+ opacity: 1;
1781
+ }
1782
+ .insertion-helper:hover {
1783
+ background: var(--accent);
1784
+ color: var(--accent-fg);
1785
+ transform: scale(1.15);
1786
+ }
1787
+ /* Line pseudo element — extends beyond button as a visual cue */
1788
+ .insertion-helper::before {
1789
+ content: "";
1790
+ position: absolute;
1791
+ background: var(--accent);
1792
+ opacity: 0.5;
1793
+ pointer-events: none;
1794
+ border-radius: 1px;
1795
+ }
1796
+ /* Horizontal edges (column / block layout) */
1797
+ .insertion-helper[data-edge="top"],
1798
+ .insertion-helper[data-edge="bottom"] {
1799
+ left: anchor(center);
1800
+ translate: -50% 0;
1801
+ }
1802
+ .insertion-helper[data-edge="top"] {
1803
+ bottom: anchor(top);
1804
+ translate: -50% 50%;
1805
+ }
1806
+ .insertion-helper[data-edge="bottom"] {
1807
+ top: anchor(bottom);
1808
+ translate: -50% -50%;
1809
+ }
1810
+ .insertion-helper[data-edge="top"]::before,
1811
+ .insertion-helper[data-edge="bottom"]::before {
1812
+ width: 80px;
1813
+ height: 2px;
1814
+ top: 50%;
1815
+ left: 50%;
1816
+ translate: -50% -50%;
1817
+ z-index: -1;
1818
+ }
1819
+ /* Vertical edges (row / inline layout) */
1820
+ .insertion-helper[data-edge="left"],
1821
+ .insertion-helper[data-edge="right"] {
1822
+ top: anchor(center);
1823
+ translate: 0 -50%;
1824
+ }
1825
+ .insertion-helper[data-edge="left"] {
1826
+ right: anchor(left);
1827
+ translate: 50% -50%;
1828
+ }
1829
+ .insertion-helper[data-edge="right"] {
1830
+ left: anchor(right);
1831
+ translate: -50% -50%;
1832
+ }
1833
+ .insertion-helper[data-edge="left"]::before,
1834
+ .insertion-helper[data-edge="right"]::before {
1835
+ height: 80px;
1836
+ width: 2px;
1837
+ top: 50%;
1838
+ left: 50%;
1839
+ translate: -50% -50%;
1840
+ z-index: -1;
1841
+ }
1842
+ /* Empty container center */
1843
+ .insertion-helper[data-edge="center"] {
1844
+ top: anchor(center);
1845
+ left: anchor(center);
1846
+ translate: -50% -50%;
1847
+ }
1848
+
1849
+ /* ─── Inspector ──────────────────────────────── */
1850
+ .inspector-fields {
1851
+ padding: 4px 8px 8px;
1852
+ }
1853
+ .inspector-fields.hidden {
1854
+ display: none;
1855
+ }
1856
+ .field-row {
1857
+ display: flex;
1858
+ align-items: center;
1859
+ gap: 6px;
1860
+ margin-bottom: 4px;
1861
+ }
1862
+ .field-label {
1863
+ width: 80px;
1864
+ flex-shrink: 0;
1865
+ font-size: var(--spectrum-font-size-50, 11px);
1866
+ color: var(--fg-dim);
1867
+ text-align: right;
1868
+ overflow: hidden;
1869
+ text-overflow: ellipsis;
1870
+ white-space: nowrap;
1871
+ }
1872
+ .field-input {
1873
+ flex: 1;
1874
+ min-width: 0;
1875
+ padding: 3px 6px;
1876
+ font: inherit;
1877
+ font-size: var(--spectrum-font-size-50, 11px);
1878
+ color: var(--fg);
1879
+ background: var(--bg-input);
1880
+ border: 1px solid var(--border);
1881
+ border-radius: var(--radius);
1882
+ outline: none;
1883
+ }
1884
+ .field-input:focus {
1885
+ border-color: var(--accent);
1886
+ }
1887
+ .field-input[type="checkbox"] {
1888
+ width: auto;
1889
+ flex: none;
1890
+ }
1891
+ textarea.field-input {
1892
+ resize: vertical;
1893
+ min-height: 60px;
1894
+ font-family: var(--font-mono);
1895
+ }
1896
+ /* Spectrum components inside field rows */
1897
+ .field-row sp-textfield,
1898
+ .field-row sp-picker {
1899
+ flex: 1;
1900
+ min-width: 0;
1901
+ }
1902
+ .field-row sp-textfield {
1903
+ --spectrum-textfield-height: 26px;
1904
+ }
1905
+ .field-row sp-picker {
1906
+ --spectrum-picker-min-width: 0;
1907
+ }
1908
+ .field-row sp-checkbox {
1909
+ flex: none;
1910
+ }
1911
+ .field-row sp-field-label {
1912
+ width: 80px;
1913
+ flex-shrink: 0;
1914
+ font-size: var(--spectrum-font-size-50, 11px);
1915
+ color: var(--fg-dim);
1916
+ text-align: right;
1917
+ }
1918
+ .signal-editor .field-row sp-field-label {
1919
+ width: 65px;
1920
+ font-size: 10px;
1921
+ }
1922
+ .signal-editor .field-row sp-textfield {
1923
+ --spectrum-textfield-height: 24px;
1924
+ }
1925
+
1926
+ /* ─── Style editor (key-value list) ──────────── */
1927
+ .kv-row {
1928
+ display: flex;
1929
+ gap: 4px;
1930
+ margin-bottom: 3px;
1931
+ }
1932
+ .kv-key {
1933
+ width: 90px;
1934
+ flex-shrink: 0;
1935
+ }
1936
+ .kv-val {
1937
+ flex: 1;
1938
+ min-width: 0;
1939
+ }
1940
+ .kv-del {
1941
+ width: 20px;
1942
+ text-align: center;
1943
+ cursor: pointer;
1944
+ color: var(--danger);
1945
+ font-size: 13px;
1946
+ line-height: 24px;
1947
+ }
1948
+ .kv-add {
1949
+ display: inline-block;
1950
+ padding: 2px 8px;
1951
+ font-size: var(--spectrum-font-size-50, 11px);
1952
+ cursor: pointer;
1953
+ color: var(--accent);
1954
+ }
1955
+ .kv-add:hover {
1956
+ text-decoration: underline;
1957
+ }
1958
+
1959
+ /* ─── Style sidebar (Spectrum accordion) ──────── */
1960
+ .style-sidebar sp-accordion {
1961
+ border: none;
1962
+ }
1963
+ .style-sidebar sp-accordion-item {
1964
+ --spectrum-accordion-item-header-font-size: var(--spectrum-font-size-50, 11px);
1965
+ }
1966
+ .style-sidebar sp-accordion-item [slot="heading"] {
1967
+ display: flex;
1968
+ align-items: center;
1969
+ gap: 4px;
1970
+ }
1971
+ .style-row {
1972
+ display: flex;
1973
+ flex-direction: column;
1974
+ align-items: stretch;
1975
+ gap: 2px;
1976
+ padding: 2px 0;
1977
+ }
1978
+ .style-row--child {
1979
+ padding-left: 16px;
1980
+ }
1981
+ /* removed: .style-row--horizontal — all rows use top labels now */
1982
+ .style-row-label {
1983
+ display: flex;
1984
+ align-items: center;
1985
+ gap: 4px;
1986
+ font-size: 10px;
1987
+ color: var(--fg-dim);
1988
+ }
1989
+ .set-dot {
1990
+ display: inline-block;
1991
+ width: 6px;
1992
+ height: 6px;
1993
+ border-radius: 50%;
1994
+ background: var(--accent);
1995
+ cursor: pointer;
1996
+ flex-shrink: 0;
1997
+ vertical-align: middle;
1998
+ }
1999
+ .set-dot:hover {
2000
+ background: var(--danger);
2001
+ }
2002
+ .set-dot--section {
2003
+ width: 7px;
2004
+ height: 7px;
2005
+ }
2006
+ .style-row--warning .style-row-label {
2007
+ color: var(--warning);
2008
+ }
2009
+ .style-row--warning .style-row-label::before {
2010
+ content: "⚠ ";
2011
+ }
2012
+ .style-row > sp-textfield,
2013
+ .style-row > sp-number-field,
2014
+ .style-row > sp-picker,
2015
+ .style-row > sp-combobox,
2016
+ .style-row > textarea {
2017
+ width: 100%;
2018
+ }
2019
+ .style-input-color {
2020
+ display: flex;
2021
+ align-items: center;
2022
+ gap: 6px;
2023
+ flex: 1;
2024
+ min-width: 0;
2025
+ }
2026
+ .style-input-color sp-swatch {
2027
+ flex-shrink: 0;
2028
+ cursor: pointer;
2029
+ }
2030
+ .style-input-color sp-textfield {
2031
+ flex: 1;
2032
+ min-width: 0;
2033
+ }
2034
+ .color-popover-inner {
2035
+ display: flex;
2036
+ flex-direction: column;
2037
+ gap: 8px;
2038
+ width: 200px;
2039
+ overflow: hidden;
2040
+ }
2041
+ .color-popover-inner sp-textfield {
2042
+ width: 100%;
2043
+ }
2044
+ .color-popover-swatches-label {
2045
+ font-size: 10px;
2046
+ color: var(--spectrum-gray-600);
2047
+ text-transform: uppercase;
2048
+ letter-spacing: 0.05em;
2049
+ }
2050
+ .color-popover-inner sp-swatch-group {
2051
+ --mod-swatch-border-color: var(--spectrum-gray-400);
2052
+ }
2053
+ .font-token-item {
2054
+ display: flex;
2055
+ flex-direction: column;
2056
+ gap: 1px;
2057
+ }
2058
+ .font-token-preview {
2059
+ font-size: var(--spectrum-font-size-75, 12px);
2060
+ line-height: 1.3;
2061
+ }
2062
+ .font-token-name {
2063
+ font-size: 9px;
2064
+ color: var(--spectrum-gray-600);
2065
+ font-family: monospace;
2066
+ }
2067
+ /* jx-styled-combobox — dual-mode styled combobox component */
2068
+ jx-styled-combobox {
2069
+ display: contents;
2070
+ }
2071
+ jx-styled-combobox sp-picker {
2072
+ width: 100%;
2073
+ }
2074
+ .jx-combobox-group {
2075
+ display: inline-flex;
2076
+ position: relative;
2077
+ width: 100%;
2078
+ }
2079
+ .jx-combobox-group sp-textfield {
2080
+ flex: 1 1 auto;
2081
+ min-width: 0;
2082
+ --mod-textfield-border-start-end-radius: 0;
2083
+ --mod-textfield-border-end-end-radius: 0;
2084
+ margin-inline-end: calc(-1 * var(--spectrum-border-width-100, 1px));
2085
+ }
2086
+ .jx-combobox-group sp-picker-button {
2087
+ flex: 0 0 auto;
2088
+ --mod-picker-button-border-start-start-radius: 0;
2089
+ --mod-picker-button-border-end-start-radius: 0;
2090
+ --mod-picker-button-border-color: var(--spectrum-gray-400);
2091
+ }
2092
+ /* Number-unit compound input: textfield + picker-button */
2093
+ .style-input-number-unit {
2094
+ flex: 1;
2095
+ min-width: 0;
2096
+ }
2097
+ /* Combobox-like composite: textfield + picker-button, matching sp-combobox visually */
2098
+ .input-group {
2099
+ display: inline-flex;
2100
+ position: relative;
2101
+ width: 100%;
2102
+ }
2103
+ .input-group sp-textfield {
2104
+ flex: 1 1 auto;
2105
+ min-width: 0;
2106
+ /* Zero out the inline-end corners so the textfield abuts the picker-button */
2107
+ --mod-textfield-border-start-end-radius: 0;
2108
+ --mod-textfield-border-end-end-radius: 0;
2109
+ /* Pull textfield's border into the picker-button so they share one line */
2110
+ margin-inline-end: calc(-1 * var(--spectrum-border-width-100, 1px));
2111
+ }
2112
+ .input-group sp-picker-button {
2113
+ flex: 0 0 auto;
2114
+ /* Zero out the inline-start corners to abut the textfield */
2115
+ --mod-picker-button-border-start-start-radius: 0;
2116
+ --mod-picker-button-border-end-start-radius: 0;
2117
+ --mod-picker-button-border-color: var(--spectrum-gray-400);
2118
+ }
2119
+ .input-group.is-expression sp-picker-button {
2120
+ display: none;
2121
+ }
2122
+ .input-group.is-expression sp-textfield {
2123
+ --mod-textfield-text-color-default: var(--spectrum-accent-color-800);
2124
+ --mod-textfield-border-start-end-radius: var(--spectrum-corner-radius-100);
2125
+ --mod-textfield-border-end-end-radius: var(--spectrum-corner-radius-100);
2126
+ margin-inline-end: 0;
2127
+ }
2128
+ .style-shorthand-header {
2129
+ display: flex;
2130
+ align-items: center;
2131
+ gap: 4px;
2132
+ }
2133
+ .style-shorthand-header sp-textfield {
2134
+ flex: 1;
2135
+ min-width: 0;
2136
+ }
2137
+
2138
+ /* Button-group + overflow picker-button combo */
2139
+ .button-group-combo {
2140
+ display: inline-flex;
2141
+ align-items: stretch;
2142
+ }
2143
+ .button-group-combo.has-overflow sp-action-group {
2144
+ --mod-actionbutton-border-radius: 0;
2145
+ }
2146
+ .button-group-combo sp-picker-button {
2147
+ flex: 0 0 auto;
2148
+ --mod-picker-button-border-start-start-radius: 0;
2149
+ --mod-picker-button-border-end-start-radius: 0;
2150
+ --mod-picker-button-border-color: var(--spectrum-gray-400);
2151
+ margin-inline-start: calc(-1 * var(--spectrum-border-width-100, 1px));
2152
+ }
2153
+ .button-group-combo sp-picker-button.has-selection {
2154
+ --mod-picker-button-background-color: var(--spectrum-accent-background-color-default);
2155
+ }
2156
+
2157
+ /* ─── Grid section layout (Size panel) ─── */
2158
+ .style-section-body--grid {
2159
+ display: grid;
2160
+ grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
2161
+ gap: 6px 8px;
2162
+ }
2163
+ .style-section-body--grid .style-row {
2164
+ min-width: 0;
2165
+ overflow: hidden;
2166
+ }
2167
+
2168
+ /* ─── Signals tab ────────────────────────────── */
2169
+ .signal-row {
2170
+ display: flex;
2171
+ align-items: center;
2172
+ gap: 4px;
2173
+ padding: 4px 8px;
2174
+ cursor: pointer;
2175
+ border-left: 2px solid transparent;
2176
+ user-select: none;
2177
+ }
2178
+ .signal-row:hover {
2179
+ background: var(--hover-bg);
2180
+ }
2181
+ .signal-row.expanded {
2182
+ background: var(--accent-10);
2183
+ border-left-color: var(--accent);
2184
+ }
2185
+ .signal-badge {
2186
+ padding: 0 4px;
2187
+ font-size: 10px;
2188
+ border-radius: var(--spectrum-corner-radius-75, 2px);
2189
+ font-weight: 600;
2190
+ flex-shrink: 0;
2191
+ min-width: 18px;
2192
+ text-align: center;
2193
+ }
2194
+ .signal-badge.state {
2195
+ background: color-mix(in srgb, var(--signal) 25%, transparent);
2196
+ color: var(--signal);
2197
+ }
2198
+ .signal-badge.computed {
2199
+ background: color-mix(in srgb, var(--success) 25%, transparent);
2200
+ color: var(--success);
2201
+ }
2202
+ .signal-badge.data {
2203
+ background: color-mix(in srgb, var(--tag) 25%, transparent);
2204
+ color: var(--tag);
2205
+ }
2206
+ .signal-badge.handler {
2207
+ background: color-mix(in srgb, var(--handler) 25%, transparent);
2208
+ color: var(--handler);
2209
+ }
2210
+ .signal-name {
2211
+ flex: 1;
2212
+ font-family: var(--font-mono);
2213
+ font-size: var(--spectrum-font-size-50, 11px);
2214
+ overflow: hidden;
2215
+ text-overflow: ellipsis;
2216
+ }
2217
+ .signal-hint {
2218
+ font-size: 10px;
2219
+ color: var(--fg-dim);
2220
+ flex-shrink: 0;
2221
+ max-width: 80px;
2222
+ overflow: hidden;
2223
+ text-overflow: ellipsis;
2224
+ }
2225
+ .signal-del {
2226
+ visibility: hidden;
2227
+ cursor: pointer;
2228
+ color: var(--danger);
2229
+ font-size: var(--spectrum-font-size-50, 11px);
2230
+ flex-shrink: 0;
2231
+ }
2232
+ .signal-row:hover .signal-del {
2233
+ visibility: visible;
2234
+ }
2235
+ .signal-editor {
2236
+ padding: 4px 8px 8px 26px;
2237
+ border-bottom: 1px solid var(--border);
2238
+ }
2239
+ /* Signals panel accordion (matches style-sidebar pattern) */
2240
+ .signals-panel sp-accordion {
2241
+ border: none;
2242
+ }
2243
+ .signals-panel sp-accordion-item {
2244
+ --spectrum-accordion-item-header-font-size: var(--spectrum-font-size-50, 11px);
2245
+ }
2246
+ .signals-add {
2247
+ display: flex;
2248
+ align-items: center;
2249
+ gap: 4px;
2250
+ padding: 6px 8px;
2251
+ }
2252
+
2253
+ /* ─── Data explorer ──────────────────────────── */
2254
+ .data-explorer-toolbar {
2255
+ padding: 4px 8px;
2256
+ border-bottom: 1px solid var(--border);
2257
+ display: flex;
2258
+ justify-content: flex-end;
2259
+ }
2260
+ .data-refresh-btn {
2261
+ font-size: var(--spectrum-font-size-50, 11px);
2262
+ padding: 2px 8px;
2263
+ background: var(--bg-input);
2264
+ border: 1px solid var(--border);
2265
+ border-radius: var(--radius);
2266
+ color: var(--fg);
2267
+ cursor: pointer;
2268
+ }
2269
+ .data-refresh-btn:hover {
2270
+ border-color: var(--accent);
2271
+ }
2272
+ .data-row {
2273
+ border-bottom: 1px solid var(--border);
2274
+ }
2275
+ .data-row-header {
2276
+ display: flex;
2277
+ align-items: center;
2278
+ gap: 4px;
2279
+ padding: 4px 8px;
2280
+ cursor: pointer;
2281
+ user-select: none;
2282
+ }
2283
+ .data-row-header:hover {
2284
+ background: var(--hover-bg);
2285
+ }
2286
+ .data-row-header::before {
2287
+ content: "\25B6";
2288
+ font-size: 8px;
2289
+ color: var(--fg-dim);
2290
+ transition: transform 0.15s;
2291
+ }
2292
+ .data-row-header.expanded::before {
2293
+ transform: rotate(90deg);
2294
+ }
2295
+ .data-name {
2296
+ flex: 1;
2297
+ font-family: var(--font-mono, monospace);
2298
+ font-size: var(--spectrum-font-size-50, 11px);
2299
+ overflow: hidden;
2300
+ text-overflow: ellipsis;
2301
+ white-space: nowrap;
2302
+ }
2303
+ .data-type {
2304
+ font-size: 10px;
2305
+ color: var(--fg-dim);
2306
+ flex-shrink: 0;
2307
+ }
2308
+ .data-tree {
2309
+ padding: 2px 0;
2310
+ max-height: 300px;
2311
+ overflow-y: auto;
2312
+ }
2313
+ .data-leaf,
2314
+ .data-branch {
2315
+ font-size: var(--spectrum-font-size-50, 11px);
2316
+ font-family: var(--font-mono, monospace);
2317
+ padding: 1px 8px;
2318
+ line-height: 1.5;
2319
+ white-space: nowrap;
2320
+ overflow: hidden;
2321
+ text-overflow: ellipsis;
2322
+ }
2323
+ .data-key {
2324
+ color: var(--data-key);
2325
+ }
2326
+ .data-value {
2327
+ color: var(--fg);
2328
+ }
2329
+ .data-null {
2330
+ color: var(--fg-dim);
2331
+ font-style: italic;
2332
+ }
2333
+ .data-string {
2334
+ color: var(--data-string);
2335
+ }
2336
+ .data-number {
2337
+ color: var(--data-number);
2338
+ }
2339
+ .data-boolean {
2340
+ color: var(--data-boolean);
2341
+ }
2342
+ .data-object-label {
2343
+ color: var(--fg-dim);
2344
+ font-style: italic;
2345
+ }
2346
+ .data-ellipsis {
2347
+ color: var(--fg-dim);
2348
+ font-style: italic;
2349
+ }
2350
+ .data-pending {
2351
+ animation: pulse 1.5s ease-in-out infinite;
2352
+ }
2353
+ @keyframes pulse {
2354
+ 0%,
2355
+ 100% {
2356
+ opacity: 1;
2357
+ }
2358
+ 50% {
2359
+ opacity: 0.4;
2360
+ }
2361
+ }
2362
+ .field-check {
2363
+ width: auto;
2364
+ margin: 0;
2365
+ }
2366
+
2367
+ /* ─── Binding toggle ─────────────────────────── */
2368
+ .bind-toggle {
2369
+ width: 20px;
2370
+ height: 20px;
2371
+ display: flex;
2372
+ align-items: center;
2373
+ justify-content: center;
2374
+ font-size: var(--spectrum-font-size-50, 11px);
2375
+ cursor: pointer;
2376
+ color: var(--fg-dim);
2377
+ border: 1px solid transparent;
2378
+ border-radius: var(--radius);
2379
+ flex-shrink: 0;
2380
+ }
2381
+ .bind-toggle:hover {
2382
+ color: var(--fg);
2383
+ background: var(--hover-bg);
2384
+ }
2385
+ .bind-toggle.bound {
2386
+ color: var(--accent);
2387
+ }
2388
+
2389
+ /* ─── Events section ─────────────────────────── */
2390
+ .events-panel {
2391
+ padding: 8px;
2392
+ }
2393
+ .events-section {
2394
+ margin-bottom: 8px;
2395
+ }
2396
+ .declared-event-row {
2397
+ display: flex;
2398
+ gap: 6px;
2399
+ align-items: center;
2400
+ padding: 2px 0;
2401
+ font-size: var(--spectrum-font-size-50, 11px);
2402
+ }
2403
+ .event-code {
2404
+ font-family: monospace;
2405
+ color: var(--accent);
2406
+ }
2407
+ .event-source {
2408
+ color: var(--fg-dim);
2409
+ font-size: 10px;
2410
+ }
2411
+ .event-type {
2412
+ margin-left: auto;
2413
+ color: var(--fg-dim);
2414
+ font-size: 10px;
2415
+ }
2416
+ .event-binding {
2417
+ margin-bottom: 8px;
2418
+ }
2419
+ .event-row {
2420
+ display: flex;
2421
+ gap: 4px;
2422
+ align-items: center;
2423
+ }
2424
+ .event-name {
2425
+ flex: 1;
2426
+ min-width: 0;
2427
+ }
2428
+ .event-mode {
2429
+ width: 72px;
2430
+ flex-shrink: 0;
2431
+ }
2432
+ .event-handler {
2433
+ width: 100%;
2434
+ }
2435
+ .event-body-row {
2436
+ display: flex;
2437
+ gap: 4px;
2438
+ align-items: start;
2439
+ margin-top: 3px;
2440
+ }
2441
+ .event-body-row sp-textfield {
2442
+ flex: 1;
2443
+ font-size: var(--spectrum-font-size-50, 11px);
2444
+ }
2445
+
2446
+ /* ─── Toolbar ────────────────────────────────── */
2447
+ .tb-filename {
2448
+ font-size: var(--spectrum-font-size-50, 11px);
2449
+ color: var(--fg-dim);
2450
+ max-width: 200px;
2451
+ overflow: hidden;
2452
+ text-overflow: ellipsis;
2453
+ }
2454
+ .tb-file-title {
2455
+ font-size: var(--spectrum-font-size-50, 11px);
2456
+ color: var(--fg);
2457
+ max-width: 300px;
2458
+ overflow: hidden;
2459
+ text-overflow: ellipsis;
2460
+ white-space: nowrap;
2461
+ padding: 0 8px;
2462
+ font-family: var(--font-mono);
2463
+ }
2464
+ .tb-dirty {
2465
+ color: var(--accent);
2466
+ font-size: 16px;
2467
+ line-height: 1;
2468
+ margin-left: 4px;
2469
+ }
2470
+ .tb-split-btn {
2471
+ display: flex;
2472
+ }
2473
+ .tb-split-btn .tb-split-main {
2474
+ border-top-right-radius: 0;
2475
+ border-bottom-right-radius: 0;
2476
+ }
2477
+ .tb-split-btn .tb-split-trigger,
2478
+ .tb-split-btn overlay-trigger > sp-action-button {
2479
+ border-top-left-radius: 0;
2480
+ border-bottom-left-radius: 0;
2481
+ border-left: 1px solid rgba(0, 0, 0, 0.15);
2482
+ }
2483
+ .tb-spacer {
2484
+ flex: 1;
2485
+ }
2486
+ .tb-search-trigger {
2487
+ flex: 0 1 280px;
2488
+ border: 1px solid var(--spectrum-gray-300, #393939);
2489
+ border-radius: var(--radius);
2490
+ --mod-actionbutton-edge-to-text: 10px;
2491
+ }
2492
+ .tb-search-trigger:hover {
2493
+ border-color: var(--spectrum-gray-400, #4a4a4a);
2494
+ }
2495
+ .tb-search-label {
2496
+ flex: 1;
2497
+ text-align: left;
2498
+ color: var(--spectrum-gray-600, #666);
2499
+ font-weight: normal;
2500
+ font-size: var(--spectrum-font-size-75, 12px);
2501
+ }
2502
+ .tb-search-label kbd {
2503
+ font-family: inherit;
2504
+ opacity: 0.6;
2505
+ }
2506
+ /* ─── Responsive toolbar collapse ──────────────────
2507
+ As the window narrows the toolbar sheds width in two stages so the
2508
+ window controls and every action stay reachable instead of clipping:
2509
+ 1. the quick-access (file search) bar collapses to a search icon
2510
+ 2. every button drops its text label, leaving an icon (the `title`
2511
+ attribute supplies a tooltip with the full name)
2512
+ The breakpoints are the toolbar widths at which each fuller layout
2513
+ stops fitting (measured against the English labels); re-tune them if
2514
+ the toolbar's buttons or labels change. */
2515
+ @container toolbar (max-width: 1360px) {
2516
+ .tb-search-trigger {
2517
+ flex: 0 0 auto;
2518
+ gap: 0;
2519
+ }
2520
+ .tb-search-label {
2521
+ display: none;
2522
+ }
2523
+ }
2524
+ @container toolbar (max-width: 1140px) {
2525
+ #toolbar .tb-label {
2526
+ display: none;
2527
+ }
2528
+ /* Collapse the icon-to-(now hidden)-label gap so buttons read as icons. */
2529
+ #toolbar sp-action-button {
2530
+ gap: 0;
2531
+ }
2532
+ }
2533
+ .quick-search-overlay {
2534
+ position: fixed;
2535
+ inset: 0;
2536
+ z-index: 1000;
2537
+ display: flex;
2538
+ justify-content: center;
2539
+ padding-top: 60px;
2540
+ background: rgba(0, 0, 0, 0.4);
2541
+ }
2542
+ .quick-search-panel {
2543
+ width: 560px;
2544
+ max-height: 420px;
2545
+ display: flex;
2546
+ flex-direction: column;
2547
+ background: var(--spectrum-gray-100, #1e1e1e);
2548
+ border: 1px solid var(--spectrum-gray-300, #393939);
2549
+ border-radius: var(--spectrum-corner-radius-200, 8px);
2550
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
2551
+ overflow: hidden;
2552
+ align-self: flex-start;
2553
+ }
2554
+ .quick-search-input {
2555
+ width: 100%;
2556
+ padding: 12px 16px;
2557
+ font-size: var(--spectrum-font-size-100, 14px);
2558
+ border: none;
2559
+ outline: none;
2560
+ background: var(--spectrum-gray-75, #141414);
2561
+ color: var(--spectrum-gray-900, #e0e0e0);
2562
+ border-bottom: 1px solid var(--spectrum-gray-300, #393939);
2563
+ }
2564
+ .quick-search-results {
2565
+ overflow-y: auto;
2566
+ flex: 1;
2567
+ }
2568
+ .quick-search-item {
2569
+ display: flex;
2570
+ align-items: center;
2571
+ gap: 8px;
2572
+ padding: 6px 16px;
2573
+ cursor: pointer;
2574
+ font-size: 13px;
2575
+ color: var(--spectrum-gray-800, #ccc);
2576
+ }
2577
+ .quick-search-item.selected {
2578
+ background: var(--spectrum-blue-700, #0054a3);
2579
+ color: var(--spectrum-white, #fff);
2580
+ }
2581
+ .quick-search-item:hover:not(.selected) {
2582
+ background: var(--spectrum-gray-200, #2a2a2a);
2583
+ }
2584
+ .quick-search-icon {
2585
+ flex-shrink: 0;
2586
+ opacity: 0.7;
2587
+ }
2588
+ .quick-search-name {
2589
+ font-weight: 500;
2590
+ white-space: nowrap;
2591
+ }
2592
+ .quick-search-path {
2593
+ opacity: 0.5;
2594
+ font-size: var(--spectrum-font-size-75, 12px);
2595
+ white-space: nowrap;
2596
+ overflow: hidden;
2597
+ text-overflow: ellipsis;
2598
+ }
2599
+ .quick-search-badge {
2600
+ margin-left: auto;
2601
+ font-size: var(--spectrum-font-size-50, 11px);
2602
+ padding: 1px 6px;
2603
+ border-radius: var(--radius);
2604
+ background: var(--spectrum-gray-300, #393939);
2605
+ color: var(--spectrum-gray-700, #999);
2606
+ }
2607
+ .quick-search-empty {
2608
+ padding: 16px;
2609
+ text-align: center;
2610
+ color: var(--spectrum-gray-600, #666);
2611
+ font-size: 13px;
2612
+ }
2613
+ .quick-search-section-label {
2614
+ padding: 8px 16px 4px;
2615
+ font-size: var(--spectrum-font-size-50, 11px);
2616
+ text-transform: uppercase;
2617
+ color: var(--spectrum-gray-600, #666);
2618
+ letter-spacing: 0.5px;
2619
+ }
2620
+
2621
+ /* ─── Browse modal ──────────────────────────────── */
2622
+ .browse-modal {
2623
+ position: fixed;
2624
+ inset: 40px;
2625
+ z-index: 1000;
2626
+ display: flex;
2627
+ flex-direction: column;
2628
+ background: var(--bg-panel);
2629
+ border: 1px solid var(--border);
2630
+ border-radius: var(--spectrum-corner-radius-200, 8px);
2631
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
2632
+ overflow: hidden;
2633
+ }
2634
+ .browse-modal-header {
2635
+ display: flex;
2636
+ align-items: center;
2637
+ justify-content: space-between;
2638
+ padding: 12px 16px;
2639
+ border-bottom: 1px solid var(--border);
2640
+ }
2641
+ .browse-modal-title {
2642
+ margin: 0;
2643
+ font-size: var(--spectrum-font-size-100, 14px);
2644
+ font-weight: 600;
2645
+ color: var(--fg);
2646
+ }
2647
+ .browse-modal-content {
2648
+ flex: 1;
2649
+ min-height: 0;
2650
+ overflow: hidden;
2651
+ }
2652
+
2653
+ /* ─── Browse view ────────────────────────────── */
2654
+ .browse-view {
2655
+ display: flex;
2656
+ flex-direction: column;
2657
+ width: 100%;
2658
+ height: 100%;
2659
+ overflow: hidden;
2660
+ }
2661
+ .browse-view.browse-drop-active {
2662
+ outline: 2px dashed var(--spectrum-blue-600, #0070c1);
2663
+ outline-offset: -4px;
2664
+ }
2665
+ .browse-filter-bar {
2666
+ display: flex;
2667
+ align-items: center;
2668
+ gap: 12px;
2669
+ padding: 8px 16px;
2670
+ background: var(--bg-panel);
2671
+ border-bottom: 1px solid var(--border);
2672
+ flex-shrink: 0;
2673
+ }
2674
+ .browse-filter-bar sp-search {
2675
+ width: 240px;
2676
+ }
2677
+ .browse-table {
2678
+ flex: 1;
2679
+ overflow: auto;
2680
+ padding: 0 16px 16px;
2681
+ }
2682
+ .browse-table sp-table {
2683
+ width: 100%;
2684
+ min-width: 100%;
2685
+ }
2686
+ .browse-table sp-table-head-cell:nth-child(1),
2687
+ .browse-table sp-table-cell:nth-child(1) {
2688
+ flex: 3;
2689
+ }
2690
+ .browse-table sp-table-head-cell:nth-child(2),
2691
+ .browse-table sp-table-cell:nth-child(2) {
2692
+ flex: 0 0 80px;
2693
+ }
2694
+ .browse-table sp-table-head-cell:nth-child(3),
2695
+ .browse-table sp-table-cell:nth-child(3) {
2696
+ flex: 0 0 60px;
2697
+ }
2698
+ .browse-table sp-table-head-cell:nth-child(4),
2699
+ .browse-table sp-table-cell:nth-child(4) {
2700
+ flex: 2;
2701
+ }
2702
+ .browse-row {
2703
+ cursor: pointer;
2704
+ }
2705
+ .browse-row-media,
2706
+ sp-table-row:has(.browse-thumb) {
2707
+ cursor: default;
2708
+ }
2709
+ .browse-row:hover {
2710
+ background: var(--spectrum-gray-200, #333);
2711
+ }
2712
+ .browse-name-cell {
2713
+ font-weight: 500;
2714
+ }
2715
+ .browse-thumb {
2716
+ width: 32px;
2717
+ height: 32px;
2718
+ object-fit: cover;
2719
+ border-radius: var(--radius);
2720
+ vertical-align: middle;
2721
+ margin-right: 8px;
2722
+ background: var(--spectrum-gray-200, #2a2a2a);
2723
+ }
2724
+ .browse-path-cell {
2725
+ color: var(--fg-dim);
2726
+ font-family: var(--font-mono);
2727
+ font-size: var(--spectrum-font-size-50, 11px);
2728
+ }
2729
+ .browse-view-switcher {
2730
+ display: flex;
2731
+ gap: 2px;
2732
+ margin-left: auto;
2733
+ }
2734
+ .browse-grid {
2735
+ display: grid;
2736
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
2737
+ gap: 12px;
2738
+ padding: 12px;
2739
+ align-items: start;
2740
+ }
2741
+ .browse-grid .element-card {
2742
+ cursor: pointer;
2743
+ margin-bottom: 0;
2744
+ overflow: hidden;
2745
+ }
2746
+ .browse-grid .element-card-preview {
2747
+ aspect-ratio: 4/3;
2748
+ max-height: none;
2749
+ min-height: unset;
2750
+ display: block;
2751
+ overflow: hidden;
2752
+ }
2753
+ .browse-grid-empty {
2754
+ padding: 24px;
2755
+ text-align: center;
2756
+ color: var(--fg-dim);
2757
+ }
2758
+ .browse-body {
2759
+ flex: 1;
2760
+ overflow-y: auto;
2761
+ min-height: 0;
2762
+ }
2763
+
2764
+ /* ─── Settings Modal ─── */
2765
+ .settings-modal {
2766
+ position: fixed;
2767
+ inset: 40px;
2768
+ z-index: 1000;
2769
+ display: flex;
2770
+ flex-direction: column;
2771
+ background: var(--bg-panel);
2772
+ border: 1px solid var(--border);
2773
+ border-radius: var(--spectrum-corner-radius-200, 8px);
2774
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
2775
+ overflow: hidden;
2776
+ }
2777
+ .about-modal {
2778
+ position: fixed;
2779
+ top: 50%;
2780
+ left: 50%;
2781
+ transform: translate(-50%, -50%);
2782
+ width: min(440px, calc(100vw - 48px));
2783
+ max-height: calc(100vh - 80px);
2784
+ z-index: 1000;
2785
+ display: flex;
2786
+ flex-direction: column;
2787
+ background: var(--bg-panel);
2788
+ border: 1px solid var(--border);
2789
+ border-radius: var(--spectrum-corner-radius-200, 8px);
2790
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
2791
+ overflow: hidden;
2792
+ }
2793
+ .about-modal-body {
2794
+ flex: 1;
2795
+ overflow-y: auto;
2796
+ padding: 20px;
2797
+ }
2798
+ .about-meta {
2799
+ margin: 0 0 16px;
2800
+ display: flex;
2801
+ flex-direction: column;
2802
+ gap: 6px;
2803
+ }
2804
+ .about-meta-row {
2805
+ display: flex;
2806
+ gap: 12px;
2807
+ font-size: 13px;
2808
+ }
2809
+ .about-meta-label {
2810
+ width: 96px;
2811
+ min-width: 96px;
2812
+ margin: 0;
2813
+ color: var(--fg-dim);
2814
+ }
2815
+ .about-meta-value {
2816
+ margin: 0;
2817
+ color: var(--fg);
2818
+ word-break: break-word;
2819
+ }
2820
+ .about-links {
2821
+ display: flex;
2822
+ gap: 16px;
2823
+ padding: 12px 0;
2824
+ margin-bottom: 12px;
2825
+ border-top: 1px solid var(--border);
2826
+ border-bottom: 1px solid var(--border);
2827
+ font-size: 13px;
2828
+ }
2829
+ .about-links a {
2830
+ color: var(--spectrum-accent-color-1000, #6aa9ff);
2831
+ text-decoration: none;
2832
+ }
2833
+ .about-links a:hover {
2834
+ text-decoration: underline;
2835
+ }
2836
+ .about-section-title {
2837
+ margin: 0 0 8px;
2838
+ font-size: 13px;
2839
+ font-weight: 600;
2840
+ color: var(--fg);
2841
+ }
2842
+ .about-muted {
2843
+ margin: 0;
2844
+ font-size: 13px;
2845
+ color: var(--fg-dim);
2846
+ }
2847
+ .about-packages {
2848
+ list-style: none;
2849
+ margin: 0;
2850
+ padding: 0;
2851
+ display: flex;
2852
+ flex-direction: column;
2853
+ gap: 4px;
2854
+ }
2855
+ .about-package-row {
2856
+ display: flex;
2857
+ justify-content: space-between;
2858
+ gap: 12px;
2859
+ font-size: var(--spectrum-font-size-75, 12px);
2860
+ }
2861
+ .about-package-name {
2862
+ color: var(--fg-dim);
2863
+ }
2864
+ .about-package-version {
2865
+ color: var(--fg);
2866
+ font-variant-numeric: tabular-nums;
2867
+ }
2868
+ .settings-modal-header {
2869
+ display: flex;
2870
+ align-items: center;
2871
+ justify-content: space-between;
2872
+ padding: 12px 16px;
2873
+ border-bottom: 1px solid var(--border);
2874
+ }
2875
+ .settings-modal-title {
2876
+ margin: 0;
2877
+ font-size: var(--spectrum-font-size-100, 14px);
2878
+ font-weight: 600;
2879
+ color: var(--fg);
2880
+ }
2881
+ .settings-modal-body {
2882
+ display: flex;
2883
+ flex: 1;
2884
+ min-height: 0;
2885
+ }
2886
+ .settings-modal-nav {
2887
+ width: 180px;
2888
+ min-width: 180px;
2889
+ padding: 8px 0;
2890
+ border-right: 1px solid var(--border);
2891
+ overflow-y: auto;
2892
+ display: flex;
2893
+ flex-direction: column;
2894
+ }
2895
+ .settings-nav-item {
2896
+ display: block;
2897
+ width: 100%;
2898
+ padding: 8px 16px;
2899
+ border: none;
2900
+ background: none;
2901
+ color: var(--fg-dim);
2902
+ font-size: 13px;
2903
+ text-align: left;
2904
+ cursor: pointer;
2905
+ border-radius: 0;
2906
+ }
2907
+ .settings-nav-item:hover {
2908
+ background: var(--spectrum-gray-200, #333);
2909
+ color: var(--fg);
2910
+ }
2911
+ .settings-nav-item.active {
2912
+ background: var(--spectrum-gray-300, #444);
2913
+ color: var(--fg);
2914
+ font-weight: 500;
2915
+ }
2916
+ .settings-modal-content {
2917
+ flex: 1;
2918
+ overflow-y: auto;
2919
+ padding: 24px;
2920
+ }
2921
+ .settings-section-title {
2922
+ margin: 0 0 16px;
2923
+ font-size: 16px;
2924
+ font-weight: 600;
2925
+ color: var(--fg);
2926
+ }
2927
+ .settings-field {
2928
+ margin-bottom: 20px;
2929
+ }
2930
+ .settings-field-label {
2931
+ display: block;
2932
+ font-size: 13px;
2933
+ font-weight: 500;
2934
+ color: var(--fg);
2935
+ margin-bottom: 2px;
2936
+ }
2937
+ .settings-field-desc {
2938
+ margin: 0 0 6px;
2939
+ font-size: var(--spectrum-font-size-75, 12px);
2940
+ color: var(--fg-dim);
2941
+ }
2942
+ .settings-field-row {
2943
+ display: flex;
2944
+ gap: 8px;
2945
+ align-items: center;
2946
+ margin-bottom: 8px;
2947
+ }
2948
+ .settings-media-list {
2949
+ display: flex;
2950
+ flex-direction: column;
2951
+ gap: 6px;
2952
+ }
2953
+ .settings-media-row {
2954
+ display: flex;
2955
+ gap: 6px;
2956
+ align-items: center;
2957
+ }
2958
+ .settings-media-name-fixed {
2959
+ width: 80px;
2960
+ font-size: var(--spectrum-font-size-75, 12px);
2961
+ font-weight: 500;
2962
+ color: var(--fg-dim);
2963
+ padding: 0 8px;
2964
+ }
2965
+ .settings-media-name {
2966
+ width: 80px;
2967
+ }
2968
+ .settings-media-value {
2969
+ flex: 1;
2970
+ }
2971
+ /* New Project modal */
2972
+ .new-project-modal {
2973
+ position: fixed;
2974
+ top: 50%;
2975
+ left: 50%;
2976
+ transform: translate(-50%, -50%);
2977
+ z-index: 1000;
2978
+ display: flex;
2979
+ flex-direction: column;
2980
+ background: var(--bg-panel);
2981
+ border: 1px solid var(--border);
2982
+ border-radius: var(--spectrum-corner-radius-200, 8px);
2983
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.4);
2984
+ width: min(720px, calc(100vw - 48px));
2985
+ max-height: 80vh;
2986
+ }
2987
+ .new-project-modal-header {
2988
+ display: flex;
2989
+ align-items: center;
2990
+ justify-content: space-between;
2991
+ padding: 12px 16px;
2992
+ border-bottom: 1px solid var(--border);
2993
+ }
2994
+ .new-project-modal-title {
2995
+ margin: 0;
2996
+ font-size: var(--spectrum-font-size-100, 14px);
2997
+ font-weight: 600;
2998
+ color: var(--fg);
2999
+ }
3000
+ .new-project-modal-body {
3001
+ padding: 16px;
3002
+ overflow-y: auto;
3003
+ display: flex;
3004
+ flex-direction: column;
3005
+ gap: 12px;
3006
+ }
3007
+ .new-project-modal-footer {
3008
+ display: flex;
3009
+ justify-content: flex-end;
3010
+ gap: 8px;
3011
+ padding: 12px 16px;
3012
+ border-top: 1px solid var(--border);
3013
+ }
3014
+ .new-project-field {
3015
+ display: flex;
3016
+ flex-direction: column;
3017
+ gap: 4px;
3018
+ }
3019
+ .new-project-label {
3020
+ font-size: var(--spectrum-font-size-75, 12px);
3021
+ font-weight: 500;
3022
+ color: var(--fg-dim);
3023
+ }
3024
+ .new-project-error {
3025
+ font-size: var(--spectrum-font-size-75, 12px);
3026
+ color: var(--danger);
3027
+ padding: 4px 0;
3028
+ }
3029
+ /* Backend/global creation errors sit between the scroll body and the footer so they are
3030
+ visible regardless of scroll position. */
3031
+ .new-project-error--global {
3032
+ flex: none;
3033
+ padding: 8px 16px;
3034
+ border-top: 1px solid var(--border);
3035
+ }
3036
+ .add-repo-modal .new-project-modal-body {
3037
+ display: flex;
3038
+ flex-direction: column;
3039
+ gap: 8px;
3040
+ }
3041
+ .add-repo-list {
3042
+ display: flex;
3043
+ flex-direction: column;
3044
+ max-height: 320px;
3045
+ overflow-y: auto;
3046
+ }
3047
+ .add-repo-row {
3048
+ display: flex;
3049
+ align-items: baseline;
3050
+ gap: 8px;
3051
+ width: 100%;
3052
+ padding: 5px 8px;
3053
+ background: none;
3054
+ border: none;
3055
+ border-radius: var(--radius);
3056
+ font: inherit;
3057
+ font-size: 13px;
3058
+ color: var(--fg);
3059
+ cursor: pointer;
3060
+ text-align: left;
3061
+ }
3062
+ .add-repo-row:hover:not([disabled]) {
3063
+ background: var(--hover-bg);
3064
+ }
3065
+ .add-repo-row[disabled] {
3066
+ opacity: 0.6;
3067
+ cursor: default;
3068
+ }
3069
+ .add-repo-name {
3070
+ color: var(--accent);
3071
+ }
3072
+ .add-repo-meta {
3073
+ display: flex;
3074
+ align-items: baseline;
3075
+ gap: 6px;
3076
+ font-size: var(--spectrum-font-size-50, 11px);
3077
+ color: var(--fg-dim);
3078
+ }
3079
+ .add-repo-badge {
3080
+ padding: 0 5px;
3081
+ border: 1px solid var(--border);
3082
+ border-radius: 8px;
3083
+ }
3084
+ .add-repo-busy {
3085
+ margin-left: auto;
3086
+ font-size: var(--spectrum-font-size-50, 11px);
3087
+ color: var(--fg-dim);
3088
+ }
3089
+ .add-repo-empty {
3090
+ padding: 12px 8px;
3091
+ font-size: var(--spectrum-font-size-75, 12px);
3092
+ color: var(--fg-dim);
3093
+ }
3094
+ .add-repo-install {
3095
+ color: var(--accent, #1473e6);
3096
+ text-decoration: underline;
3097
+ }
3098
+ .new-project-tabs {
3099
+ padding: 0 16px;
3100
+ border-bottom: 1px solid var(--border);
3101
+ }
3102
+ .new-project-tab-intro {
3103
+ font-size: var(--spectrum-font-size-75, 12px);
3104
+ color: var(--fg-dim);
3105
+ line-height: 1.5;
3106
+ }
3107
+ .new-project-creds {
3108
+ display: flex;
3109
+ flex-direction: column;
3110
+ max-width: 480px;
3111
+ }
3112
+ .new-project-import-grid {
3113
+ display: grid;
3114
+ grid-template-columns: 1fr 1fr;
3115
+ gap: 12px;
3116
+ }
3117
+ .new-project-import-progress {
3118
+ display: flex;
3119
+ align-items: center;
3120
+ gap: 8px;
3121
+ font-size: var(--spectrum-font-size-75, 12px);
3122
+ color: var(--fg);
3123
+ }
3124
+ .new-project-import-log {
3125
+ font-family: var(--font-mono);
3126
+ font-size: 11px;
3127
+ line-height: 1.6;
3128
+ background: var(--bg-input);
3129
+ border: 1px solid var(--border);
3130
+ border-radius: var(--radius);
3131
+ padding: 8px 10px;
3132
+ max-height: 240px;
3133
+ overflow-y: auto;
3134
+ white-space: pre-wrap;
3135
+ word-break: break-word;
3136
+ }
3137
+ .new-project-import-log-line {
3138
+ color: var(--fg);
3139
+ }
3140
+ .new-project-import-phase {
3141
+ color: var(--fg-dim);
3142
+ margin-right: 6px;
3143
+ }
3144
+ .new-project-agent-prompt {
3145
+ min-height: 120px;
3146
+ }
3147
+ .new-project-step-context {
3148
+ font-size: var(--spectrum-font-size-75, 12px);
3149
+ color: var(--fg-dim);
3150
+ }
3151
+ .new-project-step-heading {
3152
+ font-size: var(--spectrum-font-size-200, 16px);
3153
+ font-weight: 600;
3154
+ color: var(--fg);
3155
+ margin-bottom: 4px;
3156
+ }
3157
+ .new-project-design-section {
3158
+ display: flex;
3159
+ flex-direction: column;
3160
+ gap: 8px;
3161
+ padding-top: 8px;
3162
+ border-top: 1px solid var(--border);
3163
+ }
3164
+ .new-project-design-heading {
3165
+ font-size: var(--spectrum-font-size-75, 12px);
3166
+ font-weight: 600;
3167
+ color: var(--fg);
3168
+ text-transform: uppercase;
3169
+ letter-spacing: 0.5px;
3170
+ }
3171
+ .new-project-color-row {
3172
+ display: flex;
3173
+ align-items: center;
3174
+ gap: 8px;
3175
+ }
3176
+ .new-project-color-row .new-project-label {
3177
+ min-width: 90px;
3178
+ }
3179
+ .new-project-color-row sp-textfield {
3180
+ flex: 1;
3181
+ }
3182
+ .new-project-logo-row {
3183
+ display: flex;
3184
+ align-items: center;
3185
+ gap: 10px;
3186
+ color: var(--fg);
3187
+ font-size: var(--spectrum-font-size-75, 12px);
3188
+ }
3189
+ .new-project-logo-name {
3190
+ display: inline-flex;
3191
+ align-items: center;
3192
+ gap: 4px;
3193
+ color: var(--fg-dim);
3194
+ }
3195
+ .new-project-media-row {
3196
+ display: flex;
3197
+ align-items: center;
3198
+ gap: 8px;
3199
+ }
3200
+ .new-project-media-row .new-project-media-name {
3201
+ width: 110px;
3202
+ }
3203
+ .new-project-media-row .new-project-media-value {
3204
+ flex: 1;
3205
+ }
3206
+ .new-project-templates {
3207
+ display: grid;
3208
+ grid-template-columns: 1fr 1fr 1fr;
3209
+ gap: 8px;
3210
+ }
3211
+ .new-project-template {
3212
+ text-align: left;
3213
+ border: 1px solid var(--border);
3214
+ border-radius: 6px;
3215
+ overflow: hidden;
3216
+ cursor: pointer;
3217
+ background: var(--bg-panel);
3218
+ padding: 0;
3219
+ display: flex;
3220
+ flex-direction: column;
3221
+ }
3222
+ .new-project-template:hover {
3223
+ border-color: var(--fg-dim);
3224
+ }
3225
+ .new-project-template.selected {
3226
+ border-color: var(--accent, #3b82f6);
3227
+ box-shadow: 0 0 0 1px var(--accent, #3b82f6);
3228
+ }
3229
+ .new-project-template-thumb {
3230
+ width: 100%;
3231
+ aspect-ratio: 16 / 10;
3232
+ object-fit: cover;
3233
+ display: block;
3234
+ background: var(--bg-elevated, #1a1a1a);
3235
+ }
3236
+ .new-project-template-blank {
3237
+ display: flex;
3238
+ align-items: center;
3239
+ justify-content: center;
3240
+ aspect-ratio: 16 / 10;
3241
+ color: var(--fg-dim);
3242
+ font-size: 28px;
3243
+ background: var(--bg-elevated, #1a1a1a);
3244
+ }
3245
+ .new-project-template-body {
3246
+ padding: 6px 8px 8px;
3247
+ }
3248
+ .new-project-template-name {
3249
+ font-size: 12px;
3250
+ font-weight: 600;
3251
+ color: var(--fg);
3252
+ }
3253
+ .new-project-template-tag {
3254
+ font-size: 11px;
3255
+ color: var(--fg-dim);
3256
+ margin-top: 2px;
3257
+ line-height: 1.3;
3258
+ }
3259
+ /* CSS Vars editor */
3260
+ .css-vars-group {
3261
+ margin-bottom: 24px;
3262
+ }
3263
+ .css-vars-group-title {
3264
+ margin: 0 0 8px;
3265
+ font-size: 13px;
3266
+ font-weight: 600;
3267
+ color: var(--fg);
3268
+ text-transform: uppercase;
3269
+ letter-spacing: 0.5px;
3270
+ }
3271
+ .css-var-row {
3272
+ display: flex;
3273
+ align-items: center;
3274
+ gap: 8px;
3275
+ padding: 4px 0;
3276
+ }
3277
+ .css-var-name {
3278
+ font-size: var(--spectrum-font-size-75, 12px);
3279
+ color: var(--fg-dim);
3280
+ min-width: 100px;
3281
+ }
3282
+ .css-var-swatch {
3283
+ width: 24px;
3284
+ height: 24px;
3285
+ border-radius: var(--radius);
3286
+ border: 1px solid var(--border);
3287
+ position: relative;
3288
+ overflow: hidden;
3289
+ cursor: pointer;
3290
+ }
3291
+ .css-var-swatch input[type="color"] {
3292
+ position: absolute;
3293
+ inset: 0;
3294
+ opacity: 0;
3295
+ cursor: pointer;
3296
+ width: 100%;
3297
+ height: 100%;
3298
+ }
3299
+ .css-var-font-preview {
3300
+ font-size: 13px;
3301
+ color: var(--fg-dim);
3302
+ padding: 4px 0 12px 108px;
3303
+ }
3304
+ .css-var-media-overrides {
3305
+ padding-left: 108px;
3306
+ margin-bottom: 8px;
3307
+ }
3308
+ .css-var-media-row {
3309
+ display: flex;
3310
+ align-items: center;
3311
+ gap: 8px;
3312
+ padding: 2px 0;
3313
+ }
3314
+ .css-var-media-label {
3315
+ font-size: var(--spectrum-font-size-50, 11px);
3316
+ color: var(--fg-dim);
3317
+ min-width: 60px;
3318
+ }
3319
+ .css-var-add-row {
3320
+ display: flex;
3321
+ gap: 8px;
3322
+ align-items: center;
3323
+ padding: 8px 0;
3324
+ border-top: 1px solid var(--border);
3325
+ margin-top: 8px;
3326
+ }
3327
+ /* Head editor */
3328
+ .head-entry {
3329
+ border: 1px solid var(--border);
3330
+ border-radius: var(--radius);
3331
+ padding: 12px;
3332
+ margin-bottom: 8px;
3333
+ }
3334
+ .head-entry-header {
3335
+ display: flex;
3336
+ align-items: center;
3337
+ justify-content: space-between;
3338
+ margin-bottom: 8px;
3339
+ }
3340
+ .head-entry-tag {
3341
+ font-size: var(--spectrum-font-size-75, 12px);
3342
+ font-weight: 600;
3343
+ color: var(--fg);
3344
+ }
3345
+ .head-code-editor {
3346
+ width: 100%;
3347
+ min-height: 80px;
3348
+ padding: 8px;
3349
+ font-family: var(--font-mono);
3350
+ font-size: var(--spectrum-font-size-75, 12px);
3351
+ background: var(--spectrum-gray-100, #1e1e1e);
3352
+ color: var(--fg);
3353
+ border: 1px solid var(--border);
3354
+ border-radius: var(--radius);
3355
+ resize: vertical;
3356
+ }
3357
+
3358
+ /* ─── Settings editors (Collections / Definitions) ─── */
3359
+ .settings-two-col {
3360
+ display: flex;
3361
+ height: 100%;
3362
+ gap: 1px;
3363
+ background: var(--border);
3364
+ }
3365
+ .settings-list-panel {
3366
+ display: flex;
3367
+ flex-direction: column;
3368
+ gap: 4px;
3369
+ padding: 12px;
3370
+ width: 200px;
3371
+ min-width: 200px;
3372
+ background: var(--bg-panel);
3373
+ overflow-y: auto;
3374
+ }
3375
+ .settings-list-panel sp-action-button {
3376
+ width: 100%;
3377
+ justify-content: flex-start;
3378
+ }
3379
+ .settings-editor-panel {
3380
+ flex: 1;
3381
+ padding: 16px;
3382
+ background: var(--bg-panel);
3383
+ overflow-y: auto;
3384
+ }
3385
+ .settings-editor-header {
3386
+ display: flex;
3387
+ align-items: center;
3388
+ gap: 12px;
3389
+ margin-bottom: 16px;
3390
+ }
3391
+ .settings-editor-header h3 {
3392
+ margin: 0;
3393
+ font-size: var(--spectrum-font-size-100, 14px);
3394
+ font-weight: 600;
3395
+ }
3396
+ .settings-empty-state {
3397
+ flex: 1;
3398
+ display: flex;
3399
+ align-items: center;
3400
+ justify-content: center;
3401
+ background: var(--bg-panel);
3402
+ color: var(--fg-dim);
3403
+ font-size: 13px;
3404
+ }
3405
+ .settings-inline-form {
3406
+ display: flex;
3407
+ align-items: center;
3408
+ gap: 6px;
3409
+ }
3410
+ .settings-top-chrome {
3411
+ z-index: 16 !important;
3412
+ }
3413
+
3414
+ /* ─── Schema field cards ─── */
3415
+ .schema-field-list {
3416
+ display: flex;
3417
+ flex-direction: column;
3418
+ gap: 4px;
3419
+ margin-bottom: 12px;
3420
+ }
3421
+ .schema-field-card {
3422
+ border: 1px solid var(--border);
3423
+ border-radius: var(--radius);
3424
+ padding: 6px 10px;
3425
+ }
3426
+ .schema-field-row {
3427
+ display: flex;
3428
+ align-items: center;
3429
+ gap: 8px;
3430
+ }
3431
+ .schema-field-nested {
3432
+ margin-left: 16px;
3433
+ margin-top: 6px;
3434
+ padding-left: 8px;
3435
+ border-left: 2px solid var(--border);
3436
+ }
3437
+ .schema-field-name-input {
3438
+ flex: 1;
3439
+ max-width: 140px;
3440
+ }
3441
+ .schema-field-card--nested {
3442
+ border-color: var(--spectrum-gray-300, #444);
3443
+ }
3444
+ .schema-nested-add {
3445
+ display: flex;
3446
+ align-items: center;
3447
+ gap: 6px;
3448
+ padding: 4px 0;
3449
+ }
3450
+ .schema-nested-add-name {
3451
+ flex: 1;
3452
+ max-width: 120px;
3453
+ }
3454
+ .schema-add-field {
3455
+ display: flex;
3456
+ align-items: center;
3457
+ gap: 8px;
3458
+ padding: 8px 0;
3459
+ }
3460
+
3461
+ /* ─── Media picker ─────────────────────────────── */
3462
+ .media-picker {
3463
+ display: flex;
3464
+ align-items: center;
3465
+ gap: 4px;
3466
+ flex: 1;
3467
+ }
3468
+ .media-picker sp-textfield {
3469
+ flex: 1;
3470
+ }
3471
+ .media-picker-thumb {
3472
+ width: 24px;
3473
+ height: 24px;
3474
+ object-fit: cover;
3475
+ border-radius: var(--radius);
3476
+ border: 1px solid var(--border);
3477
+ flex-shrink: 0;
3478
+ }
3479
+ /* .media-picker-popover is no longer used — inlined in media-picker.ts */
3480
+
3481
+ /* ─── Source view ────────────────────────────── */
3482
+ #source-view {
3483
+ width: 100%;
3484
+ height: 100%;
3485
+ background: var(--bg);
3486
+ color: var(--fg);
3487
+ font: 11px/1.6 var(--font-mono, monospace);
3488
+ border: none;
3489
+ padding: 8px;
3490
+ resize: none;
3491
+ outline: none;
3492
+ }
3493
+
3494
+ /* ─── Empty state ────────────────────────────── */
3495
+ .empty-state {
3496
+ padding: 24px;
3497
+ text-align: center;
3498
+ color: var(--fg-dim);
3499
+ font-size: 13px;
3500
+ }
3501
+
3502
+ /* ─── Style toolbar (media tabs + selector) ──── */
3503
+ .style-toolbar {
3504
+ display: flex;
3505
+ align-items: center;
3506
+ padding: 4px 8px;
3507
+ gap: 8px;
3508
+ }
3509
+ .style-toolbar-tabs {
3510
+ flex: 1;
3511
+ min-width: 0;
3512
+ }
3513
+ .style-toolbar .selector-select {
3514
+ flex-shrink: 0;
3515
+ max-width: 120px;
3516
+ }
3517
+ .style-filter-bar {
3518
+ display: flex;
3519
+ align-items: center;
3520
+ padding: 2px 8px 4px;
3521
+ gap: 6px;
3522
+ }
3523
+ .style-filter-input {
3524
+ flex: 1;
3525
+ min-width: 0;
3526
+ --spectrum-textfield-texticon-min-width: 0;
3527
+ }
3528
+ .style-filter-toggle[selected] {
3529
+ background: var(--accent);
3530
+ color: var(--accent-fg);
3531
+ }
3532
+ .selector-select {
3533
+ min-width: 0;
3534
+ font-size: 10px;
3535
+ }
3536
+ .selector-custom-input {
3537
+ flex: 1;
3538
+ min-width: 0;
3539
+ padding: 3px 6px;
3540
+ font: inherit;
3541
+ font-size: 10px;
3542
+ font-family: var(--font-mono);
3543
+ color: var(--fg);
3544
+ background: var(--bg-input);
3545
+ border: 1px solid var(--accent);
3546
+ border-radius: var(--radius);
3547
+ outline: none;
3548
+ }
3549
+
3550
+ /* ─── Git panel ──────────────────────────────── */
3551
+ .git-panel {
3552
+ display: flex;
3553
+ flex-direction: column;
3554
+ height: 100%;
3555
+ font-size: var(--spectrum-font-size-75, 12px);
3556
+ }
3557
+
3558
+ /* Sync status bar */
3559
+ .git-sync-bar {
3560
+ display: flex;
3561
+ align-items: center;
3562
+ gap: 10px;
3563
+ padding: 12px 12px;
3564
+ border-bottom: 1px solid var(--border);
3565
+ }
3566
+ .git-sync-icon {
3567
+ flex-shrink: 0;
3568
+ }
3569
+ .git-sync-text {
3570
+ display: flex;
3571
+ flex-direction: column;
3572
+ gap: 2px;
3573
+ flex: 1;
3574
+ }
3575
+ .git-sync-actions {
3576
+ flex-shrink: 0;
3577
+ margin-left: auto;
3578
+ }
3579
+ .git-sync-label {
3580
+ font-size: 13px;
3581
+ font-weight: 600;
3582
+ color: var(--fg);
3583
+ }
3584
+ .git-sync-time {
3585
+ font-size: var(--spectrum-font-size-50, 11px);
3586
+ color: var(--fg-dim);
3587
+ }
3588
+
3589
+ /* Branch selector row */
3590
+ .git-branch-row {
3591
+ display: flex;
3592
+ align-items: center;
3593
+ gap: 10px;
3594
+ padding: 10px 12px;
3595
+ border-bottom: 1px solid var(--border);
3596
+ }
3597
+ .git-branch-icon {
3598
+ flex-shrink: 0;
3599
+ color: var(--fg-dim);
3600
+ }
3601
+ .git-branch-text {
3602
+ display: flex;
3603
+ flex-direction: column;
3604
+ gap: 1px;
3605
+ flex: 1;
3606
+ min-width: 0;
3607
+ }
3608
+ .git-branch-label {
3609
+ font-size: var(--spectrum-font-size-50, 11px);
3610
+ color: var(--fg-dim);
3611
+ }
3612
+ .git-branch-name {
3613
+ font-size: 13px;
3614
+ font-weight: 600;
3615
+ color: var(--fg);
3616
+ }
3617
+ .git-branch-picker {
3618
+ flex-shrink: 0;
3619
+ --spectrum-picker-min-width: 0;
3620
+ }
3621
+
3622
+ /* Tabs: Local Changes / History */
3623
+ .git-tabs {
3624
+ display: flex;
3625
+ border-bottom: 1px solid var(--border);
3626
+ }
3627
+ .git-tab {
3628
+ flex: 1;
3629
+ padding: 8px 12px;
3630
+ font: inherit;
3631
+ font-size: var(--spectrum-font-size-75, 12px);
3632
+ font-weight: 600;
3633
+ background: var(--hover-bg);
3634
+ border: none;
3635
+ border-bottom: 2px solid transparent;
3636
+ color: var(--fg-dim);
3637
+ cursor: pointer;
3638
+ transition:
3639
+ color 0.15s,
3640
+ border-color 0.15s;
3641
+ }
3642
+ .git-tab:hover {
3643
+ color: var(--fg);
3644
+ }
3645
+ .git-tab.active {
3646
+ color: var(--fg);
3647
+ border-bottom-color: var(--accent, #e2b93d);
3648
+ background: transparent;
3649
+ }
3650
+
3651
+ /* Commit area */
3652
+ .git-commit-area {
3653
+ display: flex;
3654
+ flex-direction: column;
3655
+ gap: 8px;
3656
+ padding: 12px;
3657
+ border-bottom: 1px solid var(--border);
3658
+ }
3659
+ .git-commit-label {
3660
+ font-size: var(--spectrum-font-size-75, 12px);
3661
+ font-weight: 500;
3662
+ color: var(--fg-dim);
3663
+ }
3664
+ .git-commit-input {
3665
+ width: 100%;
3666
+ --spectrum-textfield-texticon-min-width: 0;
3667
+ }
3668
+ .git-commit-actions {
3669
+ display: flex;
3670
+ }
3671
+ .git-split-btn {
3672
+ display: flex;
3673
+ flex: 1;
3674
+ position: relative;
3675
+ }
3676
+ .git-split-btn .git-commit-btn {
3677
+ flex: 1;
3678
+ border-top-right-radius: 0;
3679
+ border-bottom-right-radius: 0;
3680
+ }
3681
+ .git-split-btn .git-split-trigger {
3682
+ border-top-left-radius: 0;
3683
+ border-bottom-left-radius: 0;
3684
+ border-left: 1px solid rgba(0, 0, 0, 0.15);
3685
+ }
3686
+ .git-split-menu {
3687
+ position: absolute;
3688
+ top: 100%;
3689
+ left: 0;
3690
+ right: 0;
3691
+ margin-top: 4px;
3692
+ background: var(--bg-panel);
3693
+ border: 1px solid var(--border);
3694
+ border-radius: var(--radius);
3695
+ z-index: 10;
3696
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
3697
+ }
3698
+ .git-split-menu-item {
3699
+ display: block;
3700
+ width: 100%;
3701
+ padding: 6px 12px;
3702
+ font: inherit;
3703
+ font-size: var(--spectrum-font-size-75, 12px);
3704
+ color: var(--fg);
3705
+ background: none;
3706
+ border: none;
3707
+ text-align: left;
3708
+ cursor: pointer;
3709
+ }
3710
+ .git-split-menu-item:hover {
3711
+ background: var(--hover-bg);
3712
+ }
3713
+
3714
+ /* Changed Components grouping */
3715
+ .git-component-group {
3716
+ margin-bottom: 2px;
3717
+ }
3718
+ .git-component-header {
3719
+ display: flex;
3720
+ align-items: center;
3721
+ gap: 6px;
3722
+ padding: 4px 8px;
3723
+ }
3724
+ .git-component-overflow {
3725
+ flex-shrink: 0;
3726
+ }
3727
+ .git-component-name {
3728
+ font-size: var(--spectrum-font-size-75, 12px);
3729
+ font-weight: 500;
3730
+ color: var(--fg);
3731
+ }
3732
+
3733
+ /* Sections */
3734
+ .git-section {
3735
+ border-bottom: 1px solid var(--border);
3736
+ }
3737
+ .git-section-header {
3738
+ display: flex;
3739
+ align-items: center;
3740
+ gap: 6px;
3741
+ padding: 8px 12px 6px;
3742
+ font-size: var(--spectrum-font-size-75, 12px);
3743
+ font-weight: 700;
3744
+ color: var(--fg);
3745
+ }
3746
+ .git-count {
3747
+ display: inline-flex;
3748
+ align-items: center;
3749
+ justify-content: center;
3750
+ min-width: 18px;
3751
+ height: 18px;
3752
+ padding: 0 5px;
3753
+ border-radius: 9px;
3754
+ background: var(--accent-15);
3755
+ color: var(--accent);
3756
+ font-size: 10px;
3757
+ font-weight: 600;
3758
+ }
3759
+ .git-section-header .git-count {
3760
+ margin-right: auto;
3761
+ }
3762
+
3763
+ /* File rows */
3764
+ .git-file-row {
3765
+ display: flex;
3766
+ align-items: center;
3767
+ gap: 4px;
3768
+ padding: 2px 8px 2px 16px;
3769
+ cursor: default;
3770
+ }
3771
+ .git-file-row:hover {
3772
+ background: var(--hover-bg);
3773
+ }
3774
+ .git-file-info {
3775
+ flex: 1;
3776
+ min-width: 0;
3777
+ display: flex;
3778
+ align-items: baseline;
3779
+ gap: 6px;
3780
+ overflow: hidden;
3781
+ }
3782
+ .git-file-name {
3783
+ white-space: nowrap;
3784
+ overflow: hidden;
3785
+ text-overflow: ellipsis;
3786
+ }
3787
+ .git-file-dir {
3788
+ font-size: 10px;
3789
+ color: var(--fg-dim);
3790
+ white-space: nowrap;
3791
+ overflow: hidden;
3792
+ text-overflow: ellipsis;
3793
+ }
3794
+ .git-file-actions {
3795
+ display: flex;
3796
+ gap: 0;
3797
+ opacity: 0;
3798
+ }
3799
+ .git-file-row:hover .git-file-actions {
3800
+ opacity: 1;
3801
+ }
3802
+ .git-file-badge {
3803
+ flex-shrink: 0;
3804
+ width: 16px;
3805
+ text-align: center;
3806
+ font-size: 10px;
3807
+ font-weight: 700;
3808
+ font-family: var(--font-mono);
3809
+ }
3810
+ .git-status-M {
3811
+ color: var(--signal);
3812
+ }
3813
+ .git-status-A {
3814
+ color: var(--success);
3815
+ }
3816
+ .git-status-D {
3817
+ color: var(--danger);
3818
+ }
3819
+ .git-status-R {
3820
+ color: var(--tag);
3821
+ }
3822
+ .git-status-U {
3823
+ color: var(--success);
3824
+ }
3825
+ .git-status-C {
3826
+ color: var(--tag);
3827
+ }
3828
+
3829
+ /* History tab */
3830
+ .git-history {
3831
+ padding: 4px 0;
3832
+ overflow-y: auto;
3833
+ flex: 1;
3834
+ }
3835
+ .git-history-entry {
3836
+ display: flex;
3837
+ flex-direction: column;
3838
+ gap: 2px;
3839
+ padding: 6px 12px;
3840
+ border-bottom: 1px solid var(--border);
3841
+ }
3842
+ .git-history-entry:hover {
3843
+ background: var(--hover-bg);
3844
+ }
3845
+ .git-history-hash {
3846
+ font-size: 10px;
3847
+ font-family: var(--font-mono);
3848
+ color: var(--accent);
3849
+ }
3850
+ .git-history-message {
3851
+ font-size: var(--spectrum-font-size-75, 12px);
3852
+ color: var(--fg);
3853
+ }
3854
+ .git-history-meta {
3855
+ font-size: 10px;
3856
+ color: var(--fg-dim);
3857
+ }
3858
+
3859
+ /* Utility */
3860
+ .git-loading {
3861
+ padding: 8px;
3862
+ text-align: center;
3863
+ color: var(--fg-dim);
3864
+ font-size: var(--spectrum-font-size-50, 11px);
3865
+ }
3866
+ .git-error {
3867
+ padding: 6px 8px;
3868
+ font-size: var(--spectrum-font-size-50, 11px);
3869
+ color: var(--danger);
3870
+ background: color-mix(in srgb, var(--danger) 8%, transparent);
3871
+ border-bottom: 1px solid var(--border);
3872
+ }
3873
+ .git-empty {
3874
+ padding: 16px 8px;
3875
+ text-align: center;
3876
+ color: var(--fg-dim);
3877
+ font-size: var(--spectrum-font-size-75, 12px);
3878
+ }
3879
+
3880
+ .git-panel-empty {
3881
+ justify-content: center;
3882
+ align-items: center;
3883
+ }
3884
+ .git-empty-state {
3885
+ display: flex;
3886
+ flex-direction: column;
3887
+ align-items: center;
3888
+ gap: 12px;
3889
+ padding: 24px 16px;
3890
+ text-align: center;
3891
+ color: var(--fg-dim);
3892
+ }
3893
+ .git-empty-state p {
3894
+ margin: 0;
3895
+ font-size: var(--spectrum-font-size-75, 12px);
3896
+ }
3897
+ .git-sync-bar--no-remote {
3898
+ gap: 8px;
3899
+ }
3900
+
3901
+ /* GitHub auth dialog */
3902
+ .github-auth-dialog {
3903
+ text-align: center;
3904
+ padding: 16px 0;
3905
+ }
3906
+ .github-auth-dialog p {
3907
+ margin: 8px 0;
3908
+ font-size: 13px;
3909
+ }
3910
+ .github-auth-code {
3911
+ font-size: 24px;
3912
+ font-weight: 700;
3913
+ letter-spacing: 2px;
3914
+ font-family: var(--font-mono, monospace);
3915
+ padding: 12px 16px;
3916
+ background: var(--hover-bg);
3917
+ border-radius: var(--radius);
3918
+ display: inline-block;
3919
+ margin: 8px 0;
3920
+ }
3921
+ .github-auth-waiting {
3922
+ color: var(--fg-dim);
3923
+ font-style: italic;
3924
+ }
3925
+
3926
+ /* GitHub publish dialog */
3927
+ .github-publish-dialog {
3928
+ display: flex;
3929
+ flex-direction: column;
3930
+ gap: 8px;
3931
+ padding: 8px 0;
3932
+ }
3933
+ .github-publish-dialog sp-textfield {
3934
+ width: 100%;
3935
+ }
3936
+
3937
+ /* ─── Feature toggle (stylebook) ─────────────── */
3938
+ .tb-toggle {
3939
+ padding: 3px 8px;
3940
+ font: inherit;
3941
+ font-size: var(--spectrum-font-size-50, 11px);
3942
+ color: var(--fg-dim);
3943
+ background: transparent;
3944
+ border: 1px solid var(--border);
3945
+ border-radius: var(--radius);
3946
+ cursor: pointer;
3947
+ }
3948
+ .tb-toggle:hover {
3949
+ background: var(--hover-bg);
3950
+ }
3951
+ .tb-toggle.active {
3952
+ color: var(--accent);
3953
+ border-color: var(--accent);
3954
+ background: var(--accent-15);
3955
+ }
3956
+
3957
+ /* ─── Stylebook ─────────────────────────────────── */
3958
+ .stylebook-style-header {
3959
+ padding: 6px 8px;
3960
+ font-size: var(--spectrum-font-size-50, 11px);
3961
+ font-weight: 600;
3962
+ color: var(--accent);
3963
+ border-bottom: 1px solid var(--border);
3964
+ font-family: var(--font-mono);
3965
+ }
3966
+
3967
+ /* Chrome bar (tabs + filter) above the canvas viewport */
3968
+ .sb-chrome {
3969
+ display: flex;
3970
+ align-items: center;
3971
+ padding: 4px 8px;
3972
+ background: var(--bg-panel);
3973
+ border-bottom: 1px solid var(--border);
3974
+ gap: 4px;
3975
+ flex-shrink: 0;
3976
+ }
3977
+
3978
+ /* Section layout in canvas */
3979
+ .sb-section {
3980
+ margin-bottom: 24px;
3981
+ }
3982
+ .sb-label {
3983
+ font-size: 10px;
3984
+ font-weight: 700;
3985
+ text-transform: uppercase;
3986
+ letter-spacing: 0.08em;
3987
+ color: var(--canvas-muted);
3988
+ padding: 8px 0 4px;
3989
+ border-bottom: 1px solid var(--canvas-rule);
3990
+ margin-bottom: 8px;
3991
+ }
3992
+ .sb-body {
3993
+ padding: 4px 0;
3994
+ display: flex;
3995
+ flex-direction: column;
3996
+ gap: 6px;
3997
+ }
3998
+
3999
+ /* Variable rows — unified layout for existing + add-new */
4000
+ .sb-var-row {
4001
+ display: flex;
4002
+ flex-direction: column;
4003
+ gap: 4px;
4004
+ padding: 10px 0;
4005
+ border-bottom: 1px solid var(--canvas-rule);
4006
+ }
4007
+ .sb-var-row:last-child {
4008
+ border-bottom: none;
4009
+ }
4010
+ .sb-var-row-header {
4011
+ display: flex;
4012
+ align-items: baseline;
4013
+ gap: 6px;
4014
+ min-height: 18px;
4015
+ flex-wrap: wrap;
4016
+ }
4017
+ .sb-var-row-title {
4018
+ font-weight: 600;
4019
+ font-size: var(--spectrum-font-size-75, 12px);
4020
+ color: var(--canvas-fg-2);
4021
+ white-space: nowrap;
4022
+ }
4023
+ .sb-var-row-ref {
4024
+ font-size: 10px;
4025
+ color: var(--canvas-muted);
4026
+ font-family: var(--font-mono);
4027
+ overflow: hidden;
4028
+ text-overflow: ellipsis;
4029
+ }
4030
+ .sb-var-row-header .sb-var-del {
4031
+ margin-left: auto;
4032
+ }
4033
+ .sb-var-row sp-textfield {
4034
+ pointer-events: auto;
4035
+ }
4036
+ /* Existing variable: horizontal swatch + value */
4037
+ .sb-var-input-row {
4038
+ display: flex;
4039
+ align-items: flex-end;
4040
+ gap: 8px;
4041
+ }
4042
+ .sb-var-col-name {
4043
+ min-width: 0;
4044
+ }
4045
+ .sb-var-col-value {
4046
+ flex: 1;
4047
+ min-width: 0;
4048
+ }
4049
+ .sb-var-col-name sp-textfield,
4050
+ .sb-var-col-value sp-textfield {
4051
+ width: 100%;
4052
+ }
4053
+ .sb-var-col-label {
4054
+ font-size: 10px;
4055
+ color: var(--canvas-dim);
4056
+ margin-bottom: 2px;
4057
+ font-weight: 500;
4058
+ }
4059
+ /* Add-new form: horizontal layout matching existing rows */
4060
+ .sb-var-row.is-new .sb-var-input-row {
4061
+ flex-wrap: nowrap;
4062
+ align-items: flex-end;
4063
+ }
4064
+ .sb-var-row.is-new .sb-var-col-name {
4065
+ flex: 2;
4066
+ min-width: 0;
4067
+ }
4068
+ .sb-var-row.is-new .sb-var-col-value {
4069
+ flex: 3;
4070
+ min-width: 0;
4071
+ }
4072
+ .sb-var-row.is-new .sb-var-swatch {
4073
+ align-self: flex-end;
4074
+ margin-bottom: 2px;
4075
+ }
4076
+ .sb-var-swatch {
4077
+ width: 28px;
4078
+ height: 28px;
4079
+ border-radius: var(--radius);
4080
+ border: 1px solid var(--canvas-border);
4081
+ cursor: pointer;
4082
+ position: relative;
4083
+ flex-shrink: 0;
4084
+ align-self: flex-end;
4085
+ margin-bottom: 2px;
4086
+ }
4087
+ .sb-var-swatch input[type="color"] {
4088
+ position: absolute;
4089
+ inset: 0;
4090
+ width: 100%;
4091
+ height: 100%;
4092
+ opacity: 0;
4093
+ cursor: pointer;
4094
+ pointer-events: auto;
4095
+ }
4096
+ .sb-var-preview {
4097
+ margin-top: 2px;
4098
+ padding: 8px;
4099
+ background: var(--canvas-bg-1);
4100
+ border-radius: var(--radius);
4101
+ border: 1px solid var(--canvas-rule);
4102
+ }
4103
+ .sb-var-font-preview {
4104
+ font-size: var(--spectrum-font-size-100, 14px);
4105
+ line-height: 1.4;
4106
+ color: var(--canvas-fg-2);
4107
+ }
4108
+ .sb-var-size-track {
4109
+ background: var(--canvas-track);
4110
+ height: 8px;
4111
+ border-radius: var(--radius);
4112
+ width: 100%;
4113
+ overflow: hidden;
4114
+ }
4115
+ .sb-var-size-bar {
4116
+ height: 100%;
4117
+ background: var(--accent, #3b82f6);
4118
+ transition: width 0.3s;
4119
+ border-radius: var(--radius);
4120
+ }
4121
+ .sb-var-del {
4122
+ opacity: 0;
4123
+ transition: opacity 0.15s;
4124
+ flex-shrink: 0;
4125
+ }
4126
+ .sb-var-row:hover .sb-var-del {
4127
+ opacity: 1;
4128
+ }
4129
+ .sb-var-empty {
4130
+ padding: 16px 8px;
4131
+ text-align: center;
4132
+ color: var(--canvas-light);
4133
+ font-size: var(--spectrum-font-size-75, 12px);
4134
+ font-style: italic;
4135
+ }
4136
+ .sb-var-add-btn {
4137
+ margin-top: 6px;
4138
+ pointer-events: auto;
4139
+ background: none;
4140
+ border: 1px dashed var(--canvas-border);
4141
+ border-radius: var(--radius);
4142
+ padding: 5px 10px;
4143
+ font-size: var(--spectrum-font-size-75, 12px);
4144
+ color: var(--canvas-fg-3);
4145
+ cursor: pointer;
4146
+ display: flex;
4147
+ align-items: center;
4148
+ gap: 4px;
4149
+ transition: all 0.15s;
4150
+ }
4151
+ .sb-var-add-btn:hover {
4152
+ border-color: var(--canvas-muted);
4153
+ color: var(--canvas-fg-2);
4154
+ background: var(--canvas-bg-1);
4155
+ }
4156
+ .sb-var-add-icon {
4157
+ font-size: var(--spectrum-font-size-100, 14px);
4158
+ font-weight: 600;
4159
+ }
4160
+ .sb-var-add-actions {
4161
+ display: flex;
4162
+ gap: 4px;
4163
+ align-items: center;
4164
+ flex-shrink: 0;
4165
+ align-self: flex-end;
4166
+ margin-bottom: 2px;
4167
+ }
4168
+ .sb-unit-input {
4169
+ position: relative;
4170
+ display: flex;
4171
+ align-items: center;
4172
+ width: 100%;
4173
+ }
4174
+ .sb-unit-input sp-textfield {
4175
+ width: 100%;
4176
+ }
4177
+ .sb-unit-input sp-picker {
4178
+ position: absolute;
4179
+ right: 2px;
4180
+ --mod-picker-border-width: 0;
4181
+ --mod-picker-min-width: 56px;
4182
+ }
4183
+ .sb-var-add-preview {
4184
+ font-size: 10px;
4185
+ color: var(--canvas-muted);
4186
+ font-family: var(--font-mono);
4187
+ min-height: 14px;
4188
+ }
4189
+
4190
+ /* ─── Inline editing ─────────────────────────── */
4191
+ .canvas-panel-canvas [contenteditable="true"] {
4192
+ outline: 2px solid var(--accent);
4193
+ outline-offset: 1px;
4194
+ cursor: text;
4195
+ min-height: 1.5em;
4196
+ border-radius: var(--spectrum-corner-radius-75, 2px);
4197
+ }
4198
+ .canvas-panel-canvas [contenteditable="true"]:focus {
4199
+ outline-color: var(--accent);
4200
+ box-shadow: 0 0 0 3px var(--accent-15);
4201
+ }
4202
+
4203
+ /* ─── Welcome screen ─────────────────────────── */
4204
+ .welcome-screen {
4205
+ width: 100%;
4206
+ height: 100%;
4207
+ display: flex;
4208
+ align-items: flex-start;
4209
+ justify-content: center;
4210
+ padding-top: 10vh;
4211
+ overflow-y: auto;
4212
+ }
4213
+ .welcome-content {
4214
+ max-width: 500px;
4215
+ width: 100%;
4216
+ padding: 0 24px;
4217
+ }
4218
+ .welcome-title {
4219
+ font-size: 28px;
4220
+ font-weight: 300;
4221
+ color: var(--fg);
4222
+ margin: 0;
4223
+ letter-spacing: -0.5px;
4224
+ }
4225
+ .welcome-subtitle {
4226
+ font-size: var(--spectrum-font-size-100, 14px);
4227
+ color: var(--fg-dim);
4228
+ margin: 2px 0 0;
4229
+ }
4230
+ .welcome-section {
4231
+ margin-top: 28px;
4232
+ }
4233
+ .welcome-section-title {
4234
+ font-size: 13px;
4235
+ font-weight: 600;
4236
+ color: var(--fg);
4237
+ margin: 0 0 8px;
4238
+ text-transform: uppercase;
4239
+ letter-spacing: 0.3px;
4240
+ }
4241
+ .welcome-action {
4242
+ display: flex;
4243
+ align-items: center;
4244
+ gap: 8px;
4245
+ width: 100%;
4246
+ padding: 5px 8px;
4247
+ margin: 0;
4248
+ background: none;
4249
+ border: none;
4250
+ border-radius: var(--radius);
4251
+ font: inherit;
4252
+ font-size: 13px;
4253
+ color: var(--accent);
4254
+ cursor: pointer;
4255
+ text-align: left;
4256
+ }
4257
+ .welcome-action:hover {
4258
+ background: var(--hover-bg);
4259
+ text-decoration: underline;
4260
+ }
4261
+ .welcome-action-icon {
4262
+ flex-shrink: 0;
4263
+ opacity: 0.8;
4264
+ }
4265
+ a.welcome-action {
4266
+ text-decoration: none;
4267
+ box-sizing: border-box;
4268
+ }
4269
+ .welcome-install-note {
4270
+ margin: 4px 8px 0;
4271
+ font-size: 12px;
4272
+ color: var(--fg-dim);
4273
+ }
4274
+ .welcome-recent {
4275
+ display: flex;
4276
+ align-items: baseline;
4277
+ gap: 12px;
4278
+ width: 100%;
4279
+ padding: 4px 8px;
4280
+ margin: 0;
4281
+ background: none;
4282
+ border: none;
4283
+ border-radius: var(--radius);
4284
+ font: inherit;
4285
+ font-size: 13px;
4286
+ color: var(--fg);
4287
+ cursor: pointer;
4288
+ text-align: left;
4289
+ }
4290
+ .welcome-recent:hover {
4291
+ background: var(--hover-bg);
4292
+ }
4293
+ .welcome-recent-name {
4294
+ color: var(--accent);
4295
+ flex-shrink: 0;
4296
+ }
4297
+ .welcome-recent-name:hover {
4298
+ text-decoration: underline;
4299
+ }
4300
+ .welcome-recent-path {
4301
+ color: var(--fg-dim);
4302
+ font-size: var(--spectrum-font-size-75, 12px);
4303
+ overflow: hidden;
4304
+ text-overflow: ellipsis;
4305
+ white-space: nowrap;
4306
+ }
4307
+ .welcome-section-header {
4308
+ display: flex;
4309
+ align-items: baseline;
4310
+ justify-content: space-between;
4311
+ gap: 12px;
4312
+ }
4313
+ .welcome-clear {
4314
+ padding: 0 4px;
4315
+ background: none;
4316
+ border: none;
4317
+ font: inherit;
4318
+ font-size: var(--spectrum-font-size-75, 12px);
4319
+ color: var(--fg-dim);
4320
+ cursor: pointer;
4321
+ }
4322
+ .welcome-clear:hover {
4323
+ color: var(--fg);
4324
+ text-decoration: underline;
4325
+ }
4326
+ .welcome-recent-row {
4327
+ display: flex;
4328
+ align-items: center;
4329
+ }
4330
+ .welcome-recent-row .welcome-recent {
4331
+ flex: 1;
4332
+ min-width: 0;
4333
+ }
4334
+ .welcome-recent-remove {
4335
+ flex-shrink: 0;
4336
+ padding: 2px 6px;
4337
+ background: none;
4338
+ border: none;
4339
+ font: inherit;
4340
+ font-size: var(--spectrum-font-size-75, 12px);
4341
+ color: var(--fg-dim);
4342
+ cursor: pointer;
4343
+ opacity: 0;
4344
+ border-radius: var(--radius);
4345
+ }
4346
+ .welcome-recent-row:hover .welcome-recent-remove {
4347
+ opacity: 1;
4348
+ }
4349
+ .welcome-recent-remove:hover {
4350
+ color: var(--fg);
4351
+ background: var(--hover-bg);
4352
+ }
4353
+
4354
+ /* ─── Grid editor (Tabulator theme over Spectrum tokens) ─────────────── */
4355
+ .jx-grid {
4356
+ display: flex;
4357
+ flex-direction: column;
4358
+ height: 100%;
4359
+ min-height: 0;
4360
+ background: var(--bg);
4361
+ }
4362
+ .jx-grid-toolbar {
4363
+ display: flex;
4364
+ align-items: center;
4365
+ gap: 6px;
4366
+ padding: 6px 10px;
4367
+ border-bottom: 1px solid var(--border);
4368
+ background: var(--bg-panel);
4369
+ flex-shrink: 0;
4370
+ }
4371
+ .jx-grid-toolbar sp-search {
4372
+ width: 200px;
4373
+ }
4374
+ .jx-grid-spacer {
4375
+ flex: 1;
4376
+ }
4377
+ .jx-grid-note {
4378
+ font-size: var(--spectrum-font-size-50, 11px);
4379
+ color: var(--fg-dim);
4380
+ border: 1px solid var(--border);
4381
+ border-radius: var(--radius);
4382
+ padding: 1px 6px;
4383
+ cursor: help;
4384
+ }
4385
+ .jx-grid-count {
4386
+ font-size: var(--spectrum-font-size-75, 12px);
4387
+ color: var(--fg-dim);
4388
+ white-space: nowrap;
4389
+ }
4390
+ .jx-grid-error-text {
4391
+ color: var(--danger);
4392
+ }
4393
+ .jx-grid-host {
4394
+ flex: 1;
4395
+ min-height: 0;
4396
+ }
4397
+ .jx-grid-missing {
4398
+ padding: 24px;
4399
+ color: var(--fg-dim);
4400
+ }
4401
+
4402
+ /* Tabulator structural overrides — tokens only, scoped under .jx-grid. */
4403
+ .jx-grid .tabulator {
4404
+ background: var(--bg);
4405
+ color: var(--fg);
4406
+ border: none;
4407
+ font-size: var(--spectrum-font-size-75, 12px);
4408
+ height: 100%;
4409
+ }
4410
+ .jx-grid .tabulator .tabulator-header {
4411
+ background: var(--bg-panel);
4412
+ color: var(--fg);
4413
+ border-bottom: 1px solid var(--border);
4414
+ }
4415
+ .jx-grid .tabulator .tabulator-header .tabulator-col {
4416
+ background: var(--bg-panel);
4417
+ border-right: 1px solid var(--border);
4418
+ }
4419
+ .jx-grid .tabulator .tabulator-header .tabulator-col .tabulator-col-title {
4420
+ color: var(--fg);
4421
+ font-weight: 600;
4422
+ }
4423
+ .jx-grid .tabulator .tabulator-header .tabulator-header-filter input {
4424
+ background: var(--bg);
4425
+ color: var(--fg);
4426
+ border: 1px solid var(--border);
4427
+ border-radius: var(--spectrum-corner-radius-75, 2px);
4428
+ padding: 1px 4px;
4429
+ font: inherit;
4430
+ }
4431
+ .jx-grid .tabulator .tabulator-tableholder {
4432
+ background: var(--bg);
4433
+ }
4434
+ .jx-grid .tabulator .tabulator-row {
4435
+ background: var(--bg);
4436
+ color: var(--fg);
4437
+ border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
4438
+ min-height: 26px;
4439
+ }
4440
+ .jx-grid .tabulator .tabulator-row.tabulator-row-even {
4441
+ background: color-mix(in srgb, var(--bg-panel) 45%, var(--bg));
4442
+ }
4443
+ .jx-grid .tabulator .tabulator-row.tabulator-selected {
4444
+ background: color-mix(in srgb, var(--accent) 16%, var(--bg));
4445
+ }
4446
+ .jx-grid .tabulator .tabulator-row .tabulator-cell {
4447
+ border-right: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
4448
+ padding: 3px 8px;
4449
+ }
4450
+ .jx-grid .tabulator .tabulator-row .tabulator-cell.tabulator-frozen {
4451
+ background: var(--bg-panel);
4452
+ border-right: 1px solid var(--border);
4453
+ }
4454
+ .jx-grid .tabulator .tabulator-range {
4455
+ border: 1px solid var(--accent);
4456
+ background: color-mix(in srgb, var(--accent) 10%, transparent);
4457
+ }
4458
+ .jx-grid .tabulator .tabulator-range-overlay .tabulator-range-cell-active {
4459
+ border: 2px solid var(--accent);
4460
+ }
4461
+ .jx-grid .tabulator .tabulator-placeholder .tabulator-placeholder-contents {
4462
+ color: var(--fg-dim);
4463
+ background: transparent;
4464
+ }
4465
+
4466
+ /* Buffer-state paint (dirty / error / stale / pending rows). */
4467
+ .jx-grid .tabulator-cell.jx-grid-cell--dirty {
4468
+ box-shadow: inset 2px 0 0 var(--accent);
4469
+ background: color-mix(in srgb, var(--accent) 8%, transparent);
4470
+ }
4471
+ .jx-grid .tabulator-cell.jx-grid-cell--error {
4472
+ box-shadow: inset 2px 0 0 var(--danger);
4473
+ background: color-mix(in srgb, var(--danger) 12%, transparent);
4474
+ }
4475
+ .jx-grid .tabulator-cell.jx-grid-cell--stale {
4476
+ opacity: 0.65;
4477
+ }
4478
+ .jx-grid .tabulator-row.jx-grid-row--pending-delete .tabulator-cell {
4479
+ text-decoration: line-through;
4480
+ opacity: 0.55;
4481
+ }
4482
+ .jx-grid .tabulator-row.jx-grid-row--pending-insert {
4483
+ background: color-mix(in srgb, var(--success, var(--accent)) 10%, var(--bg));
4484
+ }
4485
+ .jx-grid .tabulator-row.jx-grid-row--stale {
4486
+ outline: 1px dashed var(--fg-dim);
4487
+ outline-offset: -1px;
4488
+ }
4489
+
4490
+ /* Cell content + in-cell editors. */
4491
+ .jx-grid-cell-content {
4492
+ overflow: hidden;
4493
+ text-overflow: ellipsis;
4494
+ white-space: nowrap;
4495
+ }
4496
+ .jx-grid-kind-number {
4497
+ text-align: right;
4498
+ font-variant-numeric: tabular-nums;
4499
+ }
4500
+ .jx-grid-kind-readonly {
4501
+ color: var(--fg-dim);
4502
+ font-family: var(--font-mono);
4503
+ font-size: var(--spectrum-font-size-50, 11px);
4504
+ }
4505
+ .jx-grid-chip {
4506
+ display: inline-block;
4507
+ background: color-mix(in srgb, var(--accent) 18%, transparent);
4508
+ border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
4509
+ border-radius: 8px;
4510
+ padding: 0 6px;
4511
+ margin-right: 4px;
4512
+ font-size: var(--spectrum-font-size-50, 11px);
4513
+ line-height: 16px;
4514
+ }
4515
+ .jx-grid-editor {
4516
+ width: 100%;
4517
+ height: 100%;
4518
+ display: flex;
4519
+ align-items: center;
4520
+ }
4521
+ .jx-grid-editor .jx-grid-input,
4522
+ .jx-grid-editor .jx-grid-select {
4523
+ width: 100%;
4524
+ background: var(--bg);
4525
+ color: var(--fg);
4526
+ border: 1px solid var(--accent);
4527
+ border-radius: var(--spectrum-corner-radius-75, 2px);
4528
+ padding: 2px 6px;
4529
+ font: inherit;
4530
+ outline: none;
4531
+ }
4532
+ .jx-grid-editor .jx-grid-checkbox {
4533
+ margin: 0 auto;
4534
+ accent-color: var(--accent);
4535
+ }
4536
+ .jx-grid-pill-editor .jx-grid-pills {
4537
+ display: flex;
4538
+ flex-wrap: wrap;
4539
+ gap: 2px;
4540
+ align-items: center;
4541
+ width: 100%;
4542
+ background: var(--bg);
4543
+ border: 1px solid var(--accent);
4544
+ border-radius: var(--spectrum-corner-radius-75, 2px);
4545
+ padding: 1px 4px;
4546
+ }
4547
+ .jx-grid-pill-input {
4548
+ flex: 1;
4549
+ min-width: 60px;
4550
+ background: transparent;
4551
+ border: none;
4552
+ outline: none;
4553
+ color: var(--fg);
4554
+ font: inherit;
4555
+ }
4556
+ .jx-grid-chip-x {
4557
+ background: none;
4558
+ border: none;
4559
+ color: inherit;
4560
+ cursor: pointer;
4561
+ padding: 0 0 0 4px;
4562
+ font: inherit;
4563
+ line-height: 1;
4564
+ }
4565
+ .jx-grid-chip-x:hover {
4566
+ color: var(--danger);
4567
+ }
4568
+ .jx-grid-cell-popover-body {
4569
+ display: flex;
4570
+ flex-direction: column;
4571
+ gap: 8px;
4572
+ padding: 10px;
4573
+ min-width: 260px;
4574
+ }
4575
+ .jx-grid-cell-popover-title {
4576
+ font-weight: 600;
4577
+ font-size: var(--spectrum-font-size-75, 12px);
4578
+ }
4579
+ .jx-grid-cell-popover-hint {
4580
+ color: var(--fg-dim);
4581
+ font-size: var(--spectrum-font-size-50, 11px);
4582
+ }
4583
+ .jx-grid-cell-popover-actions {
4584
+ display: flex;
4585
+ justify-content: flex-end;
4586
+ }
4587
+ .jx-grid-cell-popover .jx-grid-select,
4588
+ .jx-grid-cell-popover .jx-grid-input {
4589
+ width: 100%;
4590
+ background: var(--bg);
4591
+ color: var(--fg);
4592
+ border: 1px solid var(--border);
4593
+ border-radius: var(--spectrum-corner-radius-75, 2px);
4594
+ padding: 3px 6px;
4595
+ font: inherit;
4596
+ }
4597
+ </style>
4598
+ </head>
4599
+ <body>
4600
+ <sp-theme color="dark" scale="medium" system="spectrum">
4601
+ <div id="app">
4602
+ <div id="toolbar"></div>
4603
+ <div id="tab-strip"></div>
4604
+ <div id="tab-bar"></div>
4605
+ <div id="frontmatter-panel" hidden></div>
4606
+ <div id="activity-bar"></div>
4607
+ <div id="left-panel"></div>
4608
+ <div id="resize-left" class="resize-handle"></div>
4609
+ <div id="canvas-wrap"></div>
4610
+ <div id="resize-right" class="resize-handle"></div>
4611
+ <div id="right-panel"></div>
4612
+ <div id="resize-chat" class="resize-handle"></div>
4613
+ <div id="chat-panel"></div>
4614
+ <div id="statusbar"></div>
4615
+ </div>
4616
+ <div
4617
+ id="layer-popover"
4618
+ style="position: fixed; inset: 0; pointer-events: none; z-index: 1000"
4619
+ ></div>
4620
+ <div
4621
+ id="layer-modal"
4622
+ style="position: fixed; inset: 0; pointer-events: none; z-index: 2000"
4623
+ ></div>
4624
+ <div
4625
+ id="layer-dialog"
4626
+ style="position: fixed; inset: 0; pointer-events: none; z-index: 3000"
4627
+ ></div>
4628
+ </sp-theme>
4629
+ <script type="module" src="./dist/studio.js"></script>
4630
+ </body>
4631
+ </html>