@westopp/windo 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +146 -0
  3. package/dist/chunk-5RM2VYAM.js +150 -0
  4. package/dist/chunk-5RM2VYAM.js.map +1 -0
  5. package/dist/cli.cjs +303 -0
  6. package/dist/cli.cjs.map +1 -0
  7. package/dist/cli.d.cts +1 -0
  8. package/dist/cli.d.ts +1 -0
  9. package/dist/cli.js +138 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/index.cjs +219 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.cts +374 -0
  14. package/dist/index.d.ts +374 -0
  15. package/dist/index.js +182 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/plugin.cjs +185 -0
  18. package/dist/plugin.cjs.map +1 -0
  19. package/dist/plugin.d.cts +11 -0
  20. package/dist/plugin.d.ts +11 -0
  21. package/dist/plugin.js +11 -0
  22. package/dist/plugin.js.map +1 -0
  23. package/package.json +95 -0
  24. package/src/cli/index.ts +160 -0
  25. package/src/client/App.tsx +310 -0
  26. package/src/client/Canvas.tsx +358 -0
  27. package/src/client/Inspector.tsx +586 -0
  28. package/src/client/Sidebar.tsx +108 -0
  29. package/src/client/bridge.ts +124 -0
  30. package/src/client/chrome.css +1966 -0
  31. package/src/client/icons.tsx +110 -0
  32. package/src/client/index.ts +15 -0
  33. package/src/client/internal-types.ts +147 -0
  34. package/src/client/persist.ts +38 -0
  35. package/src/define-config.ts +54 -0
  36. package/src/descriptor.test.ts +59 -0
  37. package/src/descriptor.ts +185 -0
  38. package/src/globals.d.ts +9 -0
  39. package/src/index.ts +54 -0
  40. package/src/plugin/index.ts +181 -0
  41. package/src/preview/ctx.ts +43 -0
  42. package/src/preview/index.ts +283 -0
  43. package/src/preview/preview.css +81 -0
  44. package/src/preview/registry.ts +159 -0
  45. package/src/preview/render.tsx +90 -0
  46. package/src/preview/virtual.d.ts +8 -0
  47. package/src/protocol.ts +59 -0
  48. package/src/types.ts +319 -0
@@ -0,0 +1,1966 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:ital,wght@0,400..700;1,400..700&display=swap");
2
+
3
+ /* ============================================================
4
+ Workbench chrome — clean neutral identity.
5
+ White panels on light grey, hairline borders, rounded
6
+ geometry, near-black accent. Mono reserved for code.
7
+ ============================================================ */
8
+
9
+ :root {
10
+ --bg: #f4f4f5;
11
+ --panel: #ffffff;
12
+ --panel2: #fafafa;
13
+ --inset: #f1f1f2;
14
+ --border: #e8e8ea;
15
+ --border-strong: #dcdcdf;
16
+ --text: #161618;
17
+ --muted: #6e6e73;
18
+ --faint: #a5a5ab;
19
+ --accent: #161618;
20
+ --accent-ui: var(--accent);
21
+ --accent-text: #ffffff;
22
+ --accent-soft: color-mix(in srgb, var(--accent) 8%, transparent);
23
+ --danger: #c0443c;
24
+ --surface: #ffffff;
25
+ --shadow: 0 1px 2px rgba(16, 16, 18, 0.04), 0 8px 24px rgba(16, 16, 18, 0.06);
26
+ --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
27
+ --sans: "Instrument Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
28
+ --r: 8px;
29
+ }
30
+
31
+ [data-theme="dark"] {
32
+ --bg: #111113;
33
+ --panel: #1a1a1c;
34
+ --panel2: #161618;
35
+ --inset: #242427;
36
+ --border: #29292d;
37
+ --border-strong: #39393e;
38
+ --text: #ececee;
39
+ --muted: #9b9ba2;
40
+ --faint: #5c5c63;
41
+ --accent-ui: color-mix(in oklab, var(--accent) 35%, white);
42
+ --accent-soft: color-mix(in srgb, var(--accent-ui) 14%, transparent);
43
+ --danger: #e0837b;
44
+ --surface: #161618;
45
+ --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 32px rgba(0, 0, 0, 0.45);
46
+ }
47
+
48
+ * {
49
+ box-sizing: border-box;
50
+ }
51
+
52
+ html,
53
+ body {
54
+ margin: 0;
55
+ height: 100%;
56
+ }
57
+
58
+ body {
59
+ font-family: var(--sans);
60
+ font-size: 13px;
61
+ color: var(--text);
62
+ background: var(--bg);
63
+ -webkit-font-smoothing: antialiased;
64
+ }
65
+
66
+ #root {
67
+ height: 100%;
68
+ }
69
+
70
+ button {
71
+ font: inherit;
72
+ color: inherit;
73
+ }
74
+
75
+ ::selection {
76
+ background: color-mix(in srgb, var(--text) 12%, transparent);
77
+ }
78
+
79
+ /* ---------- App layout ---------- */
80
+
81
+ .wb-app {
82
+ display: flex;
83
+ flex-direction: column;
84
+ height: 100%;
85
+ overflow: hidden;
86
+ }
87
+
88
+ .wb-main {
89
+ display: flex;
90
+ flex: 1;
91
+ min-height: 0;
92
+ }
93
+
94
+ .wb-center {
95
+ display: flex;
96
+ flex-direction: column;
97
+ flex: 1;
98
+ min-width: 0;
99
+ }
100
+
101
+ .wb-center-row {
102
+ display: flex;
103
+ flex: 1;
104
+ min-height: 0;
105
+ }
106
+
107
+ .wb-canvas-col {
108
+ display: flex;
109
+ flex-direction: column;
110
+ flex: 1;
111
+ min-width: 0;
112
+ container-type: inline-size;
113
+ container-name: canvastools;
114
+ }
115
+
116
+ /* ---------- Top bar ---------- */
117
+
118
+ .wb-topbar {
119
+ display: flex;
120
+ align-items: center;
121
+ gap: 16px;
122
+ height: 50px;
123
+ padding: 0 16px;
124
+ background: var(--panel);
125
+ border-bottom: 1px solid var(--border);
126
+ flex-shrink: 0;
127
+ }
128
+
129
+ .wb-logo {
130
+ display: flex;
131
+ align-items: center;
132
+ gap: 9px;
133
+ font-size: 13.5px;
134
+ font-weight: 650;
135
+ letter-spacing: -0.01em;
136
+ }
137
+
138
+ .wb-logo-mark {
139
+ width: 22px;
140
+ height: 22px;
141
+ border-radius: 6px;
142
+ background: var(--text);
143
+ color: var(--panel);
144
+ display: grid;
145
+ place-items: center;
146
+ font-size: 10.5px;
147
+ font-weight: 700;
148
+ }
149
+
150
+ .wb-logo-sub {
151
+ color: var(--faint);
152
+ font-weight: 500;
153
+ }
154
+
155
+ .wb-crumb {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: 7px;
159
+ color: var(--muted);
160
+ font-size: 12.5px;
161
+ min-width: 0;
162
+ }
163
+
164
+ .wb-crumb b {
165
+ color: var(--text);
166
+ font-weight: 600;
167
+ }
168
+ .wb-crumb .sep {
169
+ color: var(--faint);
170
+ }
171
+
172
+ .wb-topbar-spacer {
173
+ flex: 1;
174
+ }
175
+
176
+ .wb-version {
177
+ font-size: 11.5px;
178
+ color: var(--faint);
179
+ }
180
+
181
+ /* ---------- Generic icon button ---------- */
182
+
183
+ .wb-iconbtn {
184
+ display: inline-flex;
185
+ align-items: center;
186
+ justify-content: center;
187
+ gap: 6px;
188
+ height: 30px;
189
+ min-width: 30px;
190
+ padding: 0 7px;
191
+ border: 1px solid transparent;
192
+ border-radius: var(--r);
193
+ background: transparent;
194
+ color: var(--muted);
195
+ cursor: pointer;
196
+ transition:
197
+ background 0.12s,
198
+ color 0.12s,
199
+ border-color 0.12s;
200
+ }
201
+
202
+ .wb-iconbtn:hover {
203
+ background: var(--inset);
204
+ color: var(--text);
205
+ }
206
+
207
+ .wb-iconbtn.active {
208
+ background: var(--accent-soft);
209
+ color: var(--accent-ui);
210
+ }
211
+
212
+ .wb-iconbtn svg {
213
+ display: block;
214
+ }
215
+
216
+ /* ---------- Sidebar ---------- */
217
+
218
+ .wb-sidebar {
219
+ width: 240px;
220
+ flex-shrink: 0;
221
+ background: var(--panel);
222
+ border-right: 1px solid var(--border);
223
+ display: flex;
224
+ flex-direction: column;
225
+ min-height: 0;
226
+ }
227
+
228
+ .wb-sidebar.collapsed {
229
+ width: 44px;
230
+ align-items: center;
231
+ padding: 8px 0;
232
+ gap: 12px;
233
+ }
234
+
235
+ .wb-rail-label {
236
+ writing-mode: vertical-rl;
237
+ font-size: 10px;
238
+ font-weight: 600;
239
+ letter-spacing: 0.08em;
240
+ text-transform: uppercase;
241
+ color: var(--faint);
242
+ user-select: none;
243
+ }
244
+
245
+ .wb-sidebar-head {
246
+ display: flex;
247
+ align-items: center;
248
+ gap: 6px;
249
+ margin: 12px 12px 6px 12px;
250
+ }
251
+
252
+ .wb-search {
253
+ position: relative;
254
+ flex: 1;
255
+ min-width: 0;
256
+ }
257
+
258
+ .wb-search svg {
259
+ position: absolute;
260
+ left: 10px;
261
+ top: 50%;
262
+ transform: translateY(-50%);
263
+ color: var(--faint);
264
+ pointer-events: none;
265
+ }
266
+
267
+ .wb-search input {
268
+ width: 100%;
269
+ height: 32px;
270
+ padding: 0 10px 0 31px;
271
+ border: 1px solid var(--border);
272
+ border-radius: var(--r);
273
+ background: var(--panel2);
274
+ color: var(--text);
275
+ font: inherit;
276
+ font-size: 12.5px;
277
+ outline: none;
278
+ transition:
279
+ border-color 0.12s,
280
+ box-shadow 0.12s;
281
+ }
282
+
283
+ .wb-search input::placeholder {
284
+ color: var(--faint);
285
+ }
286
+
287
+ .wb-search input:focus {
288
+ border-color: var(--border-strong);
289
+ box-shadow: 0 0 0 3px var(--accent-soft);
290
+ }
291
+
292
+ .wb-nav {
293
+ flex: 1;
294
+ overflow-y: auto;
295
+ padding: 4px 12px 16px 12px;
296
+ }
297
+
298
+ .wb-nav-group {
299
+ margin-top: 18px;
300
+ }
301
+
302
+ .wb-nav-group-label {
303
+ display: flex;
304
+ align-items: center;
305
+ gap: 6px;
306
+ width: 100%;
307
+ border: none;
308
+ background: transparent;
309
+ cursor: pointer;
310
+ font-size: 10.5px;
311
+ font-weight: 600;
312
+ letter-spacing: 0.07em;
313
+ text-transform: uppercase;
314
+ color: var(--faint);
315
+ padding: 3px 8px;
316
+ margin-bottom: 3px;
317
+ border-radius: var(--r);
318
+ transition: color 0.12s;
319
+ }
320
+
321
+ .wb-nav-group-label:hover {
322
+ color: var(--muted);
323
+ }
324
+
325
+ .wb-nav-group-label .chev {
326
+ flex-shrink: 0;
327
+ transition: transform 0.15s;
328
+ }
329
+
330
+ .wb-nav-group-label.closed .chev {
331
+ transform: rotate(-90deg);
332
+ }
333
+
334
+ .wb-nav-group-label .grow {
335
+ flex: 1;
336
+ }
337
+
338
+ .wb-nav-group-label .cnt {
339
+ font-weight: 500;
340
+ letter-spacing: 0;
341
+ font-variant-numeric: tabular-nums;
342
+ }
343
+
344
+ .wb-nav-group-label .seldot {
345
+ width: 5px;
346
+ height: 5px;
347
+ border-radius: 50%;
348
+ background: var(--accent-ui);
349
+ flex-shrink: 0;
350
+ }
351
+
352
+ .wb-nav-list {
353
+ display: flex;
354
+ flex-direction: column;
355
+ gap: 1px;
356
+ }
357
+
358
+ .wb-nav-item {
359
+ display: flex;
360
+ align-items: center;
361
+ gap: 8px;
362
+ width: 100%;
363
+ height: 31px;
364
+ padding: 0 9px;
365
+ border: none;
366
+ border-radius: var(--r);
367
+ background: transparent;
368
+ color: var(--muted);
369
+ font-size: 13px;
370
+ text-align: left;
371
+ cursor: pointer;
372
+ transition:
373
+ background 0.1s,
374
+ color 0.1s;
375
+ }
376
+
377
+ .wb-nav-item:hover {
378
+ background: var(--inset);
379
+ color: var(--text);
380
+ }
381
+
382
+ .wb-nav-item.selected {
383
+ background: var(--inset);
384
+ color: var(--text);
385
+ font-weight: 600;
386
+ }
387
+
388
+ .wb-nav-item .name {
389
+ flex: 1;
390
+ overflow: hidden;
391
+ text-overflow: ellipsis;
392
+ white-space: nowrap;
393
+ }
394
+
395
+ .wb-status {
396
+ font-size: 10px;
397
+ font-weight: 600;
398
+ padding: 2px 7px;
399
+ border-radius: 999px;
400
+ text-transform: capitalize;
401
+ flex-shrink: 0;
402
+ }
403
+
404
+ .wb-status.stable {
405
+ color: #3c7a4a;
406
+ background: rgba(60, 122, 74, 0.1);
407
+ }
408
+ .wb-status.beta {
409
+ color: #99661c;
410
+ background: rgba(153, 102, 28, 0.1);
411
+ }
412
+ .wb-status.deprecated {
413
+ color: #a8433a;
414
+ background: rgba(168, 67, 58, 0.1);
415
+ }
416
+
417
+ [data-theme="dark"] .wb-status.stable {
418
+ color: #84c896;
419
+ background: rgba(132, 200, 150, 0.12);
420
+ }
421
+ [data-theme="dark"] .wb-status.beta {
422
+ color: #dcb064;
423
+ background: rgba(220, 176, 100, 0.12);
424
+ }
425
+ [data-theme="dark"] .wb-status.deprecated {
426
+ color: #e6918a;
427
+ background: rgba(230, 145, 138, 0.12);
428
+ }
429
+
430
+ .wb-nav-empty {
431
+ padding: 20px 8px;
432
+ color: var(--faint);
433
+ font-size: 12.5px;
434
+ text-align: center;
435
+ }
436
+
437
+ /* ---------- Canvas toolbar ---------- */
438
+
439
+ .wb-toolbar {
440
+ position: relative;
441
+ display: flex;
442
+ align-items: center;
443
+ gap: 10px;
444
+ height: 46px;
445
+ padding: 0 12px;
446
+ background: var(--panel);
447
+ border-bottom: 1px solid var(--border);
448
+ flex-shrink: 0;
449
+ }
450
+
451
+ .wb-toolbar .gap {
452
+ flex: 1 1 0;
453
+ min-width: 0;
454
+ }
455
+
456
+ .wb-toolbar > * {
457
+ flex-shrink: 0;
458
+ }
459
+
460
+ .wb-seg {
461
+ display: flex;
462
+ align-items: center;
463
+ gap: 2px;
464
+ padding: 2px;
465
+ background: var(--inset);
466
+ border-radius: 999px;
467
+ }
468
+
469
+ .wb-seg button {
470
+ display: inline-flex;
471
+ align-items: center;
472
+ gap: 5px;
473
+ height: 25px;
474
+ padding: 0 11px;
475
+ border: none;
476
+ border-radius: 999px;
477
+ background: transparent;
478
+ color: var(--muted);
479
+ font-size: 12px;
480
+ font-weight: 550;
481
+ cursor: pointer;
482
+ transition:
483
+ background 0.12s,
484
+ color 0.12s;
485
+ }
486
+
487
+ .wb-seg button:hover {
488
+ color: var(--text);
489
+ }
490
+
491
+ .wb-seg button.on {
492
+ background: var(--panel);
493
+ color: var(--text);
494
+ box-shadow: 0 1px 3px rgba(16, 16, 18, 0.1);
495
+ }
496
+
497
+ /* Trigger button (lives outside the canvas) */
498
+
499
+ .wb-trigger {
500
+ display: inline-flex;
501
+ align-items: center;
502
+ gap: 7px;
503
+ height: 29px;
504
+ padding: 0 13px;
505
+ border: 1px solid var(--border-strong);
506
+ border-radius: 999px;
507
+ background: transparent;
508
+ color: var(--text);
509
+ font-size: 12px;
510
+ font-weight: 550;
511
+ cursor: pointer;
512
+ transition:
513
+ background 0.12s,
514
+ color 0.12s,
515
+ border-color 0.12s;
516
+ }
517
+
518
+ .wb-trigger:hover {
519
+ background: var(--inset);
520
+ }
521
+
522
+ .wb-trigger.on {
523
+ background: var(--accent);
524
+ border-color: var(--accent);
525
+ color: var(--accent-text);
526
+ }
527
+
528
+ [data-theme="dark"] .wb-trigger.on {
529
+ background: var(--accent-ui);
530
+ border-color: var(--accent-ui);
531
+ color: #111113;
532
+ }
533
+
534
+ .wb-trigger .tdot {
535
+ width: 6px;
536
+ height: 6px;
537
+ border-radius: 50%;
538
+ background: currentColor;
539
+ }
540
+
541
+ /* Action buttons (out-of-band triggers; live outside the canvas) */
542
+
543
+ .wb-action {
544
+ display: inline-flex;
545
+ align-items: center;
546
+ height: 29px;
547
+ padding: 0 13px;
548
+ border: 1px solid var(--border-strong);
549
+ border-radius: 999px;
550
+ background: transparent;
551
+ color: var(--text);
552
+ font-size: 12px;
553
+ font-weight: 550;
554
+ cursor: pointer;
555
+ transition:
556
+ background 0.12s,
557
+ color 0.12s,
558
+ border-color 0.12s,
559
+ opacity 0.12s;
560
+ }
561
+
562
+ .wb-action:hover:not(:disabled) {
563
+ background: var(--inset);
564
+ }
565
+
566
+ .wb-action:disabled {
567
+ opacity: 0.4;
568
+ cursor: not-allowed;
569
+ }
570
+
571
+ .wb-zoom {
572
+ display: flex;
573
+ align-items: center;
574
+ gap: 2px;
575
+ }
576
+
577
+ .wb-zoom .pct {
578
+ font-size: 11.5px;
579
+ font-variant-numeric: tabular-nums;
580
+ color: var(--muted);
581
+ width: 40px;
582
+ text-align: center;
583
+ cursor: pointer;
584
+ }
585
+
586
+ /* ---------- Canvas settings popover ---------- */
587
+
588
+ .wb-pop-overlay {
589
+ position: fixed;
590
+ inset: 0;
591
+ z-index: 49;
592
+ }
593
+
594
+ .wb-pop {
595
+ position: absolute;
596
+ top: calc(100% + 8px);
597
+ right: 10px;
598
+ width: 270px;
599
+ background: var(--panel);
600
+ border: 1px solid var(--border);
601
+ border-radius: 12px;
602
+ box-shadow: var(--shadow);
603
+ z-index: 50;
604
+ padding: 14px 16px 16px 16px;
605
+ }
606
+
607
+ .wb-pop-title {
608
+ font-size: 12.5px;
609
+ font-weight: 600;
610
+ color: var(--text);
611
+ margin-bottom: 4px;
612
+ }
613
+
614
+ .wb-pop-row {
615
+ display: flex;
616
+ align-items: center;
617
+ justify-content: space-between;
618
+ gap: 10px;
619
+ margin-top: 9px;
620
+ }
621
+
622
+ .wb-pop-row .lbl {
623
+ font-size: 12px;
624
+ color: var(--muted);
625
+ flex-shrink: 0;
626
+ }
627
+
628
+ .wb-pop-row input[type="range"] {
629
+ flex: 1;
630
+ accent-color: var(--accent-ui);
631
+ min-width: 0;
632
+ }
633
+
634
+ .wb-pop-row .val {
635
+ font-size: 11px;
636
+ font-variant-numeric: tabular-nums;
637
+ color: var(--muted);
638
+ width: 36px;
639
+ text-align: right;
640
+ }
641
+
642
+ .wb-pop-sect {
643
+ display: flex;
644
+ align-items: center;
645
+ gap: 8px;
646
+ font-size: 10.5px;
647
+ font-weight: 600;
648
+ letter-spacing: 0.07em;
649
+ text-transform: uppercase;
650
+ color: var(--faint);
651
+ margin: 16px 0 2px 0;
652
+ }
653
+
654
+ .wb-pop-sect .live {
655
+ color: var(--text);
656
+ }
657
+
658
+ .wb-colorinput {
659
+ position: relative;
660
+ display: inline-flex;
661
+ align-items: center;
662
+ gap: 8px;
663
+ height: 28px;
664
+ padding: 0 10px 0 5px;
665
+ border: 1px solid var(--border);
666
+ border-radius: var(--r);
667
+ background: var(--panel2);
668
+ cursor: pointer;
669
+ transition: border-color 0.12s;
670
+ }
671
+
672
+ .wb-colorinput:hover {
673
+ border-color: var(--border-strong);
674
+ }
675
+
676
+ .wb-colorinput:focus-within {
677
+ border-color: var(--border-strong);
678
+ box-shadow: 0 0 0 3px var(--accent-soft);
679
+ }
680
+
681
+ .wb-colorinput .well {
682
+ width: 18px;
683
+ height: 18px;
684
+ border-radius: 5px;
685
+ border: 1px solid var(--border-strong);
686
+ flex-shrink: 0;
687
+ }
688
+
689
+ .wb-colorinput .hex {
690
+ font-family: var(--mono);
691
+ font-size: 10.5px;
692
+ color: var(--muted);
693
+ text-transform: lowercase;
694
+ }
695
+
696
+ .wb-colorinput input {
697
+ position: absolute;
698
+ inset: 0;
699
+ width: 100%;
700
+ height: 100%;
701
+ opacity: 0;
702
+ border: none;
703
+ padding: 0;
704
+ cursor: pointer;
705
+ }
706
+
707
+ .wb-pop-reset {
708
+ margin-top: 14px;
709
+ }
710
+
711
+ /* ---------- Canvas stage ---------- */
712
+
713
+ .wb-stage {
714
+ flex: 1;
715
+ overflow: auto;
716
+ display: flex;
717
+ justify-content: center;
718
+ padding: 22px 28px 14px 28px;
719
+ background: var(--bg);
720
+ min-height: 0;
721
+ }
722
+
723
+ .wb-zoomwrap {
724
+ transform-origin: top center;
725
+ }
726
+
727
+ .wb-frame-col {
728
+ display: flex;
729
+ flex-direction: column;
730
+ }
731
+
732
+ .wb-frame-row {
733
+ display: flex;
734
+ align-items: stretch;
735
+ gap: 8px;
736
+ }
737
+
738
+ .wb-handle {
739
+ width: 6px;
740
+ border-radius: 999px;
741
+ background: var(--border-strong);
742
+ cursor: ew-resize;
743
+ align-self: center;
744
+ height: 56px;
745
+ flex-shrink: 0;
746
+ transition:
747
+ background 0.12s,
748
+ height 0.15s;
749
+ }
750
+
751
+ .wb-handle:hover,
752
+ .wb-handle.dragging {
753
+ background: var(--accent-ui);
754
+ height: 80px;
755
+ }
756
+
757
+ .wb-handle-h {
758
+ height: 6px;
759
+ width: 56px;
760
+ border-radius: 999px;
761
+ background: var(--border-strong);
762
+ cursor: ns-resize;
763
+ margin: 8px auto 0 auto;
764
+ flex-shrink: 0;
765
+ transition:
766
+ background 0.12s,
767
+ width 0.15s;
768
+ }
769
+
770
+ .wb-handle-h:hover,
771
+ .wb-handle-h.dragging {
772
+ background: var(--accent-ui);
773
+ width: 84px;
774
+ }
775
+
776
+ .wb-framewrap {
777
+ position: relative;
778
+ display: flex;
779
+ }
780
+
781
+ .wb-corner {
782
+ display: none;
783
+ }
784
+
785
+ .wb-corner.tl {
786
+ top: -17px;
787
+ left: -17px;
788
+ }
789
+ .wb-corner.tr {
790
+ top: -17px;
791
+ right: -17px;
792
+ }
793
+ .wb-corner.bl {
794
+ bottom: -17px;
795
+ left: -17px;
796
+ }
797
+ .wb-corner.br {
798
+ bottom: -17px;
799
+ right: -17px;
800
+ }
801
+
802
+ .wb-frame {
803
+ position: relative;
804
+ background: var(--cv-bg, var(--surface));
805
+ border: 1px solid var(--border);
806
+ border-radius: 14px;
807
+ box-shadow: var(--shadow);
808
+ overflow: hidden;
809
+ display: flex;
810
+ flex-direction: column;
811
+ }
812
+
813
+ .wb-frame.grid-dots {
814
+ background-image: radial-gradient(circle, var(--cv-dot, var(--border)) 1px, transparent 1.5px);
815
+ background-size: var(--dot-size, 20px) var(--dot-size, 20px);
816
+ background-position: center center;
817
+ }
818
+
819
+ .wb-frame.grid-lines {
820
+ background-image: linear-gradient(to right, var(--cv-dot, var(--border)) 1px, transparent 1px), linear-gradient(to bottom, var(--cv-dot, var(--border)) 1px, transparent 1px);
821
+ background-size: var(--dot-size, 20px) var(--dot-size, 20px);
822
+ background-position: center center;
823
+ }
824
+
825
+ /* The preview iframe fills the grid frame. The iframe is transparent so the
826
+ grid wrapper (--cv-bg / --cv-dot) shows through behind the rendered component. */
827
+ .wb-frame > iframe {
828
+ position: absolute;
829
+ inset: 0;
830
+ width: 100%;
831
+ height: 100%;
832
+ border: 0;
833
+ background: transparent;
834
+ display: block;
835
+ }
836
+
837
+ .wb-frame-inner {
838
+ container-type: inline-size;
839
+ container-name: canvas;
840
+ position: relative;
841
+ flex: 1;
842
+ display: flex;
843
+ flex-direction: column;
844
+ min-height: 0;
845
+ }
846
+
847
+ .wb-placement {
848
+ flex: 1;
849
+ display: flex;
850
+ min-height: 0;
851
+ }
852
+
853
+ .wb-placement.center {
854
+ align-items: center;
855
+ justify-content: center;
856
+ padding: 32px;
857
+ }
858
+ .wb-placement.top {
859
+ align-items: flex-start;
860
+ justify-content: stretch;
861
+ padding: 0;
862
+ }
863
+ .wb-placement.bottom-right {
864
+ align-items: flex-end;
865
+ justify-content: flex-end;
866
+ padding: 20px;
867
+ }
868
+ .wb-placement.fill {
869
+ align-items: stretch;
870
+ justify-content: stretch;
871
+ padding: 0;
872
+ }
873
+ .wb-placement.fill > * {
874
+ flex: 1;
875
+ }
876
+ .wb-placement.top > * {
877
+ flex: 1;
878
+ }
879
+
880
+ .wb-dismissed-hint {
881
+ position: absolute;
882
+ inset: 0;
883
+ display: grid;
884
+ place-items: center;
885
+ font-size: 12px;
886
+ color: var(--faint);
887
+ pointer-events: none;
888
+ user-select: none;
889
+ }
890
+
891
+ .wb-dim-readout {
892
+ text-align: center;
893
+ font-size: 11px;
894
+ font-variant-numeric: tabular-nums;
895
+ color: var(--faint);
896
+ margin-top: 8px;
897
+ user-select: none;
898
+ white-space: nowrap;
899
+ }
900
+
901
+ .wb-dim-readout .bp {
902
+ color: var(--muted);
903
+ font-weight: 600;
904
+ }
905
+
906
+ /* ---------- Inspector ---------- */
907
+
908
+ .wb-inspector {
909
+ background: var(--panel);
910
+ display: flex;
911
+ flex-direction: column;
912
+ min-height: 0;
913
+ min-width: 0;
914
+ }
915
+
916
+ .wb-inspector.right {
917
+ width: 312px;
918
+ flex-shrink: 0;
919
+ border-left: 1px solid var(--border);
920
+ }
921
+
922
+ .wb-inspector.bottom {
923
+ height: 280px;
924
+ flex-shrink: 0;
925
+ border-top: 1px solid var(--border);
926
+ }
927
+
928
+ .wb-inspector.right.collapsed {
929
+ width: 44px;
930
+ align-items: center;
931
+ padding: 8px 0;
932
+ gap: 12px;
933
+ }
934
+
935
+ .wb-inspector.bottom.collapsed {
936
+ height: 40px;
937
+ flex-direction: row;
938
+ align-items: center;
939
+ padding: 0 12px;
940
+ gap: 10px;
941
+ }
942
+
943
+ .wb-inspector.bottom.collapsed .cname {
944
+ font-size: 12px;
945
+ font-weight: 600;
946
+ color: var(--muted);
947
+ }
948
+
949
+ .wb-tabs {
950
+ display: flex;
951
+ align-items: stretch;
952
+ gap: 13px;
953
+ padding: 0 16px;
954
+ height: 40px;
955
+ border-bottom: 1px solid var(--border);
956
+ flex-shrink: 0;
957
+ /* Six tabs can exceed the narrow right panel — scroll rather than clip. */
958
+ overflow-x: auto;
959
+ scrollbar-width: none;
960
+ }
961
+
962
+ .wb-tabs::-webkit-scrollbar {
963
+ display: none;
964
+ }
965
+
966
+ /* Read-only component-local state strip (under the tabs) */
967
+
968
+ .wb-state {
969
+ display: flex;
970
+ align-items: center;
971
+ gap: 12px;
972
+ flex-wrap: wrap;
973
+ padding: 7px 16px;
974
+ border-bottom: 1px solid var(--border);
975
+ background: var(--inset);
976
+ font-size: 11.5px;
977
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
978
+ flex-shrink: 0;
979
+ }
980
+
981
+ .wb-state-label {
982
+ text-transform: uppercase;
983
+ letter-spacing: 0.06em;
984
+ font-size: 9.5px;
985
+ font-weight: 650;
986
+ font-family: var(--sans, inherit);
987
+ color: var(--faint);
988
+ }
989
+
990
+ .wb-state-item {
991
+ display: inline-flex;
992
+ align-items: center;
993
+ gap: 5px;
994
+ }
995
+
996
+ .wb-state-item .k {
997
+ color: var(--muted);
998
+ }
999
+
1000
+ .wb-state-item .v {
1001
+ color: var(--text);
1002
+ font-weight: 600;
1003
+ }
1004
+
1005
+ .wb-tab {
1006
+ height: 100%;
1007
+ padding: 0 1px;
1008
+ border: none;
1009
+ border-bottom: 2px solid transparent;
1010
+ background: transparent;
1011
+ color: var(--muted);
1012
+ font-size: 12.5px;
1013
+ font-weight: 550;
1014
+ white-space: nowrap;
1015
+ flex: 0 0 auto;
1016
+ cursor: pointer;
1017
+ transition:
1018
+ color 0.12s,
1019
+ border-color 0.12s;
1020
+ }
1021
+
1022
+ .wb-tab:hover {
1023
+ color: var(--text);
1024
+ }
1025
+
1026
+ .wb-tab.on {
1027
+ color: var(--text);
1028
+ border-bottom-color: var(--accent-ui);
1029
+ }
1030
+
1031
+ .wb-tabs .wb-tabs-aux {
1032
+ margin-left: auto;
1033
+ display: flex;
1034
+ align-items: center;
1035
+ gap: 8px;
1036
+ min-width: 0;
1037
+ color: var(--muted);
1038
+ font-size: 12px;
1039
+ }
1040
+
1041
+ .wb-inspector-body {
1042
+ flex: 1;
1043
+ overflow-y: auto;
1044
+ min-height: 0;
1045
+ }
1046
+
1047
+ /* ---------- Props-as-code editor ---------- */
1048
+
1049
+ .wb-codeedit {
1050
+ padding: 14px 16px 18px 16px;
1051
+ display: flex;
1052
+ flex-direction: column;
1053
+ gap: 12px;
1054
+ }
1055
+
1056
+ .wb-edit-main {
1057
+ display: flex;
1058
+ flex-direction: column;
1059
+ gap: 8px;
1060
+ min-width: 0;
1061
+ }
1062
+
1063
+ .wb-codeedit-bar {
1064
+ display: flex;
1065
+ align-items: center;
1066
+ gap: 8px;
1067
+ }
1068
+
1069
+ .wb-codeedit-bar .lbl {
1070
+ flex: 1;
1071
+ font-size: 12px;
1072
+ font-weight: 600;
1073
+ color: var(--muted);
1074
+ display: flex;
1075
+ align-items: center;
1076
+ gap: 7px;
1077
+ }
1078
+
1079
+ .wb-dirty-dot {
1080
+ width: 6px;
1081
+ height: 6px;
1082
+ border-radius: 50%;
1083
+ background: var(--accent-ui);
1084
+ }
1085
+
1086
+ .wb-ghostbtn {
1087
+ height: 28px;
1088
+ padding: 0 11px;
1089
+ border: 1px solid var(--border);
1090
+ border-radius: var(--r);
1091
+ background: transparent;
1092
+ color: var(--muted);
1093
+ font-size: 12px;
1094
+ font-weight: 550;
1095
+ cursor: pointer;
1096
+ transition:
1097
+ color 0.12s,
1098
+ border-color 0.12s;
1099
+ }
1100
+
1101
+ .wb-ghostbtn:hover {
1102
+ color: var(--text);
1103
+ border-color: var(--border-strong);
1104
+ }
1105
+
1106
+ .wb-save {
1107
+ height: 28px;
1108
+ padding: 0 14px;
1109
+ border: 1px solid var(--accent);
1110
+ border-radius: var(--r);
1111
+ background: var(--accent);
1112
+ color: var(--accent-text);
1113
+ font-size: 12px;
1114
+ font-weight: 600;
1115
+ cursor: pointer;
1116
+ transition: opacity 0.12s;
1117
+ }
1118
+
1119
+ [data-theme="dark"] .wb-save {
1120
+ background: var(--accent-ui);
1121
+ border-color: var(--accent-ui);
1122
+ color: #111113;
1123
+ }
1124
+
1125
+ .wb-save:disabled {
1126
+ opacity: 0.35;
1127
+ cursor: default;
1128
+ }
1129
+
1130
+ .wb-codearea {
1131
+ width: 100%;
1132
+ resize: vertical;
1133
+ font-family: var(--mono);
1134
+ font-size: 11.5px;
1135
+ line-height: 1.65;
1136
+ padding: 10px 12px;
1137
+ background: var(--panel2);
1138
+ color: var(--text);
1139
+ border: 1px solid var(--border);
1140
+ border-radius: var(--r);
1141
+ outline: none;
1142
+ tab-size: 2;
1143
+ white-space: pre;
1144
+ overflow-x: auto;
1145
+ transition:
1146
+ border-color 0.12s,
1147
+ box-shadow 0.12s;
1148
+ }
1149
+
1150
+ .wb-codearea:focus {
1151
+ border-color: var(--border-strong);
1152
+ box-shadow: 0 0 0 3px var(--accent-soft);
1153
+ }
1154
+
1155
+ .wb-codearea.invalid {
1156
+ border-color: var(--danger);
1157
+ }
1158
+
1159
+ .wb-code-error {
1160
+ font-family: var(--mono);
1161
+ font-size: 10.5px;
1162
+ line-height: 1.6;
1163
+ color: var(--danger);
1164
+ background: rgba(192, 68, 60, 0.07);
1165
+ border: 1px solid rgba(192, 68, 60, 0.25);
1166
+ border-radius: var(--r);
1167
+ padding: 8px 10px;
1168
+ white-space: pre-wrap;
1169
+ }
1170
+
1171
+ .wb-saved-flash {
1172
+ font-size: 11.5px;
1173
+ font-weight: 550;
1174
+ color: #3c7a4a;
1175
+ }
1176
+
1177
+ [data-theme="dark"] .wb-saved-flash {
1178
+ color: #84c896;
1179
+ }
1180
+
1181
+ .wb-schema {
1182
+ border-top: 1px solid var(--border);
1183
+ padding-top: 12px;
1184
+ display: flex;
1185
+ flex-direction: column;
1186
+ gap: 6px;
1187
+ min-width: 0;
1188
+ }
1189
+
1190
+ .wb-schema-title {
1191
+ font-size: 12px;
1192
+ font-weight: 600;
1193
+ color: var(--muted);
1194
+ margin-bottom: 2px;
1195
+ }
1196
+
1197
+ .wb-schema-row {
1198
+ display: flex;
1199
+ gap: 10px;
1200
+ font-family: var(--mono);
1201
+ font-size: 10.5px;
1202
+ line-height: 1.5;
1203
+ }
1204
+
1205
+ .wb-schema-row .k {
1206
+ color: var(--text);
1207
+ font-weight: 600;
1208
+ min-width: 96px;
1209
+ flex-shrink: 0;
1210
+ }
1211
+
1212
+ .wb-schema-row .t {
1213
+ color: var(--muted);
1214
+ word-break: break-word;
1215
+ }
1216
+
1217
+ .wb-inspector.bottom .wb-codeedit {
1218
+ flex-direction: row;
1219
+ align-items: flex-start;
1220
+ }
1221
+
1222
+ .wb-inspector.bottom .wb-edit-main {
1223
+ flex: 1.5;
1224
+ }
1225
+
1226
+ .wb-inspector.bottom .wb-schema {
1227
+ flex: 1;
1228
+ border-top: none;
1229
+ border-left: 1px solid var(--border);
1230
+ padding: 0 0 0 16px;
1231
+ }
1232
+
1233
+ /* ---------- Props cards ---------- */
1234
+
1235
+ .wb-prop-cards {
1236
+ padding: 14px 16px 18px 16px;
1237
+ display: flex;
1238
+ flex-direction: column;
1239
+ gap: 8px;
1240
+ }
1241
+
1242
+ .wb-inspector.bottom .wb-prop-cards {
1243
+ display: grid;
1244
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
1245
+ gap: 8px 10px;
1246
+ align-content: start;
1247
+ }
1248
+
1249
+ .wb-prop-card {
1250
+ border: 1px solid var(--border);
1251
+ background: var(--panel2);
1252
+ border-radius: 10px;
1253
+ padding: 10px 12px 11px 12px;
1254
+ }
1255
+
1256
+ .wb-prop-card .row1 {
1257
+ display: flex;
1258
+ align-items: baseline;
1259
+ justify-content: space-between;
1260
+ gap: 8px;
1261
+ }
1262
+
1263
+ .wb-prop-card .pname {
1264
+ font-family: var(--mono);
1265
+ font-size: 12px;
1266
+ font-weight: 700;
1267
+ color: var(--text);
1268
+ }
1269
+
1270
+ .wb-prop-card .pdefault {
1271
+ font-family: var(--mono);
1272
+ font-size: 9.5px;
1273
+ color: var(--faint);
1274
+ white-space: nowrap;
1275
+ }
1276
+
1277
+ .wb-prop-card .ptype {
1278
+ font-family: var(--mono);
1279
+ font-size: 10.5px;
1280
+ line-height: 1.55;
1281
+ color: var(--muted);
1282
+ margin-top: 3px;
1283
+ word-break: break-word;
1284
+ }
1285
+
1286
+ .wb-prop-card .pdesc {
1287
+ margin: 6px 0 0 0;
1288
+ font-size: 12px;
1289
+ line-height: 1.5;
1290
+ color: var(--muted);
1291
+ text-wrap: pretty;
1292
+ }
1293
+
1294
+ /* ---------- Reset button (shared) ---------- */
1295
+
1296
+ .wb-reset {
1297
+ display: inline-flex;
1298
+ align-items: center;
1299
+ gap: 6px;
1300
+ height: 28px;
1301
+ padding: 0 11px;
1302
+ border: 1px solid var(--border);
1303
+ border-radius: var(--r);
1304
+ background: transparent;
1305
+ color: var(--muted);
1306
+ font-size: 12px;
1307
+ font-weight: 550;
1308
+ cursor: pointer;
1309
+ transition:
1310
+ color 0.12s,
1311
+ border-color 0.12s;
1312
+ }
1313
+
1314
+ .wb-reset:hover {
1315
+ color: var(--text);
1316
+ border-color: var(--border-strong);
1317
+ }
1318
+
1319
+ /* ---------- Ctrl segment (popover + misc) ---------- */
1320
+
1321
+ .wb-ctrl-seg {
1322
+ display: flex;
1323
+ gap: 2px;
1324
+ padding: 2px;
1325
+ background: var(--inset);
1326
+ border-radius: 999px;
1327
+ }
1328
+
1329
+ .wb-ctrl-seg button {
1330
+ flex: 1;
1331
+ height: 23px;
1332
+ padding: 0 10px;
1333
+ border: none;
1334
+ border-radius: 999px;
1335
+ background: transparent;
1336
+ color: var(--muted);
1337
+ font-size: 11.5px;
1338
+ font-weight: 550;
1339
+ cursor: pointer;
1340
+ transition:
1341
+ background 0.12s,
1342
+ color 0.12s;
1343
+ }
1344
+
1345
+ .wb-ctrl-seg button.on {
1346
+ background: var(--panel);
1347
+ color: var(--text);
1348
+ box-shadow: 0 1px 3px rgba(16, 16, 18, 0.1);
1349
+ }
1350
+
1351
+ /* ---------- Code tab ---------- */
1352
+
1353
+ .wb-code-wrap {
1354
+ position: relative;
1355
+ margin: 14px 16px;
1356
+ }
1357
+
1358
+ .wb-code {
1359
+ margin: 0;
1360
+ padding: 14px 16px;
1361
+ background: var(--panel2);
1362
+ border: 1px solid var(--border);
1363
+ border-radius: 10px;
1364
+ font-family: var(--mono);
1365
+ font-size: 11.5px;
1366
+ line-height: 1.65;
1367
+ color: var(--text);
1368
+ overflow-x: auto;
1369
+ white-space: pre;
1370
+ }
1371
+
1372
+ .wb-copy {
1373
+ position: absolute;
1374
+ top: 8px;
1375
+ right: 8px;
1376
+ display: inline-flex;
1377
+ align-items: center;
1378
+ gap: 5px;
1379
+ height: 27px;
1380
+ padding: 0 10px;
1381
+ border: 1px solid var(--border);
1382
+ border-radius: var(--r);
1383
+ background: var(--panel);
1384
+ color: var(--muted);
1385
+ font-size: 11.5px;
1386
+ font-weight: 550;
1387
+ cursor: pointer;
1388
+ transition: color 0.12s;
1389
+ }
1390
+
1391
+ .wb-copy:hover {
1392
+ color: var(--text);
1393
+ }
1394
+ .wb-copy.copied {
1395
+ color: #3c7a4a;
1396
+ }
1397
+
1398
+ [data-theme="dark"] .wb-copy.copied {
1399
+ color: #84c896;
1400
+ }
1401
+
1402
+ /* ---------- Variants gallery ---------- */
1403
+
1404
+ .wb-variants {
1405
+ display: grid;
1406
+ grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
1407
+ gap: 10px;
1408
+ padding: 14px 16px 20px 16px;
1409
+ }
1410
+
1411
+ .wb-variant-cell {
1412
+ border: 1px solid var(--border);
1413
+ border-radius: 10px;
1414
+ background: var(--surface);
1415
+ overflow: hidden;
1416
+ display: flex;
1417
+ flex-direction: column;
1418
+ }
1419
+
1420
+ /* Clickable apply-cell: the whole card commits the variant into the editor.
1421
+ A transparent button overlay (.wb-variant-apply) is the real click target. */
1422
+ .wb-variant-cell.clickable {
1423
+ position: relative;
1424
+ cursor: pointer;
1425
+ text-align: left;
1426
+ padding: 0;
1427
+ border-color: var(--border);
1428
+ color: inherit;
1429
+ font: inherit;
1430
+ transition:
1431
+ border-color 0.12s,
1432
+ box-shadow 0.12s,
1433
+ background 0.12s;
1434
+ }
1435
+
1436
+ .wb-variant-cell.clickable:hover {
1437
+ border-color: var(--border-strong);
1438
+ box-shadow: var(--shadow);
1439
+ }
1440
+
1441
+ .wb-variant-cell.clickable:focus-within {
1442
+ outline: none;
1443
+ border-color: var(--accent-ui);
1444
+ box-shadow: 0 0 0 3px var(--accent-soft);
1445
+ }
1446
+
1447
+ .wb-variant-apply {
1448
+ position: absolute;
1449
+ inset: 0;
1450
+ margin: 0;
1451
+ padding: 0;
1452
+ border: 0;
1453
+ background: transparent;
1454
+ cursor: pointer;
1455
+ }
1456
+
1457
+ .wb-variant-cell.applied {
1458
+ border-color: var(--accent-ui);
1459
+ box-shadow: 0 0 0 1px var(--accent-ui);
1460
+ }
1461
+
1462
+ .wb-variant-stage {
1463
+ container-type: inline-size;
1464
+ flex: 1;
1465
+ display: flex;
1466
+ align-items: center;
1467
+ justify-content: center;
1468
+ padding: 16px 12px;
1469
+ min-height: 86px;
1470
+ background-image: radial-gradient(circle, var(--border) 0.8px, transparent 1.2px);
1471
+ background-size: 14px 14px;
1472
+ }
1473
+
1474
+ .wb-fit {
1475
+ width: 100%;
1476
+ overflow: hidden;
1477
+ }
1478
+
1479
+ .wb-fit-inner {
1480
+ width: max-content;
1481
+ margin: 0 auto;
1482
+ transform-origin: top center;
1483
+ }
1484
+
1485
+ /* Live variant thumbnail: the component renders at a natural width inside its
1486
+ own iframe, scaled down to the cell width. The iframe is inert (the whole
1487
+ cell is the click target). */
1488
+ .wb-variant-thumb {
1489
+ width: 100%;
1490
+ overflow: hidden;
1491
+ border-radius: 6px;
1492
+ }
1493
+
1494
+ .wb-variant-frame {
1495
+ display: block;
1496
+ border: 0;
1497
+ background: transparent;
1498
+ transform-origin: top left;
1499
+ pointer-events: none;
1500
+ color-scheme: normal;
1501
+ }
1502
+
1503
+ .wb-variant-label {
1504
+ font-size: 11px;
1505
+ color: var(--muted);
1506
+ padding: 6px 10px;
1507
+ border-top: 1px solid var(--border);
1508
+ background: var(--panel2);
1509
+ display: flex;
1510
+ align-items: center;
1511
+ gap: 6px;
1512
+ }
1513
+
1514
+ .wb-variant-label .vname {
1515
+ flex: 1;
1516
+ overflow: hidden;
1517
+ text-overflow: ellipsis;
1518
+ white-space: nowrap;
1519
+ }
1520
+
1521
+ .wb-variant-label .vapply {
1522
+ font-size: 10px;
1523
+ font-weight: 600;
1524
+ letter-spacing: 0.04em;
1525
+ text-transform: uppercase;
1526
+ color: var(--accent-ui);
1527
+ opacity: 0;
1528
+ transition: opacity 0.12s;
1529
+ }
1530
+
1531
+ .wb-variant-cell.clickable:hover .wb-variant-label .vapply,
1532
+ .wb-variant-cell.clickable:focus-within .wb-variant-label .vapply {
1533
+ opacity: 1;
1534
+ }
1535
+
1536
+ /* ---------- Context tab ---------- */
1537
+
1538
+ .wb-context {
1539
+ padding: 14px 16px 18px 16px;
1540
+ display: flex;
1541
+ flex-direction: column;
1542
+ gap: 14px;
1543
+ }
1544
+
1545
+ .wb-context-group {
1546
+ display: flex;
1547
+ flex-direction: column;
1548
+ gap: 8px;
1549
+ }
1550
+
1551
+ .wb-context-group-head {
1552
+ display: flex;
1553
+ align-items: center;
1554
+ gap: 8px;
1555
+ font-size: 10.5px;
1556
+ font-weight: 600;
1557
+ letter-spacing: 0.07em;
1558
+ text-transform: uppercase;
1559
+ color: var(--faint);
1560
+ }
1561
+
1562
+ .wb-context-group-head .gname {
1563
+ color: var(--muted);
1564
+ letter-spacing: 0.04em;
1565
+ }
1566
+
1567
+ .wb-context-group-desc {
1568
+ margin: -2px 0 2px;
1569
+ font-size: 11.5px;
1570
+ line-height: 1.5;
1571
+ color: var(--faint);
1572
+ }
1573
+
1574
+ .wb-context-group-head .grow {
1575
+ flex: 1;
1576
+ }
1577
+
1578
+ .wb-context-group-head .gtag {
1579
+ font-family: var(--mono);
1580
+ font-size: 9.5px;
1581
+ font-weight: 500;
1582
+ letter-spacing: 0;
1583
+ text-transform: none;
1584
+ color: var(--faint);
1585
+ }
1586
+
1587
+ .wb-ctrl-row {
1588
+ display: flex;
1589
+ align-items: center;
1590
+ gap: 10px;
1591
+ min-height: 28px;
1592
+ }
1593
+
1594
+ .wb-ctrl-row .clbl {
1595
+ flex-shrink: 0;
1596
+ width: 96px;
1597
+ font-size: 12px;
1598
+ color: var(--muted);
1599
+ overflow: hidden;
1600
+ text-overflow: ellipsis;
1601
+ white-space: nowrap;
1602
+ }
1603
+
1604
+ .wb-ctrl-row .cfield {
1605
+ flex: 1;
1606
+ min-width: 0;
1607
+ display: flex;
1608
+ align-items: center;
1609
+ justify-content: flex-end;
1610
+ gap: 8px;
1611
+ }
1612
+
1613
+ .wb-ctrl-input {
1614
+ flex: 1;
1615
+ min-width: 0;
1616
+ height: 28px;
1617
+ padding: 0 9px;
1618
+ border: 1px solid var(--border);
1619
+ border-radius: var(--r);
1620
+ background: var(--panel2);
1621
+ color: var(--text);
1622
+ font: inherit;
1623
+ font-size: 12px;
1624
+ outline: none;
1625
+ transition:
1626
+ border-color 0.12s,
1627
+ box-shadow 0.12s;
1628
+ }
1629
+
1630
+ .wb-ctrl-input::placeholder {
1631
+ color: var(--faint);
1632
+ }
1633
+
1634
+ .wb-ctrl-input:focus {
1635
+ border-color: var(--border-strong);
1636
+ box-shadow: 0 0 0 3px var(--accent-soft);
1637
+ }
1638
+
1639
+ select.wb-ctrl-input {
1640
+ cursor: pointer;
1641
+ appearance: none;
1642
+ padding-right: 26px;
1643
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236e6e73' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
1644
+ background-repeat: no-repeat;
1645
+ background-position: right 8px center;
1646
+ }
1647
+
1648
+ .wb-ctrl-row input[type="range"] {
1649
+ flex: 1;
1650
+ accent-color: var(--accent-ui);
1651
+ min-width: 0;
1652
+ }
1653
+
1654
+ .wb-ctrl-row .cval {
1655
+ flex-shrink: 0;
1656
+ width: 40px;
1657
+ text-align: right;
1658
+ font-size: 11px;
1659
+ font-variant-numeric: tabular-nums;
1660
+ color: var(--muted);
1661
+ }
1662
+
1663
+ /* Switch control (booleans) */
1664
+ .wb-switch {
1665
+ position: relative;
1666
+ width: 34px;
1667
+ height: 20px;
1668
+ flex-shrink: 0;
1669
+ border: none;
1670
+ border-radius: 999px;
1671
+ background: var(--border-strong);
1672
+ cursor: pointer;
1673
+ padding: 0;
1674
+ transition: background 0.12s;
1675
+ }
1676
+
1677
+ .wb-switch::after {
1678
+ content: "";
1679
+ position: absolute;
1680
+ top: 2px;
1681
+ left: 2px;
1682
+ width: 16px;
1683
+ height: 16px;
1684
+ border-radius: 50%;
1685
+ background: var(--panel);
1686
+ box-shadow: 0 1px 2px rgba(16, 16, 18, 0.2);
1687
+ transition: transform 0.14s;
1688
+ }
1689
+
1690
+ .wb-switch.on {
1691
+ background: var(--accent-ui);
1692
+ }
1693
+ .wb-switch.on::after {
1694
+ transform: translateX(14px);
1695
+ }
1696
+
1697
+ [data-theme="dark"] .wb-switch.on::after {
1698
+ background: #111113;
1699
+ }
1700
+
1701
+ .wb-context-empty {
1702
+ padding: 24px 8px;
1703
+ color: var(--faint);
1704
+ font-size: 12.5px;
1705
+ text-align: center;
1706
+ }
1707
+
1708
+ /* ---------- Environment section ---------- */
1709
+
1710
+ .wb-env {
1711
+ display: flex;
1712
+ flex-direction: column;
1713
+ gap: 8px;
1714
+ }
1715
+
1716
+ .wb-env-head {
1717
+ display: flex;
1718
+ align-items: center;
1719
+ gap: 8px;
1720
+ font-size: 10.5px;
1721
+ font-weight: 600;
1722
+ letter-spacing: 0.07em;
1723
+ text-transform: uppercase;
1724
+ color: var(--faint);
1725
+ margin-bottom: 2px;
1726
+ }
1727
+
1728
+ .wb-env .wb-ctrl-seg {
1729
+ flex: 1;
1730
+ min-width: 0;
1731
+ }
1732
+
1733
+ /* ---------- Logs strip ---------- */
1734
+
1735
+ .wb-logs {
1736
+ display: flex;
1737
+ flex-direction: column;
1738
+ min-height: 0;
1739
+ margin-top: 6px;
1740
+ border-top: 1px solid var(--border);
1741
+ }
1742
+
1743
+ .wb-logs-bar {
1744
+ display: flex;
1745
+ align-items: center;
1746
+ gap: 8px;
1747
+ padding: 8px 16px;
1748
+ border-bottom: 1px solid var(--border);
1749
+ flex-shrink: 0;
1750
+ }
1751
+
1752
+ .wb-logs-bar .lbl {
1753
+ flex: 1;
1754
+ font-size: 10.5px;
1755
+ font-weight: 600;
1756
+ letter-spacing: 0.07em;
1757
+ text-transform: uppercase;
1758
+ color: var(--faint);
1759
+ }
1760
+
1761
+ .wb-logs-bar .cnt {
1762
+ font-family: var(--mono);
1763
+ font-size: 10.5px;
1764
+ color: var(--muted);
1765
+ font-variant-numeric: tabular-nums;
1766
+ }
1767
+
1768
+ .wb-logs-list {
1769
+ flex: 1;
1770
+ overflow-y: auto;
1771
+ min-height: 0;
1772
+ padding: 4px 0;
1773
+ }
1774
+
1775
+ .wb-log {
1776
+ display: flex;
1777
+ align-items: baseline;
1778
+ gap: 9px;
1779
+ padding: 4px 16px;
1780
+ font-family: var(--mono);
1781
+ font-size: 11px;
1782
+ line-height: 1.55;
1783
+ border-bottom: 1px solid var(--border);
1784
+ }
1785
+
1786
+ .wb-log:last-child {
1787
+ border-bottom: none;
1788
+ }
1789
+
1790
+ .wb-log .ltime {
1791
+ flex-shrink: 0;
1792
+ color: var(--faint);
1793
+ font-size: 10px;
1794
+ font-variant-numeric: tabular-nums;
1795
+ }
1796
+
1797
+ .wb-log .llevel {
1798
+ flex-shrink: 0;
1799
+ width: 42px;
1800
+ font-size: 9.5px;
1801
+ font-weight: 700;
1802
+ letter-spacing: 0.04em;
1803
+ text-transform: uppercase;
1804
+ }
1805
+
1806
+ .wb-log.log .llevel {
1807
+ color: var(--muted);
1808
+ }
1809
+ .wb-log.info .llevel {
1810
+ color: var(--accent-ui);
1811
+ }
1812
+ .wb-log.warn .llevel {
1813
+ color: #99661c;
1814
+ }
1815
+ .wb-log.error .llevel {
1816
+ color: var(--danger);
1817
+ }
1818
+
1819
+ [data-theme="dark"] .wb-log.warn .llevel {
1820
+ color: #dcb064;
1821
+ }
1822
+
1823
+ .wb-log.warn {
1824
+ background: rgba(153, 102, 28, 0.05);
1825
+ }
1826
+ .wb-log.error {
1827
+ background: rgba(192, 68, 60, 0.05);
1828
+ }
1829
+
1830
+ .wb-log .lmsg {
1831
+ flex: 1;
1832
+ color: var(--text);
1833
+ word-break: break-word;
1834
+ white-space: pre-wrap;
1835
+ }
1836
+
1837
+ .wb-logs-empty {
1838
+ padding: 18px 16px;
1839
+ color: var(--faint);
1840
+ font-size: 12px;
1841
+ line-height: 1.6;
1842
+ text-align: center;
1843
+ }
1844
+
1845
+ .wb-logs-empty code {
1846
+ font-family: var(--mono);
1847
+ font-size: 10.5px;
1848
+ color: var(--muted);
1849
+ background: var(--panel2);
1850
+ border: 1px solid var(--border);
1851
+ border-radius: 4px;
1852
+ padding: 1px 4px;
1853
+ }
1854
+
1855
+ /* ---------- Render error ---------- */
1856
+
1857
+ .wb-render-error {
1858
+ margin: 14px 16px;
1859
+ padding: 12px 14px;
1860
+ border-radius: 10px;
1861
+ background: rgba(192, 68, 60, 0.07);
1862
+ border: 1px solid rgba(192, 68, 60, 0.25);
1863
+ }
1864
+
1865
+ .wb-render-error .rtitle {
1866
+ font-size: 12px;
1867
+ font-weight: 700;
1868
+ color: var(--danger);
1869
+ margin-bottom: 6px;
1870
+ }
1871
+
1872
+ .wb-render-error pre {
1873
+ margin: 0;
1874
+ font-family: var(--mono);
1875
+ font-size: 10.5px;
1876
+ line-height: 1.6;
1877
+ color: var(--danger);
1878
+ white-space: pre-wrap;
1879
+ word-break: break-word;
1880
+ }
1881
+
1882
+ /* ---------- Doc header ---------- */
1883
+
1884
+ .wb-doc-head {
1885
+ padding: 16px 16px 0 16px;
1886
+ }
1887
+
1888
+ .wb-doc-head h2 {
1889
+ margin: 0 0 4px 0;
1890
+ font-size: 16px;
1891
+ font-weight: 600;
1892
+ letter-spacing: -0.01em;
1893
+ display: flex;
1894
+ align-items: center;
1895
+ gap: 8px;
1896
+ }
1897
+
1898
+ .wb-doc-head p {
1899
+ margin: 0;
1900
+ color: var(--muted);
1901
+ font-size: 12.5px;
1902
+ line-height: 1.5;
1903
+ text-wrap: pretty;
1904
+ }
1905
+
1906
+ .wb-deprecated-note {
1907
+ margin: 12px 16px 0 16px;
1908
+ padding: 8px 11px;
1909
+ border-radius: var(--r);
1910
+ background: rgba(168, 67, 58, 0.06);
1911
+ border: 1px solid rgba(168, 67, 58, 0.22);
1912
+ color: var(--danger);
1913
+ font-size: 12px;
1914
+ line-height: 1.45;
1915
+ }
1916
+
1917
+ /* ---------- Toolbar shrink behavior ---------- */
1918
+
1919
+ @container canvastools (max-width: 620px) {
1920
+ .wb-toolbar {
1921
+ gap: 6px;
1922
+ padding: 0 8px;
1923
+ }
1924
+ .wb-toolbar .wb-seg button {
1925
+ padding: 0 8px;
1926
+ }
1927
+ .wb-toolbar .wb-zoom .pct {
1928
+ width: 34px;
1929
+ }
1930
+ .wb-trigger {
1931
+ padding: 0 10px;
1932
+ }
1933
+ }
1934
+
1935
+ /* ---------- Scrollbars ---------- */
1936
+
1937
+ .wb-nav::-webkit-scrollbar,
1938
+ .wb-inspector-body::-webkit-scrollbar,
1939
+ .wb-stage::-webkit-scrollbar,
1940
+ .wb-code::-webkit-scrollbar,
1941
+ .wb-codearea::-webkit-scrollbar,
1942
+ .wb-logs-list::-webkit-scrollbar {
1943
+ width: 10px;
1944
+ height: 10px;
1945
+ }
1946
+
1947
+ .wb-nav::-webkit-scrollbar-thumb,
1948
+ .wb-inspector-body::-webkit-scrollbar-thumb,
1949
+ .wb-stage::-webkit-scrollbar-thumb,
1950
+ .wb-code::-webkit-scrollbar-thumb,
1951
+ .wb-codearea::-webkit-scrollbar-thumb,
1952
+ .wb-logs-list::-webkit-scrollbar-thumb {
1953
+ background: var(--border-strong);
1954
+ border-radius: 5px;
1955
+ border: 2px solid transparent;
1956
+ background-clip: content-box;
1957
+ }
1958
+
1959
+ .wb-nav::-webkit-scrollbar-track,
1960
+ .wb-inspector-body::-webkit-scrollbar-track,
1961
+ .wb-stage::-webkit-scrollbar-track,
1962
+ .wb-code::-webkit-scrollbar-track,
1963
+ .wb-codearea::-webkit-scrollbar-track,
1964
+ .wb-logs-list::-webkit-scrollbar-track {
1965
+ background: transparent;
1966
+ }