@leverege/tpi-viz 0.2.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.
@@ -0,0 +1,926 @@
1
+ /**
2
+ * scene_viewer.css - Styles for unified scene viewer
3
+ * Extends viewer_common.css with dual sidebar layout, camera tree, and parameter editing.
4
+ */
5
+
6
+ /* ── Controls overlays: Views (top-right), Projection (top-left) ── */
7
+ #pov-controls {
8
+ flex-direction: column;
9
+ align-items: stretch;
10
+ gap: 10px;
11
+ max-width: 320px;
12
+ }
13
+
14
+ /* Projection overlay, pinned top-left (mirrors .controls which is top-right). */
15
+ .controls.controls-left {
16
+ left: 12px;
17
+ right: auto;
18
+ }
19
+
20
+ .ctrl-group {
21
+ display: flex;
22
+ flex-direction: column;
23
+ gap: 5px;
24
+ }
25
+
26
+ .ctrl-label {
27
+ font-size: 9px;
28
+ font-weight: 600;
29
+ letter-spacing: 0.08em;
30
+ text-transform: uppercase;
31
+ color: var(--text-3);
32
+ }
33
+
34
+ .ctrl-row {
35
+ display: flex;
36
+ flex-wrap: wrap;
37
+ gap: 5px;
38
+ align-items: center;
39
+ }
40
+
41
+ /* Bookmark chip = go-button + delete-×, visually one unit */
42
+ .bookmark-chip {
43
+ display: inline-flex;
44
+ align-items: stretch;
45
+ border-radius: var(--r-sm);
46
+ overflow: hidden;
47
+ border: 1px solid var(--border-subtle);
48
+ }
49
+ .bookmark-chip .btn.bookmark-btn {
50
+ border: none;
51
+ border-radius: 0;
52
+ max-width: 130px;
53
+ overflow: hidden;
54
+ text-overflow: ellipsis;
55
+ white-space: nowrap;
56
+ }
57
+ .bookmark-chip .bookmark-del {
58
+ border: none;
59
+ border-left: 1px solid var(--border-subtle);
60
+ background: var(--bg-panel);
61
+ color: var(--text-3);
62
+ cursor: pointer;
63
+ padding: 0 7px;
64
+ font-size: 13px;
65
+ line-height: 1;
66
+ transition: background var(--t-fast), color var(--t-fast);
67
+ }
68
+ .bookmark-chip .bookmark-del:hover {
69
+ background: var(--accent-pink-soft);
70
+ color: var(--text-1);
71
+ }
72
+
73
+ .btn.btn-add {
74
+ font-size: 14px;
75
+ font-weight: 700;
76
+ padding: 5px 9px;
77
+ color: var(--accent-blue);
78
+ }
79
+
80
+ /* In-app name popup (replaces window.prompt for bookmarks) */
81
+ .name-popup {
82
+ position: fixed;
83
+ z-index: 100;
84
+ background: var(--bg-overlay);
85
+ backdrop-filter: blur(10px);
86
+ -webkit-backdrop-filter: blur(10px);
87
+ border: 1px solid var(--border-strong);
88
+ border-radius: var(--r-md);
89
+ box-shadow: var(--shadow-med);
90
+ padding: 10px;
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: 8px;
94
+ width: 220px;
95
+ }
96
+ .name-popup-input {
97
+ width: 100%;
98
+ padding: 7px 10px;
99
+ background: var(--bg-canvas);
100
+ color: var(--text-1);
101
+ border: 1px solid var(--border-subtle);
102
+ border-radius: var(--r-sm);
103
+ font: inherit;
104
+ font-size: 12px;
105
+ outline: none;
106
+ transition: border-color var(--t-fast), box-shadow var(--t-fast);
107
+ }
108
+ .name-popup-input:focus {
109
+ border-color: var(--accent-blue-soft);
110
+ box-shadow: 0 0 0 3px rgba(122, 155, 255, 0.12);
111
+ }
112
+ .name-popup-row {
113
+ display: flex;
114
+ justify-content: flex-end;
115
+ gap: 6px;
116
+ }
117
+ .btn.btn-primary {
118
+ background: var(--accent-blue-soft);
119
+ color: var(--text-1);
120
+ border-color: var(--accent-blue);
121
+ }
122
+ .btn.btn-primary:hover {
123
+ background: var(--accent-blue);
124
+ color: var(--bg-canvas);
125
+ }
126
+
127
+ /* Segmented control (Perspective | Orthographic) */
128
+ .segmented {
129
+ display: inline-flex;
130
+ border: 1px solid var(--border-subtle);
131
+ border-radius: var(--r-sm);
132
+ overflow: hidden;
133
+ align-self: flex-start;
134
+ }
135
+ .seg-btn {
136
+ background: var(--bg-panel);
137
+ color: var(--text-2);
138
+ border: none;
139
+ padding: 5px 12px;
140
+ font-size: 11px;
141
+ font-weight: 500;
142
+ cursor: pointer;
143
+ transition: background var(--t-fast), color var(--t-fast);
144
+ }
145
+ .seg-btn + .seg-btn {
146
+ border-left: 1px solid var(--border-subtle);
147
+ }
148
+ .seg-btn:hover { background: var(--bg-hover); color: var(--text-1); }
149
+ .seg-btn.active {
150
+ background: var(--accent-blue-soft);
151
+ color: var(--text-1);
152
+ }
153
+
154
+ /* ── Elements panel (left sidebar) ── */
155
+
156
+ #layers-panel {
157
+ padding: 0;
158
+ border-bottom: 1px solid var(--border-subtle);
159
+ }
160
+
161
+ #layers-panel h3 {
162
+ padding: 12px 16px 11px;
163
+ background: linear-gradient(180deg, var(--bg-panel-strong) 0%, var(--bg-panel) 100%);
164
+ border-bottom: 1px solid var(--border-subtle);
165
+ font-size: 11px;
166
+ font-weight: 600;
167
+ letter-spacing: 0.08em;
168
+ text-transform: uppercase;
169
+ color: var(--accent-blue);
170
+ margin: 0;
171
+ position: relative;
172
+ }
173
+ #layers-panel h3::before {
174
+ content: '';
175
+ position: absolute;
176
+ left: 0; top: 8px; bottom: 8px;
177
+ width: 3px;
178
+ border-radius: 0 2px 2px 0;
179
+ background: var(--accent-blue);
180
+ opacity: 0.85;
181
+ }
182
+
183
+ .layer-toggle {
184
+ padding: 8px 16px;
185
+ display: flex;
186
+ align-items: center;
187
+ gap: 10px;
188
+ cursor: pointer;
189
+ font-size: 12px;
190
+ color: var(--text-1);
191
+ border-bottom: 1px solid var(--border-hairline);
192
+ user-select: none;
193
+ transition: background var(--t-fast);
194
+ }
195
+
196
+ .layer-toggle:hover {
197
+ background: var(--bg-hover);
198
+ }
199
+
200
+ /* ── Layer-row toggles ──────────────────────────────────────────────
201
+ Two controls per contour row that used to be near-identical native
202
+ checkboxes (blue vs amber accent — easy to confuse). Redesigned as two
203
+ visually ORTHOGONAL custom toggles so their roles read at a glance:
204
+ • visibility → a SQUARE show/hide box (checkmark when shown)
205
+ • highlight → a ROUND colour swatch (vivid when "bright", hollow when dim)
206
+ Both remain real <input type=checkbox> (accessibility + the existing
207
+ cascade logic dispatches native change events), just restyled. */
208
+
209
+ .layer-toggle input[type="checkbox"] {
210
+ appearance: none;
211
+ -webkit-appearance: none;
212
+ margin: 0;
213
+ flex-shrink: 0;
214
+ cursor: pointer;
215
+ position: relative;
216
+ transition: background var(--t-fast), border-color var(--t-fast);
217
+ }
218
+
219
+ /* Visibility: square box, blue when shown */
220
+ .layer-toggle input.vis-cb,
221
+ .layer-toggle > input[type="checkbox"]:not(.hl-cb) {
222
+ width: 14px;
223
+ height: 14px;
224
+ border: 1.5px solid var(--border-strong);
225
+ border-radius: var(--r-sm);
226
+ background: transparent;
227
+ }
228
+ .layer-toggle input.vis-cb:hover,
229
+ .layer-toggle > input[type="checkbox"]:not(.hl-cb):hover {
230
+ border-color: var(--accent-blue);
231
+ }
232
+ .layer-toggle input.vis-cb:checked,
233
+ .layer-toggle > input[type="checkbox"]:not(.hl-cb):checked {
234
+ background: var(--accent-blue);
235
+ border-color: var(--accent-blue);
236
+ }
237
+ /* checkmark */
238
+ .layer-toggle input.vis-cb:checked::after,
239
+ .layer-toggle > input[type="checkbox"]:not(.hl-cb):checked::after {
240
+ content: '';
241
+ position: absolute;
242
+ left: 4px; top: 1px;
243
+ width: 4px; height: 8px;
244
+ border: solid var(--bg-canvas);
245
+ border-width: 0 2px 2px 0;
246
+ transform: rotate(45deg);
247
+ }
248
+
249
+ /* Highlight: round swatch. Vivid amber→orange gradient = "bright colour on";
250
+ hollow ring = "dimmed to gray". */
251
+ .layer-toggle input.hl-cb {
252
+ width: 14px;
253
+ height: 14px;
254
+ border-radius: 50%;
255
+ border: 1.5px solid var(--border-strong);
256
+ background: transparent;
257
+ }
258
+ .layer-toggle input.hl-cb:hover {
259
+ border-color: var(--accent-amber);
260
+ }
261
+ .layer-toggle input.hl-cb:checked {
262
+ border-color: transparent;
263
+ background: radial-gradient(circle at 35% 30%, var(--accent-amber), var(--accent-orange));
264
+ box-shadow: 0 0 5px rgba(240, 132, 74, 0.5);
265
+ }
266
+
267
+ .layer-toggle .layer-label {
268
+ flex: 1;
269
+ overflow: hidden;
270
+ text-overflow: ellipsis;
271
+ white-space: nowrap;
272
+ }
273
+
274
+ .layer-toggle .layer-count {
275
+ color: var(--text-3);
276
+ font-size: 10px;
277
+ font-variant-numeric: tabular-nums;
278
+ }
279
+
280
+ .layer-sub-toggle {
281
+ padding-left: 40px;
282
+ font-size: 11px;
283
+ background: var(--bg-canvas);
284
+ color: var(--text-2);
285
+ border-bottom: 1px solid var(--border-hairline);
286
+ transition: background var(--t-fast);
287
+ }
288
+
289
+ .tree-arrow {
290
+ font-size: 9px;
291
+ width: 12px;
292
+ cursor: pointer;
293
+ color: var(--text-3);
294
+ flex-shrink: 0;
295
+ transition: color var(--t-fast);
296
+ }
297
+ .tree-arrow:hover { color: var(--text-1); }
298
+
299
+ .tree-children {
300
+ border-left: 1px solid var(--border-subtle);
301
+ margin-left: 10px;
302
+ }
303
+
304
+ .layer-sub-toggle:hover {
305
+ background: var(--bg-hover);
306
+ }
307
+
308
+ /* ── Camera tree (left sidebar) ── */
309
+
310
+ #camera-tree-panel {
311
+ flex: 1;
312
+ overflow-y: auto;
313
+ border-top: 1px solid var(--border-subtle);
314
+ }
315
+
316
+ #camera-tree-panel h3 {
317
+ padding: 12px 16px 11px;
318
+ background: linear-gradient(180deg, var(--bg-panel-strong) 0%, var(--bg-panel) 100%);
319
+ border-bottom: 1px solid var(--border-subtle);
320
+ font-size: 11px;
321
+ font-weight: 600;
322
+ letter-spacing: 0.08em;
323
+ text-transform: uppercase;
324
+ color: var(--accent-pink);
325
+ margin: 0;
326
+ position: relative;
327
+ }
328
+ #camera-tree-panel h3::before {
329
+ content: '';
330
+ position: absolute;
331
+ left: 0; top: 8px; bottom: 8px;
332
+ width: 3px;
333
+ border-radius: 0 2px 2px 0;
334
+ background: var(--accent-pink);
335
+ opacity: 0.85;
336
+ }
337
+
338
+ .camera-tree {
339
+ overflow-y: auto;
340
+ }
341
+
342
+ .cam-tree-item {
343
+ border-bottom: 1px solid var(--border-hairline);
344
+ }
345
+
346
+ .cam-tree-header {
347
+ padding: 8px 16px;
348
+ cursor: pointer;
349
+ font-size: 12px;
350
+ color: var(--text-1);
351
+ display: flex;
352
+ align-items: center;
353
+ gap: 8px;
354
+ user-select: none;
355
+ transition: background var(--t-fast);
356
+ }
357
+
358
+ .cam-tree-header:hover {
359
+ background: var(--bg-hover);
360
+ }
361
+
362
+ .cam-tree-header.selected {
363
+ background: linear-gradient(90deg, rgba(255, 149, 194, 0.16) 0%, transparent 100%);
364
+ border-left: 3px solid var(--accent-pink);
365
+ padding-left: 13px;
366
+ }
367
+
368
+ .cam-tree-header .cam-dot {
369
+ width: 9px;
370
+ height: 9px;
371
+ border-radius: 50%;
372
+ flex-shrink: 0;
373
+ box-shadow: 0 0 0 2px var(--bg-sidebar), 0 0 8px currentColor;
374
+ }
375
+
376
+ .cam-tree-header .cam-name {
377
+ flex: 1;
378
+ min-width: 0; /* allow ellipsis inside flex */
379
+ overflow: hidden;
380
+ text-overflow: ellipsis;
381
+ white-space: nowrap;
382
+ }
383
+
384
+ .cam-tree-header .cam-flow-count {
385
+ color: var(--text-3);
386
+ font-size: 10px;
387
+ font-variant-numeric: tabular-nums;
388
+ padding: 1px 7px;
389
+ border-radius: 999px;
390
+ background: var(--bg-panel-strong);
391
+ border: 1px solid var(--border-subtle);
392
+ }
393
+
394
+ /* Nested flow list under camera (now: camera → useCase → flows) */
395
+ .cam-tree-flows {
396
+ padding-left: 18px;
397
+ border-left: 1px solid var(--border-subtle);
398
+ margin-left: 18px;
399
+ }
400
+
401
+ .cam-tree-flows.collapsed {
402
+ display: none;
403
+ }
404
+
405
+ .cam-tree-uc-group {
406
+ border-left: 1px solid var(--border-hairline);
407
+ margin-left: 2px;
408
+ }
409
+
410
+ .cam-tree-uc-header {
411
+ padding: 6px 12px;
412
+ cursor: pointer;
413
+ font-size: 10px;
414
+ font-weight: 600;
415
+ text-transform: uppercase;
416
+ letter-spacing: 0.06em;
417
+ color: var(--text-3);
418
+ display: flex;
419
+ align-items: center;
420
+ gap: 6px;
421
+ user-select: none;
422
+ transition: background var(--t-fast), color var(--t-fast);
423
+ }
424
+
425
+ .cam-tree-uc-header:hover {
426
+ background: var(--bg-hover);
427
+ color: var(--text-1);
428
+ }
429
+
430
+ .cam-tree-uc-header .uc-name {
431
+ flex: 1;
432
+ min-width: 0;
433
+ overflow: hidden;
434
+ text-overflow: ellipsis;
435
+ white-space: nowrap;
436
+ }
437
+
438
+ .cam-tree-uc-header .uc-flow-count {
439
+ color: var(--text-4);
440
+ font-size: 10px;
441
+ font-variant-numeric: tabular-nums;
442
+ }
443
+
444
+ .cam-tree-uc-flows {
445
+ padding-left: 12px;
446
+ }
447
+
448
+ .cam-tree-uc-flows.collapsed {
449
+ display: none;
450
+ }
451
+
452
+ .cam-tree-flow {
453
+ padding: 6px 16px;
454
+ cursor: pointer;
455
+ font-size: 11px;
456
+ color: var(--text-2);
457
+ display: flex;
458
+ align-items: center;
459
+ gap: 8px;
460
+ user-select: none;
461
+ border-bottom: 1px solid var(--border-hairline);
462
+ transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
463
+ }
464
+
465
+ .cam-tree-flow:hover {
466
+ background: var(--bg-hover);
467
+ color: var(--text-1);
468
+ }
469
+
470
+ .cam-tree-flow.active {
471
+ background: linear-gradient(90deg, rgba(240, 132, 74, 0.18) 0%, transparent 100%);
472
+ color: var(--accent-orange);
473
+ border-left: 2px solid var(--accent-orange);
474
+ padding-left: 14px;
475
+ }
476
+
477
+ .cam-tree-flow .flow-icon {
478
+ font-size: 9px;
479
+ color: var(--text-3);
480
+ transition: color var(--t-fast);
481
+ }
482
+ .cam-tree-flow:hover .flow-icon { color: var(--text-1); }
483
+ .cam-tree-flow.active .flow-icon { color: var(--accent-orange); }
484
+
485
+ .cam-tree-flow .flow-name {
486
+ flex: 1;
487
+ overflow: hidden;
488
+ text-overflow: ellipsis;
489
+ white-space: nowrap;
490
+ }
491
+
492
+ .cam-tree-flow .flow-step-count {
493
+ color: var(--text-4);
494
+ font-size: 10px;
495
+ font-variant-numeric: tabular-nums;
496
+ }
497
+
498
+ .cam-tree-flow .flow-play-btn {
499
+ background: transparent;
500
+ border: 1px solid var(--border-subtle);
501
+ color: var(--text-3);
502
+ font-size: 9px;
503
+ cursor: pointer;
504
+ padding: 2px 6px;
505
+ border-radius: var(--r-sm);
506
+ line-height: 1;
507
+ transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
508
+ }
509
+
510
+ .cam-tree-flow .flow-play-btn:hover {
511
+ background: var(--bg-active);
512
+ color: var(--text-1);
513
+ border-color: var(--border-strong);
514
+ }
515
+
516
+ /* ── Right sidebar (camera inspector) ── */
517
+
518
+ .right-sidebar {
519
+ border-right: none;
520
+ border-left: 1px solid var(--border-subtle);
521
+ }
522
+
523
+ #right-sidebar h3 {
524
+ padding: 12px 16px 11px;
525
+ background: linear-gradient(180deg, var(--bg-panel-strong) 0%, var(--bg-panel) 100%);
526
+ border-bottom: 1px solid var(--border-subtle);
527
+ font-size: 11px;
528
+ font-weight: 600;
529
+ letter-spacing: 0.08em;
530
+ text-transform: uppercase;
531
+ color: var(--accent-pink);
532
+ margin: 0;
533
+ display: flex;
534
+ justify-content: space-between;
535
+ align-items: center;
536
+ position: relative;
537
+ }
538
+ #right-sidebar h3::before {
539
+ content: '';
540
+ position: absolute;
541
+ left: 0; top: 8px; bottom: 8px;
542
+ width: 3px;
543
+ border-radius: 0 2px 2px 0;
544
+ background: var(--accent-pink);
545
+ opacity: 0.85;
546
+ }
547
+
548
+ #right-sidebar h3 .close-btn {
549
+ cursor: pointer;
550
+ color: var(--text-3);
551
+ font-size: 16px;
552
+ line-height: 1;
553
+ padding: 0 4px;
554
+ border-radius: var(--r-sm);
555
+ transition: color var(--t-fast), background var(--t-fast);
556
+ }
557
+
558
+ #right-sidebar h3 .close-btn:hover {
559
+ color: var(--text-1);
560
+ background: var(--bg-hover);
561
+ }
562
+
563
+ #camera-detail {
564
+ padding: 0;
565
+ overflow-y: auto;
566
+ flex: 1;
567
+ }
568
+
569
+ .no-selection {
570
+ padding: 24px 16px;
571
+ color: var(--text-3);
572
+ font-size: 12px;
573
+ text-align: center;
574
+ font-style: italic;
575
+ }
576
+
577
+ /* ── Flow step navigation (right sidebar) ── */
578
+
579
+ #flow-nav {
580
+ padding: 10px 16px;
581
+ border-bottom: 1px solid var(--border-subtle);
582
+ background: var(--bg-panel);
583
+ }
584
+
585
+ #flow-nav .flow-nav-title {
586
+ font-size: 11px;
587
+ color: var(--accent-orange);
588
+ margin-bottom: 8px;
589
+ font-weight: 600;
590
+ letter-spacing: 0.02em;
591
+ overflow: hidden;
592
+ text-overflow: ellipsis;
593
+ white-space: nowrap;
594
+ }
595
+
596
+ .flow-step-nav {
597
+ display: flex;
598
+ align-items: center;
599
+ justify-content: center;
600
+ gap: 10px;
601
+ margin-bottom: 6px;
602
+ }
603
+
604
+ .btn-small {
605
+ background: var(--bg-panel-strong);
606
+ color: var(--text-1);
607
+ border: 1px solid var(--border-subtle);
608
+ border-radius: var(--r-sm);
609
+ padding: 4px 10px;
610
+ cursor: pointer;
611
+ font-size: 13px;
612
+ line-height: 1;
613
+ transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast),
614
+ transform var(--t-fast);
615
+ }
616
+
617
+ .btn-small:hover {
618
+ background: var(--bg-active);
619
+ color: var(--text-1);
620
+ border-color: var(--border-strong);
621
+ }
622
+ .btn-small:active { transform: translateY(1px); }
623
+
624
+ #step-counter {
625
+ font-size: 12px;
626
+ color: var(--text-2);
627
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
628
+ font-variant-numeric: tabular-nums;
629
+ min-width: 100px;
630
+ text-align: center;
631
+ }
632
+
633
+ /* Step info grid */
634
+ .step-info-grid {
635
+ font-size: 11px;
636
+ }
637
+
638
+ .si-row {
639
+ display: flex;
640
+ justify-content: space-between;
641
+ padding: 3px 0;
642
+ }
643
+
644
+ .si-label {
645
+ color: var(--text-3);
646
+ }
647
+
648
+ .si-value {
649
+ color: var(--accent-green);
650
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
651
+ font-variant-numeric: tabular-nums;
652
+ }
653
+
654
+ /* ── Parameter sections ── */
655
+
656
+ .param-section {
657
+ padding: 0 16px;
658
+ margin-bottom: 10px;
659
+ }
660
+
661
+ .param-section-title {
662
+ font-size: 10px;
663
+ color: var(--text-3);
664
+ text-transform: uppercase;
665
+ letter-spacing: 0.08em;
666
+ font-weight: 600;
667
+ margin-bottom: 6px;
668
+ padding: 10px 0 5px;
669
+ border-bottom: 1px solid var(--border-subtle);
670
+ }
671
+
672
+ .param-row {
673
+ display: flex;
674
+ justify-content: space-between;
675
+ padding: 3px 0;
676
+ font-size: 11px;
677
+ }
678
+
679
+ .param-name {
680
+ color: var(--text-3);
681
+ }
682
+
683
+ .param-value {
684
+ color: var(--accent-green);
685
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
686
+ font-variant-numeric: tabular-nums;
687
+ }
688
+
689
+ /* Camera POV button — on the shared button palette (blue accent), not the
690
+ old bespoke purple that clashed with the rest of the UI. */
691
+ .pov-section {
692
+ padding: 8px 16px;
693
+ border-bottom: 1px solid var(--border-hairline);
694
+ }
695
+
696
+ .btn-pov {
697
+ width: 100%;
698
+ padding: 6px 12px;
699
+ background: var(--bg-panel);
700
+ color: var(--text-2);
701
+ border: 1px solid var(--border-subtle);
702
+ border-radius: var(--r-sm);
703
+ cursor: pointer;
704
+ font-size: 12px;
705
+ font-family: inherit;
706
+ transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
707
+ }
708
+
709
+ .btn-pov:hover {
710
+ background: var(--bg-hover);
711
+ color: var(--text-1);
712
+ border-color: var(--border-strong);
713
+ }
714
+
715
+ .btn-pov.active {
716
+ background: var(--bg-active);
717
+ color: var(--accent-blue);
718
+ border-color: var(--accent-blue-soft);
719
+ box-shadow: 0 0 0 1px rgba(122, 155, 255, 0.18);
720
+ }
721
+
722
+ /* PTZ slider controls */
723
+ .ptz-edit-section {
724
+ padding: 8px 16px;
725
+ border-bottom: 1px solid var(--border-hairline);
726
+ }
727
+
728
+ .slider-group {
729
+ margin-bottom: 8px;
730
+ }
731
+
732
+ .slider-label {
733
+ display: flex;
734
+ justify-content: space-between;
735
+ margin-bottom: 3px;
736
+ font-size: 11px;
737
+ }
738
+
739
+ .slider-label .name {
740
+ color: var(--text-2);
741
+ }
742
+
743
+ .slider-label .value {
744
+ color: var(--text-1);
745
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
746
+ font-variant-numeric: tabular-nums;
747
+ font-weight: bold;
748
+ }
749
+
750
+ input[type="range"] {
751
+ width: 100%;
752
+ height: 4px;
753
+ appearance: none;
754
+ background: var(--bg-panel-strong);
755
+ border-radius: 2px;
756
+ outline: none;
757
+ cursor: pointer;
758
+ }
759
+
760
+ input[type="range"]::-webkit-slider-thumb {
761
+ appearance: none;
762
+ width: 14px;
763
+ height: 14px;
764
+ background: var(--accent-blue);
765
+ border-radius: 50%;
766
+ cursor: pointer;
767
+ }
768
+
769
+ input[type="range"]::-moz-range-thumb {
770
+ width: 14px;
771
+ height: 14px;
772
+ background: var(--accent-blue);
773
+ border-radius: 50%;
774
+ cursor: pointer;
775
+ border: none;
776
+ }
777
+
778
+ /* Vector input (X, Y, Z number fields) */
779
+ .param-edit-row {
780
+ margin-bottom: 6px;
781
+ }
782
+
783
+ .param-label-small {
784
+ display: block;
785
+ font-size: 10px;
786
+ color: var(--text-3);
787
+ margin-bottom: 3px;
788
+ }
789
+
790
+ .vector-input {
791
+ display: flex;
792
+ gap: 4px;
793
+ }
794
+
795
+ .vector-input input[type="number"] {
796
+ flex: 1;
797
+ width: 0;
798
+ padding: 4px 6px;
799
+ background: var(--bg-canvas);
800
+ border: 1px solid var(--border-subtle);
801
+ border-radius: var(--r-sm);
802
+ color: var(--accent-green);
803
+ font-size: 11px;
804
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
805
+ outline: none;
806
+ transition: border-color var(--t-fast), box-shadow var(--t-fast);
807
+ }
808
+
809
+ .vector-input input[type="number"]:focus {
810
+ border-color: var(--accent-blue-soft);
811
+ box-shadow: 0 0 0 3px rgba(122, 155, 255, 0.12);
812
+ }
813
+
814
+ .vector-input input[type="number"]::-webkit-inner-spin-button {
815
+ opacity: 0.3;
816
+ }
817
+
818
+ /* ── Image panel (flow step images) ── */
819
+
820
+ #image-panel {
821
+ border-top: 1px solid var(--border-subtle);
822
+ background: var(--bg-canvas);
823
+ padding: 8px 10px;
824
+ }
825
+
826
+ .image-nav {
827
+ display: flex;
828
+ align-items: center;
829
+ justify-content: center;
830
+ gap: 10px;
831
+ margin-bottom: 6px;
832
+ }
833
+
834
+ #image-counter {
835
+ font-size: 11px;
836
+ color: var(--text-3);
837
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
838
+ font-variant-numeric: tabular-nums;
839
+ min-width: 40px;
840
+ text-align: center;
841
+ }
842
+
843
+ #image-display {
844
+ width: 100%;
845
+ line-height: 0;
846
+ }
847
+
848
+ #step-image {
849
+ width: 100%;
850
+ height: auto;
851
+ border: 1px solid var(--border-subtle);
852
+ border-radius: var(--r-sm);
853
+ display: block;
854
+ background: var(--bg-canvas);
855
+ cursor: pointer;
856
+ transition: opacity var(--t-fast);
857
+ }
858
+
859
+ #step-image:hover {
860
+ opacity: 0.85;
861
+ }
862
+
863
+ /* ── Bottom image lightbox ── */
864
+
865
+ #image-lightbox {
866
+ height: 280px;
867
+ background: var(--bg-canvas);
868
+ display: flex;
869
+ flex-direction: column;
870
+ flex-shrink: 0;
871
+ }
872
+
873
+ .lightbox-header {
874
+ display: flex;
875
+ align-items: center;
876
+ gap: 10px;
877
+ padding: 5px 12px;
878
+ background: var(--bg-sidebar);
879
+ border-bottom: 1px solid var(--border-subtle);
880
+ flex-shrink: 0;
881
+ }
882
+
883
+ #lightbox-counter {
884
+ font-size: 11px;
885
+ color: var(--text-3);
886
+ font-family: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, monospace;
887
+ font-variant-numeric: tabular-nums;
888
+ min-width: 40px;
889
+ }
890
+
891
+ .lightbox-nav {
892
+ display: flex;
893
+ gap: 6px;
894
+ }
895
+
896
+ .lightbox-header .close-btn {
897
+ margin-left: auto;
898
+ cursor: pointer;
899
+ color: var(--text-3);
900
+ font-size: 18px;
901
+ padding: 0 4px;
902
+ line-height: 1;
903
+ border-radius: var(--r-sm);
904
+ transition: color var(--t-fast), background var(--t-fast);
905
+ }
906
+
907
+ .lightbox-header .close-btn:hover {
908
+ color: var(--text-1);
909
+ background: var(--bg-hover);
910
+ }
911
+
912
+ .lightbox-body {
913
+ flex: 1;
914
+ display: flex;
915
+ align-items: center;
916
+ justify-content: center;
917
+ overflow: hidden;
918
+ background: var(--bg-canvas);
919
+ }
920
+
921
+ #lightbox-img {
922
+ max-width: 100%;
923
+ max-height: 100%;
924
+ object-fit: contain;
925
+ display: block;
926
+ }