@pipelex/mthds-ui 0.6.2 → 0.6.4

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.
@@ -0,0 +1,2224 @@
1
+ /* this gets exported as style.css and can be used for the default theming */
2
+ /* these are the necessary styles for React/Svelte Flow, they get used by base.css and style.css */
3
+ .react-flow {
4
+ direction: ltr;
5
+
6
+ --xy-edge-stroke-default: #b1b1b7;
7
+ --xy-edge-stroke-width-default: 1;
8
+ --xy-edge-stroke-selected-default: #555;
9
+
10
+ --xy-connectionline-stroke-default: #b1b1b7;
11
+ --xy-connectionline-stroke-width-default: 1;
12
+
13
+ --xy-attribution-background-color-default: rgba(255, 255, 255, 0.5);
14
+
15
+ --xy-minimap-background-color-default: #fff;
16
+ --xy-minimap-mask-background-color-default: rgba(240, 240, 240, 0.6);
17
+ --xy-minimap-mask-stroke-color-default: transparent;
18
+ --xy-minimap-mask-stroke-width-default: 1;
19
+ --xy-minimap-node-background-color-default: #e2e2e2;
20
+ --xy-minimap-node-stroke-color-default: transparent;
21
+ --xy-minimap-node-stroke-width-default: 2;
22
+
23
+ --xy-background-color-default: transparent;
24
+ --xy-background-pattern-dots-color-default: #91919a;
25
+ --xy-background-pattern-lines-color-default: #eee;
26
+ --xy-background-pattern-cross-color-default: #e2e2e2;
27
+ background-color: var(--xy-background-color, var(--xy-background-color-default));
28
+ --xy-node-color-default: inherit;
29
+ --xy-node-border-default: 1px solid #1a192b;
30
+ --xy-node-background-color-default: #fff;
31
+ --xy-node-group-background-color-default: rgba(240, 240, 240, 0.25);
32
+ --xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, 0.08);
33
+ --xy-node-boxshadow-selected-default: 0 0 0 0.5px #1a192b;
34
+ --xy-node-border-radius-default: 3px;
35
+
36
+ --xy-handle-background-color-default: #1a192b;
37
+ --xy-handle-border-color-default: #fff;
38
+
39
+ --xy-selection-background-color-default: rgba(0, 89, 220, 0.08);
40
+ --xy-selection-border-default: 1px dotted rgba(0, 89, 220, 0.8);
41
+
42
+ --xy-controls-button-background-color-default: #fefefe;
43
+ --xy-controls-button-background-color-hover-default: #f4f4f4;
44
+ --xy-controls-button-color-default: inherit;
45
+ --xy-controls-button-color-hover-default: inherit;
46
+ --xy-controls-button-border-color-default: #eee;
47
+ --xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08);
48
+
49
+ --xy-edge-label-background-color-default: #ffffff;
50
+ --xy-edge-label-color-default: inherit;
51
+ --xy-resize-background-color-default: #3367d9;
52
+ }
53
+ .react-flow.dark {
54
+ --xy-edge-stroke-default: #3e3e3e;
55
+ --xy-edge-stroke-width-default: 1;
56
+ --xy-edge-stroke-selected-default: #727272;
57
+
58
+ --xy-connectionline-stroke-default: #b1b1b7;
59
+ --xy-connectionline-stroke-width-default: 1;
60
+
61
+ --xy-attribution-background-color-default: rgba(150, 150, 150, 0.25);
62
+
63
+ --xy-minimap-background-color-default: #141414;
64
+ --xy-minimap-mask-background-color-default: rgba(60, 60, 60, 0.6);
65
+ --xy-minimap-mask-stroke-color-default: transparent;
66
+ --xy-minimap-mask-stroke-width-default: 1;
67
+ --xy-minimap-node-background-color-default: #2b2b2b;
68
+ --xy-minimap-node-stroke-color-default: transparent;
69
+ --xy-minimap-node-stroke-width-default: 2;
70
+
71
+ --xy-background-color-default: #141414;
72
+ --xy-background-pattern-dots-color-default: #777;
73
+ --xy-background-pattern-lines-color-default: #777;
74
+ --xy-background-pattern-cross-color-default: #777;
75
+ --xy-node-color-default: #f8f8f8;
76
+ --xy-node-border-default: 1px solid #3c3c3c;
77
+ --xy-node-background-color-default: #1e1e1e;
78
+ --xy-node-group-background-color-default: rgba(240, 240, 240, 0.25);
79
+ --xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, 0.08);
80
+ --xy-node-boxshadow-selected-default: 0 0 0 0.5px #999;
81
+
82
+ --xy-handle-background-color-default: #bebebe;
83
+ --xy-handle-border-color-default: #1e1e1e;
84
+
85
+ --xy-selection-background-color-default: rgba(200, 200, 220, 0.08);
86
+ --xy-selection-border-default: 1px dotted rgba(200, 200, 220, 0.8);
87
+
88
+ --xy-controls-button-background-color-default: #2b2b2b;
89
+ --xy-controls-button-background-color-hover-default: #3e3e3e;
90
+ --xy-controls-button-color-default: #f8f8f8;
91
+ --xy-controls-button-color-hover-default: #fff;
92
+ --xy-controls-button-border-color-default: #5b5b5b;
93
+ --xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, 0.08);
94
+
95
+ --xy-edge-label-background-color-default: #141414;
96
+ --xy-edge-label-color-default: #f8f8f8;
97
+ }
98
+ .react-flow__background {
99
+ background-color: var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));
100
+ pointer-events: none;
101
+ z-index: -1;
102
+ }
103
+ .react-flow__container {
104
+ position: absolute;
105
+ width: 100%;
106
+ height: 100%;
107
+ top: 0;
108
+ left: 0;
109
+ }
110
+ .react-flow__pane {
111
+ z-index: 1;
112
+ }
113
+ .react-flow__pane.draggable {
114
+ cursor: grab;
115
+ }
116
+ .react-flow__pane.dragging {
117
+ cursor: grabbing;
118
+ }
119
+ .react-flow__pane.selection {
120
+ cursor: pointer;
121
+ }
122
+ .react-flow__viewport {
123
+ transform-origin: 0 0;
124
+ z-index: 2;
125
+ pointer-events: none;
126
+ }
127
+ .react-flow__renderer {
128
+ z-index: 4;
129
+ }
130
+ .react-flow__selection {
131
+ z-index: 6;
132
+ }
133
+ .react-flow__nodesselection-rect:focus,
134
+ .react-flow__nodesselection-rect:focus-visible {
135
+ outline: none;
136
+ }
137
+ .react-flow__edge-path {
138
+ stroke: var(--xy-edge-stroke, var(--xy-edge-stroke-default));
139
+ stroke-width: var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));
140
+ fill: none;
141
+ }
142
+ .react-flow__connection-path {
143
+ stroke: var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));
144
+ stroke-width: var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));
145
+ fill: none;
146
+ }
147
+ .react-flow .react-flow__edges {
148
+ position: absolute;
149
+ }
150
+ .react-flow .react-flow__edges svg {
151
+ overflow: visible;
152
+ position: absolute;
153
+ pointer-events: none;
154
+ }
155
+ .react-flow__edge {
156
+ pointer-events: visibleStroke;
157
+ }
158
+ .react-flow__edge.selectable {
159
+ cursor: pointer;
160
+ }
161
+ .react-flow__edge.animated path {
162
+ stroke-dasharray: 5;
163
+ animation: dashdraw 0.5s linear infinite;
164
+ }
165
+ .react-flow__edge.animated path.react-flow__edge-interaction {
166
+ stroke-dasharray: none;
167
+ animation: none;
168
+ }
169
+ .react-flow__edge.inactive {
170
+ pointer-events: none;
171
+ }
172
+ .react-flow__edge.selected,
173
+ .react-flow__edge:focus,
174
+ .react-flow__edge:focus-visible {
175
+ outline: none;
176
+ }
177
+ .react-flow__edge.selected .react-flow__edge-path,
178
+ .react-flow__edge.selectable:focus .react-flow__edge-path,
179
+ .react-flow__edge.selectable:focus-visible .react-flow__edge-path {
180
+ stroke: var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default));
181
+ }
182
+ .react-flow__edge-textwrapper {
183
+ pointer-events: all;
184
+ }
185
+ .react-flow__edge .react-flow__edge-text {
186
+ pointer-events: none;
187
+ -webkit-user-select: none;
188
+ -moz-user-select: none;
189
+ user-select: none;
190
+ }
191
+ /* Arrowhead marker styles - use CSS custom properties as default */
192
+ .react-flow__arrowhead polyline {
193
+ stroke: var(--xy-edge-stroke, var(--xy-edge-stroke-default));
194
+ }
195
+ .react-flow__arrowhead polyline.arrowclosed {
196
+ fill: var(--xy-edge-stroke, var(--xy-edge-stroke-default));
197
+ }
198
+ .react-flow__connection {
199
+ pointer-events: none;
200
+ }
201
+ .react-flow__connection .animated {
202
+ stroke-dasharray: 5;
203
+ animation: dashdraw 0.5s linear infinite;
204
+ }
205
+ svg.react-flow__connectionline {
206
+ z-index: 1001;
207
+ overflow: visible;
208
+ position: absolute;
209
+ }
210
+ .react-flow__nodes {
211
+ pointer-events: none;
212
+ transform-origin: 0 0;
213
+ }
214
+ .react-flow__node {
215
+ position: absolute;
216
+ -webkit-user-select: none;
217
+ -moz-user-select: none;
218
+ user-select: none;
219
+ pointer-events: all;
220
+ transform-origin: 0 0;
221
+ box-sizing: border-box;
222
+ cursor: default;
223
+ }
224
+ .react-flow__node.selectable {
225
+ cursor: pointer;
226
+ }
227
+ .react-flow__node.draggable {
228
+ cursor: grab;
229
+ pointer-events: all;
230
+ }
231
+ .react-flow__node.draggable.dragging {
232
+ cursor: grabbing;
233
+ }
234
+ .react-flow__nodesselection {
235
+ z-index: 3;
236
+ transform-origin: left top;
237
+ pointer-events: none;
238
+ }
239
+ .react-flow__nodesselection-rect {
240
+ position: absolute;
241
+ pointer-events: all;
242
+ cursor: grab;
243
+ }
244
+ .react-flow__handle {
245
+ position: absolute;
246
+ pointer-events: none;
247
+ min-width: 5px;
248
+ min-height: 5px;
249
+ width: 6px;
250
+ height: 6px;
251
+ background-color: var(--xy-handle-background-color, var(--xy-handle-background-color-default));
252
+ border: 1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));
253
+ border-radius: 100%;
254
+ }
255
+ .react-flow__handle.connectingfrom {
256
+ pointer-events: all;
257
+ }
258
+ .react-flow__handle.connectionindicator {
259
+ pointer-events: all;
260
+ cursor: crosshair;
261
+ }
262
+ .react-flow__handle-bottom {
263
+ top: auto;
264
+ left: 50%;
265
+ bottom: 0;
266
+ transform: translate(-50%, 50%);
267
+ }
268
+ .react-flow__handle-top {
269
+ top: 0;
270
+ left: 50%;
271
+ transform: translate(-50%, -50%);
272
+ }
273
+ .react-flow__handle-left {
274
+ top: 50%;
275
+ left: 0;
276
+ transform: translate(-50%, -50%);
277
+ }
278
+ .react-flow__handle-right {
279
+ top: 50%;
280
+ right: 0;
281
+ transform: translate(50%, -50%);
282
+ }
283
+ .react-flow__edgeupdater {
284
+ cursor: move;
285
+ pointer-events: all;
286
+ }
287
+ .react-flow__pane.selection .react-flow__panel {
288
+ pointer-events: none;
289
+ }
290
+ .react-flow__panel {
291
+ position: absolute;
292
+ z-index: 5;
293
+ margin: 15px;
294
+ }
295
+ .react-flow__panel.top {
296
+ top: 0;
297
+ }
298
+ .react-flow__panel.bottom {
299
+ bottom: 0;
300
+ }
301
+ .react-flow__panel.top.center, .react-flow__panel.bottom.center {
302
+ left: 50%;
303
+ transform: translateX(-15px) translateX(-50%);
304
+ }
305
+ .react-flow__panel.left {
306
+ left: 0;
307
+ }
308
+ .react-flow__panel.right {
309
+ right: 0;
310
+ }
311
+ .react-flow__panel.left.center, .react-flow__panel.right.center {
312
+ top: 50%;
313
+ transform: translateY(-15px) translateY(-50%);
314
+ }
315
+ .react-flow__attribution {
316
+ font-size: 10px;
317
+ background: var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));
318
+ padding: 2px 3px;
319
+ margin: 0;
320
+ }
321
+ .react-flow__attribution a {
322
+ text-decoration: none;
323
+ color: #999;
324
+ }
325
+ @keyframes dashdraw {
326
+ from {
327
+ stroke-dashoffset: 10;
328
+ }
329
+ }
330
+ .react-flow__edgelabel-renderer {
331
+ position: absolute;
332
+ width: 100%;
333
+ height: 100%;
334
+ pointer-events: none;
335
+ -webkit-user-select: none;
336
+ -moz-user-select: none;
337
+ user-select: none;
338
+ left: 0;
339
+ top: 0;
340
+ }
341
+ .react-flow__viewport-portal {
342
+ position: absolute;
343
+ width: 100%;
344
+ height: 100%;
345
+ left: 0;
346
+ top: 0;
347
+ -webkit-user-select: none;
348
+ -moz-user-select: none;
349
+ user-select: none;
350
+ }
351
+ .react-flow__minimap {
352
+ background: var(
353
+ --xy-minimap-background-color-props,
354
+ var(--xy-minimap-background-color, var(--xy-minimap-background-color-default))
355
+ );
356
+ }
357
+ .react-flow__minimap-svg {
358
+ display: block;
359
+ }
360
+ .react-flow__minimap-mask {
361
+ fill: var(
362
+ --xy-minimap-mask-background-color-props,
363
+ var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default))
364
+ );
365
+ stroke: var(
366
+ --xy-minimap-mask-stroke-color-props,
367
+ var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default))
368
+ );
369
+ stroke-width: var(
370
+ --xy-minimap-mask-stroke-width-props,
371
+ var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default))
372
+ );
373
+ }
374
+ .react-flow__minimap-node {
375
+ fill: var(
376
+ --xy-minimap-node-background-color-props,
377
+ var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default))
378
+ );
379
+ stroke: var(
380
+ --xy-minimap-node-stroke-color-props,
381
+ var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default))
382
+ );
383
+ stroke-width: var(
384
+ --xy-minimap-node-stroke-width-props,
385
+ var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default))
386
+ );
387
+ }
388
+ .react-flow__background-pattern.dots {
389
+ fill: var(
390
+ --xy-background-pattern-color-props,
391
+ var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default))
392
+ );
393
+ }
394
+ .react-flow__background-pattern.lines {
395
+ stroke: var(
396
+ --xy-background-pattern-color-props,
397
+ var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default))
398
+ );
399
+ }
400
+ .react-flow__background-pattern.cross {
401
+ stroke: var(
402
+ --xy-background-pattern-color-props,
403
+ var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default))
404
+ );
405
+ }
406
+ .react-flow__controls {
407
+ display: flex;
408
+ flex-direction: column;
409
+ box-shadow: var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default));
410
+ }
411
+ .react-flow__controls.horizontal {
412
+ flex-direction: row;
413
+ }
414
+ .react-flow__controls-button {
415
+ display: flex;
416
+ justify-content: center;
417
+ align-items: center;
418
+ height: 26px;
419
+ width: 26px;
420
+ padding: 4px;
421
+ border: none;
422
+ background: var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));
423
+ border-bottom: 1px solid
424
+ var(
425
+ --xy-controls-button-border-color-props,
426
+ var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default))
427
+ );
428
+ color: var(
429
+ --xy-controls-button-color-props,
430
+ var(--xy-controls-button-color, var(--xy-controls-button-color-default))
431
+ );
432
+ cursor: pointer;
433
+ -webkit-user-select: none;
434
+ -moz-user-select: none;
435
+ user-select: none;
436
+ }
437
+ .react-flow__controls-button svg {
438
+ width: 100%;
439
+ max-width: 12px;
440
+ max-height: 12px;
441
+ fill: currentColor;
442
+ }
443
+ .react-flow__edge.updating .react-flow__edge-path {
444
+ stroke: #777;
445
+ }
446
+ .react-flow__edge-text {
447
+ font-size: 10px;
448
+ }
449
+ .react-flow__node.selectable:focus,
450
+ .react-flow__node.selectable:focus-visible {
451
+ outline: none;
452
+ }
453
+ .react-flow__node-input,
454
+ .react-flow__node-default,
455
+ .react-flow__node-output,
456
+ .react-flow__node-group {
457
+ padding: 10px;
458
+ border-radius: var(--xy-node-border-radius, var(--xy-node-border-radius-default));
459
+ width: 150px;
460
+ font-size: 12px;
461
+ color: var(--xy-node-color, var(--xy-node-color-default));
462
+ text-align: center;
463
+ border: var(--xy-node-border, var(--xy-node-border-default));
464
+ background-color: var(--xy-node-background-color, var(--xy-node-background-color-default));
465
+ }
466
+ .react-flow__node-input.selectable:hover, .react-flow__node-default.selectable:hover, .react-flow__node-output.selectable:hover, .react-flow__node-group.selectable:hover {
467
+ box-shadow: var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default));
468
+ }
469
+ .react-flow__node-input.selectable.selected,
470
+ .react-flow__node-input.selectable:focus,
471
+ .react-flow__node-input.selectable:focus-visible,
472
+ .react-flow__node-default.selectable.selected,
473
+ .react-flow__node-default.selectable:focus,
474
+ .react-flow__node-default.selectable:focus-visible,
475
+ .react-flow__node-output.selectable.selected,
476
+ .react-flow__node-output.selectable:focus,
477
+ .react-flow__node-output.selectable:focus-visible,
478
+ .react-flow__node-group.selectable.selected,
479
+ .react-flow__node-group.selectable:focus,
480
+ .react-flow__node-group.selectable:focus-visible {
481
+ box-shadow: var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default));
482
+ }
483
+ .react-flow__node-group {
484
+ background-color: var(--xy-node-group-background-color, var(--xy-node-group-background-color-default));
485
+ }
486
+ .react-flow__nodesselection-rect,
487
+ .react-flow__selection {
488
+ background: var(--xy-selection-background-color, var(--xy-selection-background-color-default));
489
+ border: var(--xy-selection-border, var(--xy-selection-border-default));
490
+ }
491
+ .react-flow__nodesselection-rect:focus,
492
+ .react-flow__nodesselection-rect:focus-visible,
493
+ .react-flow__selection:focus,
494
+ .react-flow__selection:focus-visible {
495
+ outline: none;
496
+ }
497
+ .react-flow__controls-button:hover {
498
+ background: var(
499
+ --xy-controls-button-background-color-hover-props,
500
+ var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default))
501
+ );
502
+ color: var(
503
+ --xy-controls-button-color-hover-props,
504
+ var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default))
505
+ );
506
+ }
507
+ .react-flow__controls-button:disabled {
508
+ pointer-events: none;
509
+ }
510
+ .react-flow__controls-button:disabled svg {
511
+ fill-opacity: 0.4;
512
+ }
513
+ .react-flow__controls-button:last-child {
514
+ border-bottom: none;
515
+ }
516
+ .react-flow__controls.horizontal .react-flow__controls-button {
517
+ border-bottom: none;
518
+ border-right: 1px solid
519
+ var(
520
+ --xy-controls-button-border-color-props,
521
+ var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default))
522
+ );
523
+ }
524
+ .react-flow__controls.horizontal .react-flow__controls-button:last-child {
525
+ border-right: none;
526
+ }
527
+ .react-flow__resize-control {
528
+ position: absolute;
529
+ }
530
+ .react-flow__resize-control.left,
531
+ .react-flow__resize-control.right {
532
+ cursor: ew-resize;
533
+ }
534
+ .react-flow__resize-control.top,
535
+ .react-flow__resize-control.bottom {
536
+ cursor: ns-resize;
537
+ }
538
+ .react-flow__resize-control.top.left,
539
+ .react-flow__resize-control.bottom.right {
540
+ cursor: nwse-resize;
541
+ }
542
+ .react-flow__resize-control.bottom.left,
543
+ .react-flow__resize-control.top.right {
544
+ cursor: nesw-resize;
545
+ }
546
+ /* handle styles */
547
+ .react-flow__resize-control.handle {
548
+ width: 5px;
549
+ height: 5px;
550
+ border: 1px solid #fff;
551
+ border-radius: 1px;
552
+ background-color: var(--xy-resize-background-color, var(--xy-resize-background-color-default));
553
+ translate: -50% -50%;
554
+ }
555
+ .react-flow__resize-control.handle.left {
556
+ left: 0;
557
+ top: 50%;
558
+ }
559
+ .react-flow__resize-control.handle.right {
560
+ left: 100%;
561
+ top: 50%;
562
+ }
563
+ .react-flow__resize-control.handle.top {
564
+ left: 50%;
565
+ top: 0;
566
+ }
567
+ .react-flow__resize-control.handle.bottom {
568
+ left: 50%;
569
+ top: 100%;
570
+ }
571
+ .react-flow__resize-control.handle.top.left {
572
+ left: 0;
573
+ }
574
+ .react-flow__resize-control.handle.bottom.left {
575
+ left: 0;
576
+ }
577
+ .react-flow__resize-control.handle.top.right {
578
+ left: 100%;
579
+ }
580
+ .react-flow__resize-control.handle.bottom.right {
581
+ left: 100%;
582
+ }
583
+ /* line styles */
584
+ .react-flow__resize-control.line {
585
+ border-color: var(--xy-resize-background-color, var(--xy-resize-background-color-default));
586
+ border-width: 0;
587
+ border-style: solid;
588
+ }
589
+ .react-flow__resize-control.line.left,
590
+ .react-flow__resize-control.line.right {
591
+ width: 1px;
592
+ transform: translate(-50%, 0);
593
+ top: 0;
594
+ height: 100%;
595
+ }
596
+ .react-flow__resize-control.line.left {
597
+ left: 0;
598
+ border-left-width: 1px;
599
+ }
600
+ .react-flow__resize-control.line.right {
601
+ left: 100%;
602
+ border-right-width: 1px;
603
+ }
604
+ .react-flow__resize-control.line.top,
605
+ .react-flow__resize-control.line.bottom {
606
+ height: 1px;
607
+ transform: translate(0, -50%);
608
+ left: 0;
609
+ width: 100%;
610
+ }
611
+ .react-flow__resize-control.line.top {
612
+ top: 0;
613
+ border-top-width: 1px;
614
+ }
615
+ .react-flow__resize-control.line.bottom {
616
+ border-bottom-width: 1px;
617
+ top: 100%;
618
+ }
619
+ .react-flow__edge-textbg {
620
+ fill: var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default));
621
+ }
622
+ .react-flow__edge-text {
623
+ fill: var(--xy-edge-label-color, var(--xy-edge-label-color-default));
624
+ }
625
+
626
+ /* ReactFlow base styles — resolved by the consumer's bundler */
627
+ /* Default theme — consumers can override any var on an ancestor element */
628
+ .react-flow-container {
629
+ --color-bg: #0a0a0a;
630
+ --color-bg-dots: rgba(255, 255, 255, 0.35);
631
+ --color-text-muted: #94a3b8;
632
+ --color-controller-text: #94a3b8;
633
+ --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
634
+ --font-mono: "JetBrains Mono", "Monaco", "Menlo", monospace;
635
+ --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.5);
636
+ }
637
+ .react-flow-container {
638
+ position: absolute;
639
+ inset: 0;
640
+ background: var(--color-bg);
641
+ }
642
+ .react-flow__node {
643
+ font-family: var(--font-sans);
644
+ cursor: pointer;
645
+ }
646
+ .react-flow__background {
647
+ background: var(--color-bg) !important;
648
+ }
649
+ .react-flow__edge-path {
650
+ stroke-width: 2;
651
+ }
652
+ .react-flow__edge-text {
653
+ font-size: 11px;
654
+ fill: var(--color-text-muted);
655
+ }
656
+ .react-flow__edge-textbg {
657
+ fill: var(--color-bg);
658
+ }
659
+ /* Selected node highlight */
660
+ .react-flow__node.selected {
661
+ box-shadow:
662
+ 0 0 0 3px var(--color-accent),
663
+ var(--shadow-lg) !important;
664
+ z-index: 1000 !important;
665
+ }
666
+ /* Pipe cards handle their own selection styling — suppress the wrapper outline */
667
+ .react-flow__node-pipeCard {
668
+ background: transparent !important;
669
+ border: none !important;
670
+ box-shadow: none !important;
671
+ outline: none !important;
672
+ padding: 0 !important;
673
+ }
674
+ .react-flow__node-pipeCard.selected {
675
+ box-shadow: none !important;
676
+ outline: none !important;
677
+ }
678
+ .react-flow__node-pipeCard.selected .pipe-card {
679
+ box-shadow:
680
+ 0 0 0 2px var(--color-accent, #3b82f6),
681
+ 0 4px 16px rgba(0, 0, 0, 0.6);
682
+ }
683
+ .react-flow__node-controllerGroup.selected {
684
+ box-shadow:
685
+ 0 0 0 2px var(--color-accent),
686
+ var(--shadow-lg) !important;
687
+ }
688
+ .react-flow__node-controllerGroup {
689
+ cursor: default !important;
690
+ }
691
+ /* ─── Controller Group Node ──────────────────────────────────────────── */
692
+ .controller-group-node {
693
+ --controller-border: 2px dashed rgba(148, 163, 184, 0.3);
694
+ --controller-bg: rgba(148, 163, 184, 0.04);
695
+ --controller-header-color: #64748b;
696
+
697
+ width: 100%;
698
+ height: 100%;
699
+ position: relative;
700
+ border: var(--controller-border);
701
+ border-radius: 12px;
702
+ background: var(--controller-bg);
703
+ }
704
+ .controller-group-header {
705
+ position: absolute;
706
+ top: 0;
707
+ left: 0;
708
+ right: 0;
709
+ display: flex;
710
+ align-items: center;
711
+ gap: 6px;
712
+ padding: 6px 12px;
713
+ pointer-events: none;
714
+ user-select: none;
715
+ }
716
+ .controller-group-icon {
717
+ font-size: 13px;
718
+ color: var(--controller-header-color);
719
+ line-height: 1;
720
+ }
721
+ .controller-group-badge {
722
+ font-size: 9px;
723
+ font-weight: 700;
724
+ text-transform: uppercase;
725
+ letter-spacing: 0.06em;
726
+ color: var(--controller-header-color);
727
+ font-family: var(--font-mono, "JetBrains Mono", monospace);
728
+ }
729
+ .controller-group-label {
730
+ font-size: 11px;
731
+ font-family: var(--font-mono, "JetBrains Mono", monospace);
732
+ font-weight: 500;
733
+ color: var(--color-controller-text, #94a3b8);
734
+ white-space: nowrap;
735
+ margin-left: auto;
736
+ }
737
+
738
+ /* Collapse / expand toggle for parallel & batch controllers */
739
+ .controller-group-collapse {
740
+ all: unset;
741
+ position: absolute;
742
+ bottom: 4px;
743
+ right: 8px;
744
+ font-size: 10px;
745
+ font-family: var(--font-mono, "JetBrains Mono", monospace);
746
+ color: var(--controller-header-color, #94a3b8);
747
+ cursor: pointer;
748
+ padding: 2px 8px;
749
+ border-radius: 4px;
750
+ border: 1px dashed rgba(255, 255, 255, 0.15);
751
+ pointer-events: auto;
752
+ z-index: 10;
753
+ white-space: nowrap;
754
+ }
755
+ .controller-group-collapse:hover {
756
+ color: #e2e8f0;
757
+ border-color: rgba(255, 255, 255, 0.35);
758
+ background: rgba(255, 255, 255, 0.05);
759
+ }
760
+ .controller-group-collapse:focus-visible {
761
+ outline: 2px solid var(--controller-header-color, #94a3b8);
762
+ outline-offset: 2px;
763
+ }
764
+
765
+ /* Fold-into-card toggle — sits on the right of the header bar. */
766
+ .controller-group-fold {
767
+ all: unset;
768
+ cursor: pointer;
769
+ font-size: 20px;
770
+ line-height: 1;
771
+ color: var(--controller-header-color, #94a3b8);
772
+ padding: 4px 10px;
773
+ border-radius: 6px;
774
+ pointer-events: auto;
775
+ margin-left: auto;
776
+ }
777
+ .controller-group-fold:hover {
778
+ color: #e2e8f0;
779
+ background: rgba(255, 255, 255, 0.06);
780
+ }
781
+ .controller-group-fold:focus-visible {
782
+ outline: 2px solid var(--controller-header-color, #94a3b8);
783
+ outline-offset: 2px;
784
+ }
785
+
786
+ /* Sequence — solid thin border, calm flow */
787
+ .controller-group--sequence {
788
+ --controller-border: 1.5px solid rgba(148, 163, 184, 0.25);
789
+ --controller-bg: rgba(148, 163, 184, 0.03);
790
+ --controller-header-color: #94a3b8;
791
+ }
792
+
793
+ /* Parallel — double border, forking lanes */
794
+ .controller-group--parallel {
795
+ --controller-border: 3px double rgba(139, 233, 253, 0.35);
796
+ --controller-bg: rgba(139, 233, 253, 0.03);
797
+ --controller-header-color: #8be9fd;
798
+ }
799
+
800
+ /* Condition — dashed with diamond accent */
801
+ .controller-group--condition {
802
+ --controller-border: 2px dashed rgba(251, 191, 36, 0.35);
803
+ --controller-bg: rgba(251, 191, 36, 0.03);
804
+ --controller-header-color: #fbbf24;
805
+ }
806
+
807
+ /* Batch — dotted border, loop/repeat */
808
+ .controller-group--batch {
809
+ --controller-border: 2px dotted rgba(167, 139, 250, 0.35);
810
+ --controller-bg: rgba(167, 139, 250, 0.03);
811
+ --controller-header-color: #a78bfa;
812
+ }
813
+
814
+ /* ─── Pipe Card Node ─────────────────────────────────────────────────── */
815
+ /* All tokens overridable via CSS custom properties on an ancestor. */
816
+ .pipe-card {
817
+ --pipe-card-accent: #ff6b6b;
818
+ --pipe-card-bg: rgba(148, 163, 184, 0.08);
819
+ --pipe-card-text: #e2e8f0;
820
+ --pipe-card-text-bright: #f8fafc;
821
+ --pipe-card-text-muted: #94a3b8;
822
+ --pipe-card-text-dim: #64748b;
823
+ --pipe-card-pill-bg: rgba(255, 255, 255, 0.06);
824
+ --pipe-card-pill-border: rgba(255, 255, 255, 0.08);
825
+ --pipe-card-pill-text: #cbd5e1;
826
+ --pipe-card-radius: 8px;
827
+
828
+ border-left: 4px solid var(--pipe-card-accent);
829
+ border-radius: var(--pipe-card-radius);
830
+ padding: 12px 14px;
831
+ background: var(--pipe-card-bg);
832
+ font-family: var(--font-sans, "Inter", -apple-system, sans-serif);
833
+ color: var(--pipe-card-text);
834
+ display: flex;
835
+ flex-direction: column;
836
+ gap: 8px;
837
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
838
+ transition: box-shadow 0.2s;
839
+ /* Fill the ReactFlow wrapper whose size is locked to ELK's layout dimensions */
840
+ width: 100%;
841
+ height: 100%;
842
+ box-sizing: border-box;
843
+ overflow: hidden;
844
+ }
845
+ .pipe-card:hover {
846
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.6);
847
+ }
848
+
849
+ /* Direction-aware sizing: LR = narrow + tall, TB = wide + short */
850
+ .pipe-card--lr {
851
+ min-width: 180px;
852
+ max-width: 240px;
853
+ }
854
+ .pipe-card--tb {
855
+ min-width: 280px;
856
+ max-width: 400px;
857
+ }
858
+
859
+ /* Header: badge + code + status */
860
+ .pipe-card-header {
861
+ display: flex;
862
+ align-items: center;
863
+ gap: 8px;
864
+ }
865
+ .pipe-card-badge {
866
+ font-size: 10px;
867
+ font-weight: 700;
868
+ text-transform: uppercase;
869
+ letter-spacing: 0.04em;
870
+ padding: 2px 7px;
871
+ border-radius: 4px;
872
+ white-space: nowrap;
873
+ line-height: 1.4;
874
+ background: var(--pipe-card-accent);
875
+ color: #0e0e0e;
876
+ }
877
+ .pipe-card-code {
878
+ font-family: var(--font-mono, "JetBrains Mono", monospace);
879
+ font-size: 13px;
880
+ font-weight: 600;
881
+ color: var(--pipe-card-accent);
882
+ flex: 1;
883
+ overflow: hidden;
884
+ text-overflow: ellipsis;
885
+ white-space: nowrap;
886
+ }
887
+ .pipe-card-status {
888
+ display: flex;
889
+ align-items: center;
890
+ margin-left: auto;
891
+ flex-shrink: 0;
892
+ }
893
+ .pipe-card-status-dot {
894
+ width: 8px;
895
+ height: 8px;
896
+ border-radius: 50%;
897
+ display: inline-block;
898
+ }
899
+ .pipe-card-status-dot--pulse {
900
+ animation: pipe-card-pulse 1.5s ease-in-out infinite;
901
+ }
902
+
903
+ /* Expand button — appears on folded controller cards. */
904
+ .pipe-card-expand {
905
+ all: unset;
906
+ cursor: pointer;
907
+ font-size: 20px;
908
+ line-height: 1;
909
+ color: var(--pipe-card-text-muted);
910
+ padding: 4px 8px;
911
+ border-radius: 6px;
912
+ flex-shrink: 0;
913
+ }
914
+ .pipe-card-expand:hover {
915
+ color: var(--pipe-card-text-bright);
916
+ background: rgba(255, 255, 255, 0.08);
917
+ }
918
+ .pipe-card-expand:focus-visible {
919
+ outline: 2px solid var(--pipe-card-text-bright);
920
+ outline-offset: 2px;
921
+ }
922
+
923
+ /* Folded-controller card variant — slightly tinted badge to differentiate
924
+ from operator cards. */
925
+ .pipe-card-badge--controller {
926
+ background: rgba(148, 163, 184, 0.25);
927
+ color: var(--pipe-card-text-bright);
928
+ border: 1px solid rgba(148, 163, 184, 0.4);
929
+ }
930
+ .pipe-card--controller {
931
+ --pipe-card-accent: #94a3b8;
932
+ }
933
+ @keyframes pipe-card-pulse {
934
+ 0%,
935
+ 100% {
936
+ opacity: 1;
937
+ transform: scale(1);
938
+ }
939
+ 50% {
940
+ opacity: 0.5;
941
+ transform: scale(1.3);
942
+ }
943
+ }
944
+
945
+ /* LR: stack pipe code onto its own row below the badge/status row. */
946
+ .pipe-card--lr .pipe-card-header {
947
+ flex-wrap: wrap;
948
+ }
949
+ .pipe-card--lr .pipe-card-code {
950
+ flex: 0 0 100%;
951
+ order: 1;
952
+ min-width: 0;
953
+ }
954
+
955
+ /* Description — per-direction clamping. LR gets up to 3 lines (tall/narrow card),
956
+ TB gets 1 line (wide card, horizontal layout). Both truncate with ellipsis. */
957
+ .pipe-card-description {
958
+ font-size: 11.5px;
959
+ color: var(--pipe-card-text-muted);
960
+ line-height: 1.4;
961
+ overflow: hidden;
962
+ text-overflow: ellipsis;
963
+ min-width: 0;
964
+ }
965
+ .pipe-card--lr .pipe-card-description {
966
+ display: -webkit-box;
967
+ -webkit-line-clamp: 3;
968
+ -webkit-box-orient: vertical;
969
+ }
970
+ .pipe-card--tb .pipe-card-description {
971
+ white-space: nowrap;
972
+ }
973
+
974
+ /* I/O section — base (appearance only, layout set per-direction below) */
975
+ .pipe-card-io-label {
976
+ font-size: 9px;
977
+ font-weight: 700;
978
+ text-transform: uppercase;
979
+ letter-spacing: 0.06em;
980
+ color: var(--pipe-card-text-dim);
981
+ flex-shrink: 0;
982
+ }
983
+ .pipe-card-io-pills {
984
+ display: flex;
985
+ gap: 4px;
986
+ min-width: 0;
987
+ }
988
+ .pipe-card-io-pill {
989
+ display: inline-flex;
990
+ align-items: center;
991
+ gap: 3px;
992
+ font-size: 10px;
993
+ background: var(--pipe-card-pill-bg);
994
+ border: 1px solid var(--pipe-card-pill-border);
995
+ border-radius: 4px;
996
+ padding: 1px 5px;
997
+ line-height: 1.4;
998
+ min-width: 0;
999
+ }
1000
+ .pipe-card-io-pill-name {
1001
+ font-family: var(--font-mono, "JetBrains Mono", monospace);
1002
+ color: var(--pipe-card-pill-text);
1003
+ overflow: hidden;
1004
+ text-overflow: ellipsis;
1005
+ white-space: nowrap;
1006
+ }
1007
+ .pipe-card-io-pill-concept {
1008
+ color: var(--pipe-card-text-dim);
1009
+ font-size: 9px;
1010
+ overflow: hidden;
1011
+ text-overflow: ellipsis;
1012
+ white-space: nowrap;
1013
+ }
1014
+ .pipe-card-io-more {
1015
+ all: unset;
1016
+ font-size: 10px;
1017
+ font-family: var(--font-mono, "JetBrains Mono", monospace);
1018
+ color: var(--pipe-card-text-muted);
1019
+ cursor: pointer;
1020
+ padding: 2px 6px;
1021
+ border-radius: 4px;
1022
+ border: 1px dashed rgba(255, 255, 255, 0.12);
1023
+ white-space: nowrap;
1024
+ line-height: 1.4;
1025
+ }
1026
+ .pipe-card-io-more:hover {
1027
+ color: var(--pipe-card-text);
1028
+ border-color: rgba(255, 255, 255, 0.25);
1029
+ }
1030
+ .pipe-card-io-more:focus-visible {
1031
+ outline: 2px solid var(--pipe-card-text);
1032
+ outline-offset: 2px;
1033
+ }
1034
+
1035
+ /* ─── LR: label on top, pills stacked vertically, hard-truncated ─────── */
1036
+ /* Truncation priority: concept shrinks first → name truncates last. */
1037
+ .pipe-card--lr .pipe-card-io {
1038
+ display: flex;
1039
+ flex-direction: column;
1040
+ gap: 4px;
1041
+ }
1042
+ .pipe-card--lr .pipe-card-io-pills {
1043
+ flex-direction: column;
1044
+ align-items: flex-start; /* pills size to content, not stretch */
1045
+ gap: 4px;
1046
+ }
1047
+ .pipe-card--lr .pipe-card-io-pill {
1048
+ max-width: 100%;
1049
+ overflow: hidden;
1050
+ }
1051
+ .pipe-card--lr .pipe-card-io-pill-name {
1052
+ flex: 0 1 auto; /* natural width, shrinks only after concept is gone */
1053
+ min-width: 30px;
1054
+ }
1055
+ .pipe-card--lr .pipe-card-io-pill-concept {
1056
+ flex: 0 100 auto; /* natural width, shrinks 100x faster than name */
1057
+ min-width: 0; /* allow shrinking to zero */
1058
+ }
1059
+ .pipe-card--lr .pipe-card-io-more {
1060
+ align-self: flex-start;
1061
+ }
1062
+
1063
+ /* ─── TB: label on the left, pills wrap horizontally to the right ────── */
1064
+ .pipe-card--tb .pipe-card-io {
1065
+ display: flex;
1066
+ flex-direction: row;
1067
+ align-items: flex-start;
1068
+ gap: 6px;
1069
+ }
1070
+ .pipe-card--tb .pipe-card-io-label {
1071
+ padding-top: 4px;
1072
+ min-width: 52px;
1073
+ }
1074
+ .pipe-card--tb .pipe-card-io-pills {
1075
+ flex: 1 1 0;
1076
+ flex-wrap: wrap;
1077
+ min-width: 0;
1078
+ }
1079
+ .pipe-card--tb .pipe-card-io-pill {
1080
+ max-width: 100%;
1081
+ }
1082
+ .pipe-card--tb .pipe-card-io-pill-name {
1083
+ max-width: 140px;
1084
+ }
1085
+ .pipe-card--tb .pipe-card-io-pill-concept {
1086
+ max-width: 100px;
1087
+ }
1088
+
1089
+ /* ─── StuffViewer component styles ────────────────────────────────────────── */
1090
+ /* Uses CSS custom properties for consumer theming. Defaults match graph-core.css. */
1091
+
1092
+ .stuff-viewer {
1093
+ --sv-bg: var(--color-bg, #0a0a0a);
1094
+ --sv-surface: var(--color-surface, #16213e);
1095
+ --sv-surface-hover: var(--color-surface-hover, #1f2b47);
1096
+ --sv-border: var(--color-border, #2a3a5a);
1097
+ --sv-text: var(--color-text, #e2e8f0);
1098
+ --sv-text-muted: var(--color-text-muted, #94a3b8);
1099
+ --sv-accent: var(--color-accent, #3b82f6);
1100
+ --sv-success: #10b981;
1101
+ --sv-success-bg: rgba(16, 185, 129, 0.2);
1102
+ --sv-radius: 4px;
1103
+ --sv-font-sans: var(
1104
+ --font-sans,
1105
+ "Inter",
1106
+ -apple-system,
1107
+ BlinkMacSystemFont,
1108
+ "Segoe UI",
1109
+ sans-serif
1110
+ );
1111
+ --sv-font-mono: var(--font-mono, "JetBrains Mono", "Monaco", "Menlo", monospace);
1112
+
1113
+ font-family: var(--sv-font-sans);
1114
+ color: var(--sv-text);
1115
+ display: flex;
1116
+ flex-direction: column;
1117
+ height: 100%;
1118
+ }
1119
+
1120
+ /* ─── Header ─────────────────────────────────────────────────────────────── */
1121
+
1122
+ .stuff-viewer-header {
1123
+ display: flex;
1124
+ flex-direction: column;
1125
+ gap: 2px;
1126
+ padding: 12px 16px 8px;
1127
+ border-bottom: 1px solid var(--sv-border);
1128
+ flex-shrink: 0;
1129
+ }
1130
+
1131
+ .stuff-viewer-title {
1132
+ font-size: 14px;
1133
+ font-weight: 600;
1134
+ color: var(--sv-text);
1135
+ margin: 0;
1136
+ }
1137
+
1138
+ .stuff-viewer-subtitle {
1139
+ font-size: 12px;
1140
+ color: var(--sv-text-muted);
1141
+ margin: 0;
1142
+ }
1143
+
1144
+ /* ─── Toolbar: tabs + action buttons ─────────────────────────────────────── */
1145
+
1146
+ .stuff-viewer-toolbar {
1147
+ display: flex;
1148
+ justify-content: space-between;
1149
+ align-items: center;
1150
+ padding: 8px 16px;
1151
+ gap: 8px;
1152
+ flex-shrink: 0;
1153
+ }
1154
+
1155
+ .stuff-viewer-tabs {
1156
+ display: flex;
1157
+ gap: 4px;
1158
+ }
1159
+
1160
+ .stuff-viewer-tab {
1161
+ padding: 5px 10px;
1162
+ border-radius: var(--sv-radius);
1163
+ cursor: pointer;
1164
+ font-size: 12px;
1165
+ font-weight: 500;
1166
+ background: var(--sv-surface-hover);
1167
+ color: var(--sv-text-muted);
1168
+ border: none;
1169
+ transition:
1170
+ background 0.15s,
1171
+ color 0.15s;
1172
+ }
1173
+
1174
+ .stuff-viewer-tab:hover {
1175
+ background: var(--sv-border);
1176
+ color: var(--sv-text);
1177
+ }
1178
+
1179
+ .stuff-viewer-tab--active {
1180
+ background: var(--sv-accent);
1181
+ color: #fff;
1182
+ }
1183
+
1184
+ /* ─── Action buttons ─────────────────────────────────────────────────────── */
1185
+
1186
+ .stuff-viewer-actions {
1187
+ display: flex;
1188
+ gap: 4px;
1189
+ }
1190
+
1191
+ .stuff-viewer-action-btn {
1192
+ display: flex;
1193
+ align-items: center;
1194
+ justify-content: center;
1195
+ width: 28px;
1196
+ height: 28px;
1197
+ border-radius: var(--sv-radius);
1198
+ cursor: pointer;
1199
+ background: var(--sv-surface-hover);
1200
+ color: var(--sv-text-muted);
1201
+ border: none;
1202
+ transition:
1203
+ background 0.15s,
1204
+ color 0.15s;
1205
+ }
1206
+
1207
+ .stuff-viewer-action-btn:hover {
1208
+ background: var(--sv-border);
1209
+ color: var(--sv-text);
1210
+ }
1211
+
1212
+ .stuff-viewer-action-btn--copied {
1213
+ background: var(--sv-success-bg);
1214
+ color: var(--sv-success);
1215
+ }
1216
+
1217
+ .stuff-viewer-action-btn svg {
1218
+ width: 14px;
1219
+ height: 14px;
1220
+ fill: currentColor;
1221
+ }
1222
+
1223
+ /* ─── Content area ───────────────────────────────────────────────────────── */
1224
+
1225
+ .stuff-viewer-content {
1226
+ flex: 1;
1227
+ overflow: auto;
1228
+ padding: 12px 16px 16px;
1229
+ min-height: 0;
1230
+ }
1231
+
1232
+ /* Pre-formatted text (JSON and Pretty tabs) */
1233
+ .stuff-viewer-pre {
1234
+ font-family: var(--sv-font-mono);
1235
+ font-size: 11px;
1236
+ line-height: 1.5;
1237
+ white-space: pre-wrap;
1238
+ word-wrap: break-word;
1239
+ margin: 0;
1240
+ color: var(--sv-text-muted);
1241
+ }
1242
+
1243
+ .stuff-viewer-pre--nowrap {
1244
+ white-space: pre;
1245
+ word-wrap: normal;
1246
+ line-height: 1;
1247
+ overflow-x: auto;
1248
+ padding-right: 20px;
1249
+ }
1250
+
1251
+ /* HTML content */
1252
+ .stuff-viewer-html {
1253
+ font-family: var(--sv-font-sans);
1254
+ font-size: 11px;
1255
+ color: var(--sv-text-muted);
1256
+ line-height: 1.5;
1257
+ }
1258
+
1259
+ .stuff-viewer-html table {
1260
+ border-collapse: collapse;
1261
+ width: 100%;
1262
+ }
1263
+
1264
+ .stuff-viewer-html th,
1265
+ .stuff-viewer-html td {
1266
+ border: 1px solid var(--sv-border);
1267
+ padding: 8px 12px;
1268
+ text-align: left;
1269
+ }
1270
+
1271
+ .stuff-viewer-html th {
1272
+ background: var(--sv-surface-hover);
1273
+ color: var(--sv-text);
1274
+ font-weight: 600;
1275
+ }
1276
+
1277
+ .stuff-viewer-html tr:hover {
1278
+ background: var(--sv-surface-hover);
1279
+ }
1280
+
1281
+ .stuff-viewer-html a {
1282
+ color: var(--sv-accent);
1283
+ text-decoration: none;
1284
+ }
1285
+
1286
+ .stuff-viewer-html a:hover {
1287
+ text-decoration: underline;
1288
+ }
1289
+
1290
+ .stuff-viewer-html ul {
1291
+ list-style: none;
1292
+ padding-left: 0;
1293
+ margin: 0;
1294
+ }
1295
+
1296
+ /* PDF embed */
1297
+ .stuff-viewer-pdf {
1298
+ min-height: 400px;
1299
+ height: 100%;
1300
+ }
1301
+
1302
+ .stuff-viewer-pdf embed {
1303
+ width: 100%;
1304
+ height: 100%;
1305
+ min-height: 500px;
1306
+ border: none;
1307
+ }
1308
+
1309
+ /* Image content */
1310
+ .stuff-viewer-image {
1311
+ display: flex;
1312
+ justify-content: center;
1313
+ align-items: center;
1314
+ min-height: 200px;
1315
+ }
1316
+
1317
+ .stuff-viewer-image img {
1318
+ max-width: 100%;
1319
+ max-height: 70vh;
1320
+ object-fit: contain;
1321
+ }
1322
+
1323
+ /* Local file fallback (file:// URLs that can't render inline) */
1324
+ .stuff-viewer-local-file {
1325
+ display: flex;
1326
+ align-items: center;
1327
+ gap: 12px;
1328
+ padding: 16px;
1329
+ border-radius: 6px;
1330
+ background: var(--sv-surface);
1331
+ border: 1px solid var(--sv-border);
1332
+ }
1333
+
1334
+ /* Clickable variant — used when an open-externally action is bound (e.g. PDF
1335
+ fallback in hosts that can't render <embed type="application/pdf">). */
1336
+ button.stuff-viewer-local-file--button {
1337
+ width: 100%;
1338
+ text-align: left;
1339
+ font: inherit;
1340
+ color: inherit;
1341
+ cursor: pointer;
1342
+ transition:
1343
+ background 0.15s ease,
1344
+ border-color 0.15s ease;
1345
+ }
1346
+
1347
+ button.stuff-viewer-local-file--button:hover {
1348
+ background: var(--sv-surface-hover, var(--sv-surface));
1349
+ border-color: var(--sv-accent, var(--sv-border));
1350
+ }
1351
+
1352
+ button.stuff-viewer-local-file--button:focus-visible {
1353
+ outline: 2px solid var(--sv-accent, var(--sv-border));
1354
+ outline-offset: 2px;
1355
+ }
1356
+
1357
+ .stuff-viewer-local-file-icon {
1358
+ flex-shrink: 0;
1359
+ width: 32px;
1360
+ height: 32px;
1361
+ color: var(--sv-text-muted);
1362
+ }
1363
+
1364
+ .stuff-viewer-local-file-icon svg {
1365
+ width: 100%;
1366
+ height: 100%;
1367
+ fill: currentColor;
1368
+ }
1369
+
1370
+ .stuff-viewer-local-file-info {
1371
+ flex: 1;
1372
+ min-width: 0;
1373
+ }
1374
+
1375
+ .stuff-viewer-local-file-name {
1376
+ font-family: var(--sv-font-mono);
1377
+ font-size: 12px;
1378
+ color: var(--sv-text);
1379
+ overflow: hidden;
1380
+ text-overflow: ellipsis;
1381
+ white-space: nowrap;
1382
+ }
1383
+
1384
+ .stuff-viewer-local-file-hint {
1385
+ font-size: 11px;
1386
+ color: var(--sv-text-muted);
1387
+ margin-top: 2px;
1388
+ }
1389
+
1390
+ /* Placeholder for missing data */
1391
+ .stuff-viewer-placeholder {
1392
+ color: var(--sv-text-muted);
1393
+ font-style: italic;
1394
+ font-size: 13px;
1395
+ }
1396
+
1397
+ /* ─── Detail Panel — sliding side panel for node inspection ─────────────── */
1398
+
1399
+ .detail-panel {
1400
+ position: absolute;
1401
+ top: 0;
1402
+ right: 0;
1403
+ width: 380px;
1404
+ height: 100%;
1405
+ background: #111118;
1406
+ border-left: 1px solid rgba(255, 255, 255, 0.1);
1407
+ z-index: 10;
1408
+ display: flex;
1409
+ flex-direction: column;
1410
+ font-family: "Inter", -apple-system, sans-serif;
1411
+ color: #e2e8f0;
1412
+ overflow: hidden;
1413
+ transition: transform 0.2s ease;
1414
+ }
1415
+
1416
+ .detail-panel--closed {
1417
+ transform: translateX(100%);
1418
+ pointer-events: none;
1419
+ }
1420
+
1421
+ /* ─── Resize handle — left edge drag target ────────────────────────────── */
1422
+
1423
+ .detail-panel-resize-handle {
1424
+ position: absolute;
1425
+ top: 0;
1426
+ left: -6px;
1427
+ width: 12px;
1428
+ height: 100%;
1429
+ cursor: col-resize;
1430
+ z-index: 2;
1431
+ background: transparent;
1432
+ }
1433
+
1434
+ /* Visible bar — narrower than the hit area */
1435
+ .detail-panel-resize-handle::before {
1436
+ content: "";
1437
+ position: absolute;
1438
+ top: 0;
1439
+ left: 5px;
1440
+ width: 2px;
1441
+ height: 100%;
1442
+ background: transparent;
1443
+ transition: background 0.15s;
1444
+ }
1445
+
1446
+ .detail-panel-resize-handle:hover::before,
1447
+ .detail-panel--dragging .detail-panel-resize-handle::before {
1448
+ background: rgba(59, 130, 246, 0.5);
1449
+ }
1450
+
1451
+ /* Grip indicator — visible on hover */
1452
+ .detail-panel-resize-handle::after {
1453
+ content: "";
1454
+ position: absolute;
1455
+ top: 50%;
1456
+ left: 50%;
1457
+ transform: translate(-50%, -50%);
1458
+ width: 2px;
1459
+ height: 24px;
1460
+ border-radius: 1px;
1461
+ background: transparent;
1462
+ transition: background 0.15s;
1463
+ }
1464
+
1465
+ .detail-panel-resize-handle:hover::after,
1466
+ .detail-panel--dragging .detail-panel-resize-handle::after {
1467
+ background: rgba(59, 130, 246, 0.8);
1468
+ }
1469
+
1470
+ /* Disable transition during drag for smooth resizing */
1471
+ .detail-panel--dragging {
1472
+ transition: none;
1473
+ }
1474
+
1475
+ .detail-panel--dragging .detail-panel-content {
1476
+ pointer-events: none;
1477
+ }
1478
+
1479
+ .detail-panel-close {
1480
+ all: unset;
1481
+ cursor: pointer;
1482
+ position: absolute;
1483
+ top: 12px;
1484
+ right: 12px;
1485
+ width: 24px;
1486
+ height: 24px;
1487
+ display: flex;
1488
+ align-items: center;
1489
+ justify-content: center;
1490
+ border-radius: 4px;
1491
+ color: #64748b;
1492
+ font-size: 18px;
1493
+ line-height: 1;
1494
+ z-index: 3;
1495
+ }
1496
+
1497
+ .detail-panel-close:hover {
1498
+ color: #94a3b8;
1499
+ background: rgba(255, 255, 255, 0.06);
1500
+ }
1501
+
1502
+ .detail-panel-content {
1503
+ flex: 1;
1504
+ overflow-y: auto;
1505
+ padding: 20px 16px;
1506
+ display: flex;
1507
+ flex-direction: column;
1508
+ gap: 16px;
1509
+ }
1510
+
1511
+ /* ─── Sticky header (pipe info + IO stays pinned at top) ───────────────── */
1512
+
1513
+ .detail-sticky-header {
1514
+ position: sticky;
1515
+ top: -20px;
1516
+ z-index: 1;
1517
+ background: #111118;
1518
+ padding-top: 20px;
1519
+ margin-top: -20px;
1520
+ display: flex;
1521
+ flex-direction: column;
1522
+ gap: 16px;
1523
+ }
1524
+
1525
+ /* ─── Shared detail components ──────────────────────────────────────────── */
1526
+
1527
+ .detail-section-label {
1528
+ font-size: 9px;
1529
+ font-weight: 700;
1530
+ text-transform: uppercase;
1531
+ letter-spacing: 0.06em;
1532
+ color: #64748b;
1533
+ margin-bottom: 6px;
1534
+ }
1535
+
1536
+ .detail-header {
1537
+ display: flex;
1538
+ align-items: center;
1539
+ gap: 8px;
1540
+ }
1541
+
1542
+ .detail-badge {
1543
+ font-size: 10px;
1544
+ font-weight: 700;
1545
+ text-transform: uppercase;
1546
+ letter-spacing: 0.04em;
1547
+ padding: 2px 7px;
1548
+ border-radius: 4px;
1549
+ white-space: nowrap;
1550
+ }
1551
+
1552
+ .detail-badge--operator {
1553
+ background: #ff6b6b;
1554
+ color: #0e0e0e;
1555
+ }
1556
+
1557
+ .detail-badge--controller {
1558
+ background: #bd93f9;
1559
+ color: #0e0e0e;
1560
+ }
1561
+
1562
+ .detail-pipe-code {
1563
+ font-family: "JetBrains Mono", "Monaco", monospace;
1564
+ font-size: 14px;
1565
+ font-weight: 600;
1566
+ color: #ff6b6b;
1567
+ }
1568
+
1569
+ .detail-pipe-code--controller {
1570
+ color: #bd93f9;
1571
+ }
1572
+
1573
+ .detail-status {
1574
+ display: flex;
1575
+ align-items: center;
1576
+ gap: 8px;
1577
+ }
1578
+
1579
+ .detail-status-dot {
1580
+ width: 8px;
1581
+ height: 8px;
1582
+ border-radius: 50%;
1583
+ display: inline-block;
1584
+ }
1585
+
1586
+ .detail-status-label {
1587
+ font-size: 12px;
1588
+ font-weight: 600;
1589
+ text-transform: capitalize;
1590
+ }
1591
+
1592
+ .detail-duration {
1593
+ font-size: 11px;
1594
+ color: #64748b;
1595
+ font-family: "JetBrains Mono", "Monaco", monospace;
1596
+ }
1597
+
1598
+ .detail-description {
1599
+ font-size: 12px;
1600
+ color: #94a3b8;
1601
+ line-height: 1.5;
1602
+ }
1603
+
1604
+ /* ─── IO Pills ──────────────────────────────────────────────────────────── */
1605
+
1606
+ .detail-io-pill {
1607
+ display: flex;
1608
+ align-items: center;
1609
+ gap: 6px;
1610
+ font-size: 11px;
1611
+ padding: 3px 8px;
1612
+ border-radius: 4px;
1613
+ background: rgba(255, 255, 255, 0.04);
1614
+ border: 1px solid rgba(255, 255, 255, 0.06);
1615
+ }
1616
+
1617
+ .detail-io-name {
1618
+ font-family: "JetBrains Mono", "Monaco", monospace;
1619
+ color: #e2e8f0;
1620
+ }
1621
+
1622
+ .detail-io-concept {
1623
+ color: #64748b;
1624
+ font-size: 10px;
1625
+ }
1626
+
1627
+ .detail-io-list {
1628
+ display: flex;
1629
+ flex-direction: column;
1630
+ gap: 4px;
1631
+ }
1632
+
1633
+ /* ─── Blueprint-specific sections ───────────────────────────────────────── */
1634
+
1635
+ .detail-prompt-block {
1636
+ font-family: "JetBrains Mono", "Monaco", monospace;
1637
+ font-size: 11px;
1638
+ color: #94a3b8;
1639
+ background: rgba(255, 255, 255, 0.03);
1640
+ border: 1px solid rgba(255, 255, 255, 0.06);
1641
+ border-radius: 6px;
1642
+ padding: 10px 12px;
1643
+ white-space: pre-wrap;
1644
+ word-break: break-word;
1645
+ overflow-y: auto;
1646
+ line-height: 1.5;
1647
+ }
1648
+
1649
+ .detail-prompt-block--collapsed {
1650
+ max-height: 300px;
1651
+ }
1652
+
1653
+ .detail-prompt-block--expanded {
1654
+ max-height: none;
1655
+ overflow-y: visible;
1656
+ }
1657
+
1658
+ .detail-prompt-expand-btn {
1659
+ all: unset;
1660
+ cursor: pointer;
1661
+ display: flex;
1662
+ align-items: center;
1663
+ gap: 4px;
1664
+ font-size: 9px;
1665
+ color: #64748b;
1666
+ padding: 2px 6px;
1667
+ border-radius: 3px;
1668
+ background: rgba(255, 255, 255, 0.04);
1669
+ border: 1px solid rgba(255, 255, 255, 0.06);
1670
+ transition: color 0.15s;
1671
+ }
1672
+
1673
+ .detail-prompt-expand-btn:hover {
1674
+ color: #94a3b8;
1675
+ }
1676
+
1677
+ .detail-kv-row {
1678
+ display: flex;
1679
+ justify-content: space-between;
1680
+ align-items: flex-start; /* top-align so the label stays next to the first line of a wrapped value */
1681
+ gap: 12px;
1682
+ font-size: 11px;
1683
+ padding: 3px 0;
1684
+ }
1685
+
1686
+ .detail-kv-key {
1687
+ color: #64748b;
1688
+ flex-shrink: 0; /* label stays at its natural width */
1689
+ }
1690
+
1691
+ .detail-kv-value {
1692
+ font-family: "JetBrains Mono", "Monaco", monospace;
1693
+ color: #e2e8f0;
1694
+ flex: 1 1 0;
1695
+ min-width: 0;
1696
+ text-align: right;
1697
+ word-break: break-word;
1698
+ overflow-wrap: anywhere;
1699
+ }
1700
+
1701
+ /* ─── Field block: labeled multi-line text (for long resolved values) ─── */
1702
+
1703
+ .detail-field-block {
1704
+ display: flex;
1705
+ flex-direction: column;
1706
+ gap: 4px;
1707
+ }
1708
+
1709
+ .detail-field-block-label {
1710
+ font-family: "JetBrains Mono", "Monaco", monospace;
1711
+ font-size: 10px;
1712
+ color: #64748b;
1713
+ }
1714
+
1715
+ .detail-field-block-value {
1716
+ font-family: "JetBrains Mono", "Monaco", monospace;
1717
+ font-size: 11px;
1718
+ color: #e2e8f0;
1719
+ background: rgba(255, 255, 255, 0.03);
1720
+ border: 1px solid rgba(255, 255, 255, 0.06);
1721
+ border-radius: 6px;
1722
+ padding: 8px 10px;
1723
+ white-space: pre-wrap;
1724
+ word-break: break-word;
1725
+ overflow-wrap: anywhere;
1726
+ line-height: 1.5;
1727
+ max-height: 240px;
1728
+ overflow-y: auto;
1729
+ }
1730
+
1731
+ /* ─── Nested construct sub-section header ───────────────────────────────── */
1732
+ /* Rendered before each nested sub-construct's recursive contents. The left
1733
+ * border + indent provides a visual "branch" cue so the tree structure is
1734
+ * obvious without needing collapse state. */
1735
+
1736
+ .detail-nested-header {
1737
+ display: flex;
1738
+ align-items: baseline;
1739
+ justify-content: space-between;
1740
+ gap: 8px;
1741
+ margin-top: 6px;
1742
+ margin-bottom: 4px;
1743
+ padding: 4px 0 4px 8px;
1744
+ border-left: 2px solid rgba(80, 250, 123, 0.35);
1745
+ }
1746
+
1747
+ .detail-nested-header-name {
1748
+ font-family: "JetBrains Mono", "Monaco", monospace;
1749
+ font-size: 11px;
1750
+ font-weight: 600;
1751
+ color: #e2e8f0;
1752
+ }
1753
+
1754
+ .detail-nested-header-meta {
1755
+ font-family: "JetBrains Mono", "Monaco", monospace;
1756
+ font-size: 9px;
1757
+ color: #64748b;
1758
+ text-transform: uppercase;
1759
+ letter-spacing: 0.04em;
1760
+ }
1761
+
1762
+ /* ─── Concept schema table ──────────────────────────────────────────────── */
1763
+
1764
+ .detail-schema-table {
1765
+ width: 100%;
1766
+ font-size: 11px;
1767
+ border-collapse: collapse;
1768
+ }
1769
+
1770
+ .detail-schema-table th {
1771
+ text-align: left;
1772
+ font-weight: 700;
1773
+ color: #64748b;
1774
+ font-size: 9px;
1775
+ text-transform: uppercase;
1776
+ letter-spacing: 0.06em;
1777
+ padding: 4px 6px;
1778
+ border-bottom: 1px solid rgba(255, 255, 255, 0.08);
1779
+ }
1780
+
1781
+ .detail-schema-table td {
1782
+ padding: 4px 6px;
1783
+ border-bottom: 1px solid rgba(255, 255, 255, 0.04);
1784
+ color: #94a3b8;
1785
+ }
1786
+
1787
+ .detail-schema-field {
1788
+ font-family: "JetBrains Mono", "Monaco", monospace;
1789
+ color: #e2e8f0;
1790
+ }
1791
+
1792
+ .detail-schema-type {
1793
+ color: #8be9fd;
1794
+ }
1795
+
1796
+ .detail-schema-required {
1797
+ color: #ff6b6b;
1798
+ font-size: 9px;
1799
+ }
1800
+
1801
+ /* ─── Error section ─────────────────────────────────────────────────────── */
1802
+
1803
+ .detail-error {
1804
+ background: rgba(255, 85, 85, 0.08);
1805
+ border: 1px solid rgba(255, 85, 85, 0.2);
1806
+ border-radius: 6px;
1807
+ padding: 10px 12px;
1808
+ }
1809
+
1810
+ .detail-error-type {
1811
+ font-size: 12px;
1812
+ font-weight: 600;
1813
+ color: #ff5555;
1814
+ margin-bottom: 4px;
1815
+ }
1816
+
1817
+ .detail-error-message {
1818
+ font-size: 11px;
1819
+ color: #94a3b8;
1820
+ line-height: 1.5;
1821
+ }
1822
+
1823
+ .detail-error-stack {
1824
+ font-family: "JetBrains Mono", "Monaco", monospace;
1825
+ font-size: 10px;
1826
+ color: #64748b;
1827
+ margin-top: 8px;
1828
+ max-height: 150px;
1829
+ overflow-y: auto;
1830
+ white-space: pre-wrap;
1831
+ word-break: break-word;
1832
+ }
1833
+
1834
+ /* ─── Steps list (PipeSequence, PipeCondition outcomes) ─────────────────── */
1835
+
1836
+ .detail-steps-list {
1837
+ display: flex;
1838
+ flex-direction: column;
1839
+ gap: 4px;
1840
+ }
1841
+
1842
+ .detail-step-item {
1843
+ display: flex;
1844
+ align-items: center;
1845
+ gap: 8px;
1846
+ font-size: 11px;
1847
+ padding: 4px 8px;
1848
+ border-radius: 4px;
1849
+ background: rgba(255, 255, 255, 0.03);
1850
+ border: 1px solid rgba(255, 255, 255, 0.06);
1851
+ }
1852
+
1853
+ .detail-step-index {
1854
+ color: #64748b;
1855
+ font-size: 10px;
1856
+ font-weight: 700;
1857
+ min-width: 16px;
1858
+ }
1859
+
1860
+ .detail-step-code {
1861
+ font-family: "JetBrains Mono", "Monaco", monospace;
1862
+ color: #e2e8f0;
1863
+ }
1864
+
1865
+ /* ─── Tags/Metrics ──────────────────────────────────────────────────────── */
1866
+
1867
+ .detail-tags {
1868
+ display: flex;
1869
+ flex-wrap: wrap;
1870
+ gap: 4px;
1871
+ }
1872
+
1873
+ .detail-tag {
1874
+ font-size: 10px;
1875
+ padding: 2px 6px;
1876
+ border-radius: 3px;
1877
+ background: rgba(255, 255, 255, 0.04);
1878
+ border: 1px solid rgba(255, 255, 255, 0.06);
1879
+ }
1880
+
1881
+ .detail-tag-key {
1882
+ color: #64748b;
1883
+ }
1884
+
1885
+ .detail-tag-value {
1886
+ color: #e2e8f0;
1887
+ font-family: "JetBrains Mono", "Monaco", monospace;
1888
+ }
1889
+
1890
+ /* ─── Concept panel header ──────────────────────────────────────────────── */
1891
+
1892
+ .detail-concept-code {
1893
+ font-family: "JetBrains Mono", "Monaco", monospace;
1894
+ font-size: 14px;
1895
+ font-weight: 600;
1896
+ color: #50fa7b;
1897
+ }
1898
+
1899
+ .detail-concept-domain {
1900
+ font-size: 11px;
1901
+ color: #64748b;
1902
+ }
1903
+
1904
+ .detail-refines {
1905
+ font-size: 11px;
1906
+ color: #94a3b8;
1907
+ }
1908
+
1909
+ .detail-refines-code {
1910
+ font-family: "JetBrains Mono", "Monaco", monospace;
1911
+ color: #8be9fd;
1912
+ }
1913
+
1914
+ /* ─── Not available fallback ────────────────────────────────────────────── */
1915
+
1916
+ .detail-not-available {
1917
+ font-size: 12px;
1918
+ color: #64748b;
1919
+ font-style: italic;
1920
+ padding: 8px 0;
1921
+ }
1922
+
1923
+ /* ─── Graph Toolbar — floating controls over the graph background ─────── */
1924
+
1925
+ .graph-toolbar {
1926
+ position: absolute;
1927
+ top: 8px;
1928
+ display: flex;
1929
+ align-items: center;
1930
+ gap: 4px;
1931
+ z-index: 11;
1932
+ pointer-events: auto;
1933
+ }
1934
+
1935
+ .graph-toolbar-btn {
1936
+ all: unset;
1937
+ box-sizing: border-box;
1938
+ cursor: pointer;
1939
+ width: 28px;
1940
+ height: 28px;
1941
+ display: inline-flex;
1942
+ align-items: center;
1943
+ justify-content: center;
1944
+ border-radius: 6px;
1945
+ background: rgba(17, 17, 24, 0.8);
1946
+ border: 1px solid rgba(255, 255, 255, 0.1);
1947
+ color: #cbd5e1;
1948
+ backdrop-filter: blur(6px);
1949
+ transition:
1950
+ background 0.15s,
1951
+ color 0.15s,
1952
+ border-color 0.15s;
1953
+ }
1954
+
1955
+ .graph-toolbar-btn:hover {
1956
+ background: rgba(30, 30, 40, 0.9);
1957
+ color: #f1f5f9;
1958
+ border-color: rgba(255, 255, 255, 0.18);
1959
+ }
1960
+
1961
+ .graph-toolbar-btn:focus-visible {
1962
+ outline: 2px solid rgba(59, 130, 246, 0.6);
1963
+ outline-offset: 1px;
1964
+ }
1965
+
1966
+ .graph-toolbar-btn--active {
1967
+ background: #3b82f6;
1968
+ border-color: #3b82f6;
1969
+ color: #ffffff;
1970
+ }
1971
+
1972
+ .graph-toolbar-btn--active:hover {
1973
+ background: #2563eb;
1974
+ border-color: #2563eb;
1975
+ color: #ffffff;
1976
+ }
1977
+
1978
+ .graph-toolbar-btn:disabled {
1979
+ opacity: 0.4;
1980
+ cursor: not-allowed;
1981
+ background: rgba(17, 17, 24, 0.6);
1982
+ color: #64748b;
1983
+ border-color: rgba(255, 255, 255, 0.06);
1984
+ }
1985
+
1986
+ .graph-toolbar-btn:disabled:hover {
1987
+ background: rgba(17, 17, 24, 0.6);
1988
+ color: #64748b;
1989
+ border-color: rgba(255, 255, 255, 0.06);
1990
+ }
1991
+
1992
+ .graph-toolbar-separator {
1993
+ width: 1px;
1994
+ height: 18px;
1995
+ background: rgba(255, 255, 255, 0.12);
1996
+ margin: 0 2px;
1997
+ }
1998
+
1999
+ /* ─── Standalone GraphViewer chrome (toolbar, theme, layout) ─────────── */
2000
+
2001
+ * { box-sizing: border-box; margin: 0; padding: 0; }
2002
+
2003
+ html, body {
2004
+ height: 100%;
2005
+ overflow: hidden;
2006
+ font-family: "Inter", -apple-system, sans-serif;
2007
+ }
2008
+
2009
+ /* ─── Theme system ──────────────────────────────────────────────────── */
2010
+
2011
+ body[data-theme="dark"], body:not([data-theme]) {
2012
+ --chrome-bg: #0d1117;
2013
+ --chrome-surface: #161b22;
2014
+ --chrome-border: rgba(255,255,255,0.08);
2015
+ --chrome-text: #e2e8f0;
2016
+ --chrome-text-muted: #8b949e;
2017
+ background: #0a0a0f;
2018
+ color: #e2e8f0;
2019
+ }
2020
+
2021
+ body[data-theme="light"] {
2022
+ --chrome-bg: #ffffff;
2023
+ --chrome-surface: #f6f8fa;
2024
+ --chrome-border: rgba(0,0,0,0.1);
2025
+ --chrome-text: #1f2328;
2026
+ --chrome-text-muted: #656d76;
2027
+ background: #ffffff;
2028
+ color: #1f2328;
2029
+ }
2030
+
2031
+ @media (prefers-color-scheme: light) {
2032
+ body[data-theme="system"] {
2033
+ --chrome-bg: #ffffff;
2034
+ --chrome-surface: #f6f8fa;
2035
+ --chrome-border: rgba(0,0,0,0.1);
2036
+ --chrome-text: #1f2328;
2037
+ --chrome-text-muted: #656d76;
2038
+ background: #ffffff;
2039
+ color: #1f2328;
2040
+ }
2041
+ }
2042
+
2043
+ @media (prefers-color-scheme: dark) {
2044
+ body[data-theme="system"] {
2045
+ --chrome-bg: #0d1117;
2046
+ --chrome-surface: #161b22;
2047
+ --chrome-border: rgba(255,255,255,0.08);
2048
+ --chrome-text: #e2e8f0;
2049
+ --chrome-text-muted: #8b949e;
2050
+ background: #0a0a0f;
2051
+ color: #e2e8f0;
2052
+ }
2053
+ }
2054
+
2055
+ /* ─── Layout ────────────────────────────────────────────────────────── */
2056
+
2057
+ #app-container {
2058
+ display: flex;
2059
+ flex-direction: column;
2060
+ height: 100vh;
2061
+ }
2062
+
2063
+ #root {
2064
+ flex: 1;
2065
+ position: relative;
2066
+ min-height: 0;
2067
+ }
2068
+
2069
+ /* ─── Toolbar ───────────────────────────────────────────────────────── */
2070
+
2071
+ .toolbar {
2072
+ display: flex;
2073
+ align-items: center;
2074
+ gap: 8px;
2075
+ padding: 6px 12px;
2076
+ background: var(--chrome-surface);
2077
+ border-bottom: 1px solid var(--chrome-border);
2078
+ flex-shrink: 0;
2079
+ z-index: 20;
2080
+ }
2081
+
2082
+ .toolbar-spacer { flex: 1; }
2083
+
2084
+ .toolbar-btn {
2085
+ all: unset;
2086
+ cursor: pointer;
2087
+ display: flex;
2088
+ align-items: center;
2089
+ justify-content: center;
2090
+ width: 28px;
2091
+ height: 28px;
2092
+ border-radius: 4px;
2093
+ color: var(--chrome-text-muted);
2094
+ transition: background 0.15s, color 0.15s;
2095
+ }
2096
+
2097
+ .toolbar-btn:hover {
2098
+ background: var(--chrome-border);
2099
+ color: var(--chrome-text);
2100
+ }
2101
+
2102
+ .toolbar-zoom {
2103
+ display: flex;
2104
+ gap: 2px;
2105
+ }
2106
+
2107
+ /* Direction toggle */
2108
+ .direction-icon { display: none; }
2109
+ .direction-icon.active { display: inline-flex; }
2110
+
2111
+ /* Controllers toggle */
2112
+ .toggle-switch {
2113
+ display: flex;
2114
+ align-items: center;
2115
+ gap: 6px;
2116
+ cursor: pointer;
2117
+ font-size: 11px;
2118
+ color: var(--chrome-text-muted);
2119
+ user-select: none;
2120
+ }
2121
+
2122
+ .toggle-switch input { display: none; }
2123
+
2124
+ .toggle-track {
2125
+ width: 28px;
2126
+ height: 16px;
2127
+ border-radius: 8px;
2128
+ background: var(--chrome-border);
2129
+ position: relative;
2130
+ transition: background 0.15s;
2131
+ }
2132
+
2133
+ .toggle-switch input:checked + .toggle-track {
2134
+ background: #50FA7B44;
2135
+ }
2136
+
2137
+ .toggle-knob {
2138
+ position: absolute;
2139
+ top: 2px;
2140
+ left: 2px;
2141
+ width: 12px;
2142
+ height: 12px;
2143
+ border-radius: 50%;
2144
+ background: var(--chrome-text-muted);
2145
+ transition: left 0.15s, background 0.15s;
2146
+ }
2147
+
2148
+ .toggle-switch input:checked + .toggle-track .toggle-knob {
2149
+ left: 14px;
2150
+ background: #50FA7B;
2151
+ }
2152
+
2153
+ .toggle-label {
2154
+ font-size: 11px;
2155
+ }
2156
+
2157
+ /* Theme toggle */
2158
+ .theme-btn {
2159
+ all: unset;
2160
+ cursor: pointer;
2161
+ display: flex;
2162
+ align-items: center;
2163
+ gap: 4px;
2164
+ font-size: 10px;
2165
+ color: var(--chrome-text-muted);
2166
+ padding: 4px 8px;
2167
+ border-radius: 4px;
2168
+ transition: background 0.15s;
2169
+ }
2170
+
2171
+ .theme-btn:hover {
2172
+ background: var(--chrome-border);
2173
+ }
2174
+
2175
+ .theme-label {
2176
+ text-transform: capitalize;
2177
+ }
2178
+
2179
+ /* ─── Header branding ───────────────────────────────────────────────── */
2180
+
2181
+ .header-brand {
2182
+ display: flex;
2183
+ align-items: center;
2184
+ gap: 8px;
2185
+ }
2186
+
2187
+ .header-logo {
2188
+ height: 18px;
2189
+ opacity: 0.7;
2190
+ }
2191
+
2192
+ body[data-theme="dark"] .header-logo.light-logo,
2193
+ body:not([data-theme]) .header-logo.light-logo {
2194
+ display: none;
2195
+ }
2196
+
2197
+ body[data-theme="light"] .header-logo.dark-logo {
2198
+ display: none;
2199
+ }
2200
+
2201
+ body[data-theme="light"] .header-logo.light-logo {
2202
+ display: inline;
2203
+ }
2204
+
2205
+ @media (prefers-color-scheme: light) {
2206
+ body[data-theme="system"] .header-logo.dark-logo {
2207
+ display: none;
2208
+ }
2209
+ body[data-theme="system"] .header-logo.light-logo {
2210
+ display: inline;
2211
+ }
2212
+ }
2213
+
2214
+ @media (prefers-color-scheme: dark) {
2215
+ body[data-theme="system"] .header-logo.light-logo {
2216
+ display: none;
2217
+ }
2218
+ }
2219
+
2220
+ .header-title {
2221
+ font-size: 12px;
2222
+ font-weight: 600;
2223
+ color: var(--chrome-text-muted);
2224
+ }