agentgui 1.0.948 → 1.0.949

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.
@@ -54,8 +54,32 @@
54
54
 
55
55
  --accent: var(--green);
56
56
  --accent-fg: var(--paper);
57
+ --accent-bright: var(--green-2); /* base value so var(--accent-bright) never falls back empty; ink + [data-accent] retune it */
57
58
  --accent-tint: color-mix(in oklab, var(--accent) 26%, var(--bg));
58
59
 
60
+ /* On-color foregrounds — text/icons that sit ON a saturated fill (accent,
61
+ danger, category chips). Theme-driven so white-on-color never hard-codes
62
+ #fff. --on-accent tracks --accent-fg; --on-color is the generic light
63
+ foreground for any colored fill. */
64
+ --on-accent: var(--accent-fg);
65
+ --on-color: #fff;
66
+
67
+ /* Scrims — modal/overlay backdrops. Derived from --fg so a dark theme dims
68
+ with its own ink rather than a baked rgba(0,0,0). */
69
+ --scrim: color-mix(in oklab, var(--fg) 40%, transparent);
70
+ --scrim-strong: color-mix(in oklab, var(--fg) 72%, transparent);
71
+ --scrim-media: color-mix(in oklab, var(--fg) 85%, transparent);
72
+
73
+ /* Category palette — surfaces (forum tags, project cards) that color-code by
74
+ category. Canonical so a theme/accent swap recolors categories instead of
75
+ drifting from a private --cat-* block. Derived from the base palette. */
76
+ --cat-green: var(--green-2);
77
+ --cat-purple: var(--purple-2);
78
+ --cat-mascot: var(--mascot);
79
+ --cat-sun: var(--sun);
80
+ --cat-flame: var(--flame);
81
+ --cat-sky: var(--sky);
82
+
59
83
  --panel-bg: var(--bg);
60
84
  --panel-bg-2: var(--bg-2);
61
85
  --panel-accent: var(--accent);
@@ -277,6 +301,47 @@
277
301
  --panel-text-3: inherit;
278
302
  --panel-accent-2: inherit;
279
303
  --panel-shadow: inherit;
304
+ --on-accent: inherit;
305
+ --on-color: inherit;
306
+ --scrim: inherit;
307
+ --scrim-strong: inherit;
308
+ --scrim-media: inherit;
309
+ --cat-green: inherit;
310
+ --cat-purple: inherit;
311
+ --cat-mascot: inherit;
312
+ --cat-sun: inherit;
313
+ --cat-flame: inherit;
314
+ --cat-sky: inherit;
315
+ }
316
+
317
+ /* ============================================================
318
+ Named-theme preset contract
319
+ ------------------------------------------------------------
320
+ A theme is one [data-theme="X"] block that overrides ONLY the semantic
321
+ surface tokens — never component rules, never raw literals in component
322
+ sheets. The base :root above IS the "paper" theme; [data-theme="paper"]
323
+ restates it so the attribute is explicit and round-trippable. To add a
324
+ theme: copy a block, rename the attr, retune the ~8 semantic tokens.
325
+ ============================================================ */
326
+ .ds-247420[data-theme="paper"] {
327
+ color-scheme: light;
328
+ --bg: var(--paper); --bg-2: var(--paper-2); --bg-3: var(--paper-3);
329
+ --fg: var(--ink); --fg-2: var(--ink-2); --fg-3: var(--ink-3);
330
+ --accent: var(--green); --accent-fg: var(--paper);
331
+ }
332
+
333
+ /* thebird — warm-paper brand preset. A first-class swappable theme: it lives
334
+ here in the canonical layer (not as a global :root override) so any consumer
335
+ can opt in with data-theme="thebird". The OS-shell chrome (bar heights,
336
+ window controls) stays in src/kits/os/theme.css; only color lives here. */
337
+ .ds-247420[data-theme="thebird"] {
338
+ color-scheme: light;
339
+ --paper: #F5F0E4;
340
+ --paper-2: #EFE9DB;
341
+ --paper-3: #E3DAC7;
342
+ --bg: var(--paper); --bg-2: var(--paper-2); --bg-3: var(--paper-3);
343
+ --fg: var(--ink); --fg-2: var(--ink-2); --fg-3: var(--ink-3);
344
+ --accent: var(--green); --accent-fg: var(--paper);
280
345
  }
281
346
 
282
347
  .ds-247420[data-density="compact"] { --density: 0.75; }
@@ -322,6 +387,10 @@
322
387
  0 2px 4px color-mix(in oklab, var(--fg) 6%, transparent);
323
388
  --shadow-3: 0 12px 32px color-mix(in oklab, var(--fg) 14%, transparent),
324
389
  0 4px 8px color-mix(in oklab, var(--fg) 8%, transparent);
390
+ /* Overlay elevation — the float for dialogs/lightboxes that sit above a
391
+ scrim; heavier than --shadow-3 and theme-driven (was raw rgba(0,0,0,.4)). */
392
+ --shadow-overlay: 0 12px 40px color-mix(in oklab, var(--fg) 28%, transparent),
393
+ 0 4px 12px color-mix(in oklab, var(--fg) 16%, transparent);
325
394
  --z-dropdown: 600;
326
395
  --z-popover: 700;
327
396
  --z-modal: 800;
@@ -466,7 +535,7 @@
466
535
 
467
536
  .ds-247420 pre {
468
537
  font-family: var(--ff-mono);
469
- background: var(--panel-bg, #15151a);
538
+ background: var(--panel-bg);
470
539
  color: var(--panel-text, inherit);
471
540
  padding: var(--space-5);
472
541
  overflow-x: auto;
@@ -477,7 +546,7 @@
477
546
  }
478
547
  .ds-247420 pre .k { color: var(--mascot); }
479
548
  .ds-247420 pre .s { color: var(--sun); }
480
- .ds-247420 pre .c { color: #9A9AA2; }
549
+ .ds-247420 pre .c { color: var(--fg-3); }
481
550
  .ds-247420 pre .n { color: var(--green-2); }
482
551
 
483
552
  /* ============================================================
@@ -662,7 +731,14 @@
662
731
  align-self: stretch;
663
732
  height: 100%;
664
733
  }
665
- .ds-247420 .app-main > * { min-height: 0; }
734
+ /* Document children (hero, sections, panels) keep their natural height in the
735
+ scrolling flex column. Without flex-shrink:0 the flex algorithm shrinks them
736
+ toward min-height:0 once total content exceeds the fixed-height .app-main,
737
+ collapsing every section to 0 and piling content on top of itself — the
738
+ failure mode any long-scroll page (a marketing/landing route) hits. Grow
739
+ children (.chat/.grow/etc.) re-assert flex:1 1 auto below via higher
740
+ specificity, so a single full-height pane still fills the region. */
741
+ .ds-247420 .app-main > * { min-height: 0; flex-shrink: 0; }
666
742
  /* The main region scrolls its own overflow at every breakpoint (previously
667
743
  only ≥901px), so a fixed-height .app never clips route content and inner
668
744
  panels don't fight the page scroll. */
@@ -864,6 +940,11 @@
864
940
  .ds-247420 .row.row-state-disabled { opacity: 0.5; pointer-events: none; }
865
941
  .ds-247420 .row.row-state-error { background: color-mix(in oklab, var(--flame) 10%, var(--bg-2)); }
866
942
  .ds-247420 .row.row-state-error::before { background: var(--flame); }
943
+ /* rail tones — a persistent status colour on the leading rail (the ::before
944
+ bar). Active/hover/error still win via their own rules below source order. */
945
+ .ds-247420 .row.rail-green::before { background: var(--accent); }
946
+ .ds-247420 .row.rail-purple::before { background: var(--purple-2, #7F18A4); }
947
+ .ds-247420 .row.rail-flame::before { background: var(--flame); }
867
948
  .ds-247420 .row-grid { /* explicit grid-template-columns set inline */ }
868
949
 
869
950
  .ds-247420 .row .code { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); }
@@ -921,10 +1002,10 @@
921
1002
  .ds-247420 .cli .copy {
922
1003
  padding: 8px 16px; background: transparent; color: var(--paper);
923
1004
  font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--tr-caps);
924
- cursor: pointer; box-shadow: inset 0 0 0 1px #6A6A70;
1005
+ cursor: pointer; box-shadow: inset 0 0 0 1px var(--rule-strong);
925
1006
  border-radius: var(--r-pill);
926
1007
  }
927
- .ds-247420 .cli .copy:hover { background: #6A6A70; }
1008
+ .ds-247420 .cli .copy:hover { background: var(--fg-3); }
928
1009
 
929
1010
  /* Multi-line CLI block: when .cli holds .cli-line / .cli-cmt children
930
1011
  (quickstart scripts, multi-command snippets) it stacks as a column
@@ -1026,6 +1107,7 @@
1026
1107
  /* ============================================================
1027
1108
  Currently shipping dots
1028
1109
  ============================================================ */
1110
+ .ds-247420 .ds-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex-shrink: 0; vertical-align: middle; }
1029
1111
  .ds-247420 .ds-dot-on { color: var(--green-2); }
1030
1112
  .ds-247420 .ds-dot-off { color: var(--fg-3); }
1031
1113
  .ds-247420 .ds-dot-live { color: var(--green-2); }
@@ -1118,8 +1200,13 @@
1118
1200
  .ds-247420 .app-topbar {
1119
1201
  gap: var(--space-2); padding: 12px var(--space-3);
1120
1202
  }
1203
+ /* When the topbar is folded into .app-chrome it is a flex:0 0 auto child, so
1204
+ it sizes to its nav's content and overflows the viewport instead of letting
1205
+ the nav's own overflow-x:auto engage. Constrain it to the chrome width so
1206
+ the horizontally-scrolling nav stays inside the screen. */
1207
+ .ds-247420 .app-chrome > .app-topbar { max-width: 100%; min-width: 0; flex-basis: 100%; }
1121
1208
  .ds-247420 .app-topbar > nav {
1122
- flex: 1 1 100%; margin-left: 0; order: 3;
1209
+ flex: 1 1 100%; margin-left: 0; order: 3; min-width: 0; max-width: 100%;
1123
1210
  display: flex; gap: 2px; flex-wrap: nowrap;
1124
1211
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
1125
1212
  }
@@ -1617,7 +1704,7 @@
1617
1704
  .ds-247420 .btn-primary.danger {
1618
1705
  background: var(--warn);
1619
1706
  border-color: var(--warn);
1620
- color: #fff;
1707
+ color: var(--on-color);
1621
1708
  }
1622
1709
 
1623
1710
  /* ── Preview ──────────────────────────────────────────────── */
@@ -1801,7 +1888,7 @@
1801
1888
  .ds-247420 .ds-segmented .ds-seg-btn:hover { color: var(--fg); }
1802
1889
  .ds-247420 .ds-segmented .ds-seg-btn.is-on {
1803
1890
  background: var(--bg); color: var(--fg);
1804
- box-shadow: 0 1px 2px rgba(0,0,0,0.08);
1891
+ box-shadow: var(--shadow-1);
1805
1892
  }
1806
1893
  .ds-247420 .ds-theme-toggle.btn {
1807
1894
  font-family: var(--ff-mono); font-size: var(--fs-xs);
@@ -2571,7 +2658,7 @@
2571
2658
  }
2572
2659
  .ds-247420 .ds-field input[aria-invalid="true"],
2573
2660
  .ds-247420 .ds-field textarea[aria-invalid="true"] {
2574
- box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--flame, #d64545);
2661
+ box-shadow: inset 0 0 0 var(--bw-hair, 1px) var(--flame);
2575
2662
  }
2576
2663
 
2577
2664
  /* Clear button for text inputs */
@@ -2864,6 +2951,7 @@
2864
2951
  font-size: var(--fs-sm);
2865
2952
  color: var(--fg-2);
2866
2953
  }
2954
+ .ds-247420 .ds-alert-retry { margin-top: var(--space-2); }
2867
2955
 
2868
2956
  .ds-247420 .ds-alert-dismiss {
2869
2957
  flex-shrink: 0;
@@ -4433,9 +4521,9 @@
4433
4521
  cursor: pointer; font-size: 16px; line-height: 1;
4434
4522
  }
4435
4523
  .ds-247420 .vx-vc-btn:hover { background: var(--bg-4, var(--bg-3)); }
4436
- .ds-247420 .vx-vc-on { background: var(--accent); color: var(--accent-fg, #fff); border-color: var(--accent); }
4524
+ .ds-247420 .vx-vc-on { background: var(--accent); color: var(--accent-fg); border-color: var(--accent); }
4437
4525
  .ds-247420 .vx-vc-disabled, .ds-247420 .vx-vc-btn:disabled { opacity: .4; cursor: not-allowed; }
4438
- .ds-247420 .vx-vc-leave { margin-left: auto; background: var(--danger, #d04545); color: #fff; border-color: var(--danger, #d04545); }
4526
+ .ds-247420 .vx-vc-leave { margin-left: auto; background: var(--danger); color: var(--on-color); border-color: var(--danger); }
4439
4527
  .ds-247420 .vx-vc-glyph { pointer-events: none; }
4440
4528
 
4441
4529
  /* ThreadPanel — cm-thread-panel / cm-tp-* */
@@ -4471,14 +4559,14 @@
4471
4559
  .ds-247420 .cm-tp-item-title { font-size: var(--fs-1, 14px); }
4472
4560
  .ds-247420 .cm-tp-item-snippet { font-size: var(--fs-0, 12px); color: var(--fg-2, var(--fg)); opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4473
4561
  .ds-247420 .cm-tp-item-meta { display: flex; gap: var(--space-2); font-size: var(--fs-micro, 11px); color: var(--fg-2, var(--fg)); opacity: .7; }
4474
- .ds-247420 .cm-tp-empty, .ds-247420 .cm-forum-empty { padding: var(--space-3); text-align: center; color: var(--fg-2, var(--fg)); opacity: .7; }
4562
+ .ds-247420 .cm-tp-empty, .ds-247420 .cm-forum-empty, .ds-247420 .cm-channel-empty, .ds-247420 .cm-member-empty { padding: var(--space-3); text-align: center; color: var(--fg-2, var(--fg)); opacity: .7; font-size: var(--fs-sm); }
4475
4563
 
4476
4564
  /* ForumView — cm-forum / cm-forum-* */
4477
4565
  .ds-247420 .cm-forum { display: flex; flex-direction: column; height: 100%; min-height: 0; background: var(--bg-1, var(--bg-2)); color: var(--fg); }
4478
4566
  .ds-247420 .cm-forum-toolbar { display: flex; gap: var(--space-2); align-items: center; padding: var(--space-2); border-bottom: var(--bw-hair) solid var(--rule); }
4479
4567
  .ds-247420 .cm-forum-search { flex: 1; padding: var(--space-1) var(--space-2); border: var(--bw-hair) solid var(--rule-strong); border-radius: var(--r-1); background: var(--bg-3); color: var(--fg); }
4480
4568
  .ds-247420 .cm-forum-sort { padding: var(--space-1); border: var(--bw-hair) solid var(--rule-strong); border-radius: var(--r-1); background: var(--bg-3); color: var(--fg); }
4481
- .ds-247420 .cm-forum-new { padding: var(--space-1) var(--space-2); border: none; border-radius: var(--r-1); background: var(--accent); color: var(--accent-fg, #fff); cursor: pointer; }
4569
+ .ds-247420 .cm-forum-new { padding: var(--space-1) var(--space-2); border: none; border-radius: var(--r-1); background: var(--accent); color: var(--accent-fg); cursor: pointer; }
4482
4570
  .ds-247420 .cm-forum-list { flex: 1; min-height: 0; overflow-y: auto; }
4483
4571
  .ds-247420 .cm-forum-item { display: flex; flex-direction: column; gap: var(--space-1); width: 100%; text-align: left; cursor: pointer; padding: var(--space-2) var(--space-3); border: none; background: transparent; border-bottom: var(--bw-hair) solid var(--rule); color: var(--fg); }
4484
4572
  .ds-247420 .cm-forum-item:hover { background: var(--bg-3); }
@@ -4522,8 +4610,169 @@
4522
4610
  }
4523
4611
 
4524
4612
  /* chat.css */
4525
- /* chat.css — chat-specific styles. Currently empty; all chat styles live in
4526
- app-shell.css under the .chat-* prefix. Reserved for future split. */
4613
+ /* chat.css — chat-specific styles. Most chat styles live in app-shell.css under
4614
+ the .chat-* prefix. This file carries the AgentChat kit styles (the reusable
4615
+ multi-agent orchestration chat surface). */
4616
+
4617
+ .ds-247420 .agentchat {
4618
+ display: flex;
4619
+ flex-direction: column;
4620
+ min-height: 0;
4621
+ flex: 1;
4622
+ gap: var(--space-2, 8px);
4623
+ }
4624
+
4625
+ /* agent + model picker, new/stop, status — wraps on narrow widths */
4626
+ .ds-247420 .agentchat-controls {
4627
+ display: flex;
4628
+ align-items: center;
4629
+ flex-wrap: wrap;
4630
+ gap: var(--space-2, 8px);
4631
+ }
4632
+ .ds-247420 .agentchat-controls .select,
4633
+ .ds-247420 .agentchat-controls [role="combobox"] { min-width: 130px; max-width: 240px; }
4634
+
4635
+ .ds-247420 .agentchat-status {
4636
+ display: inline-flex;
4637
+ align-items: center;
4638
+ gap: .4em;
4639
+ white-space: nowrap;
4640
+ margin-left: auto;
4641
+ font-size: .85em;
4642
+ color: var(--fg-3);
4643
+ }
4644
+ /* status disc — a CSS-drawn dot, not a glyph; pulses while streaming */
4645
+ .ds-247420 .agentchat-status .status-dot-disc {
4646
+ flex: none; width: 8px; height: 8px; border-radius: 50%;
4647
+ background: var(--fg-3);
4648
+ }
4649
+ .ds-247420 .agentchat-status .status-dot-disc.status-dot-live {
4650
+ background: var(--accent);
4651
+ animation: agentchat-pulse 2s infinite;
4652
+ }
4653
+ @keyframes agentchat-pulse {
4654
+ 0% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 50%, transparent); }
4655
+ 70% { box-shadow: 0 0 0 6px color-mix(in oklab, var(--accent) 0%, transparent); }
4656
+ 100% { box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 0%, transparent); }
4657
+ }
4658
+ @media (prefers-reduced-motion: reduce) {
4659
+ .ds-247420 .agentchat-status .status-dot-disc { animation: none !important; }
4660
+ }
4661
+
4662
+ /* working-directory bar */
4663
+ .ds-247420 .agentchat-cwd {
4664
+ display: flex;
4665
+ align-items: center;
4666
+ gap: var(--space-2, 8px);
4667
+ font-size: .85em;
4668
+ color: var(--fg-3);
4669
+ flex-wrap: wrap;
4670
+ }
4671
+ .ds-247420 .agentchat-cwd-text {
4672
+ overflow: hidden;
4673
+ text-overflow: ellipsis;
4674
+ white-space: nowrap;
4675
+ max-width: 60ch;
4676
+ }
4677
+ .ds-247420 .agentchat-cwd-btn {
4678
+ background: none;
4679
+ border: 1px solid var(--rule);
4680
+ color: inherit;
4681
+ border-radius: 6px;
4682
+ padding: 2px 8px;
4683
+ cursor: pointer;
4684
+ font: inherit;
4685
+ }
4686
+ .ds-247420 .agentchat-cwd-btn:hover { border-color: var(--accent); }
4687
+ .ds-247420 .agentchat-cwd-input {
4688
+ flex: 1;
4689
+ min-width: 12ch;
4690
+ background: var(--bg-2);
4691
+ border: 1px solid var(--rule);
4692
+ color: var(--fg);
4693
+ border-radius: 6px;
4694
+ padding: 4px 8px;
4695
+ font: inherit;
4696
+ }
4697
+
4698
+ /* head + thread */
4699
+ .ds-247420 .agentchat-head {
4700
+ display: flex;
4701
+ align-items: baseline;
4702
+ gap: .5em;
4703
+ }
4704
+ .ds-247420 .agentchat-title { font-size: 1em; margin: 0; }
4705
+ .ds-247420 .agentchat-sub { font-size: .85em; color: var(--fg-3); }
4706
+ .ds-247420 .agentchat-thread {
4707
+ flex: 1;
4708
+ min-height: 0;
4709
+ overflow-y: auto;
4710
+ display: flex;
4711
+ flex-direction: column;
4712
+ gap: var(--space-2, 8px);
4713
+ }
4714
+
4715
+ /* Empty state: a fresh thread is an invitation, not a void. */
4716
+ .ds-247420 .agentchat-empty {
4717
+ margin: auto;
4718
+ display: flex;
4719
+ flex-direction: column;
4720
+ align-items: center;
4721
+ gap: .4em;
4722
+ text-align: center;
4723
+ padding: var(--space-6, 32px) var(--space-4, 16px);
4724
+ color: var(--fg-3);
4725
+ max-width: 46ch;
4726
+ }
4727
+ .ds-247420 .agentchat-empty-title { margin: 0; font-size: 1.05em; color: var(--fg-2, var(--fg)); }
4728
+ .ds-247420 .agentchat-empty-sub { margin: 0; font-size: .9em; }
4729
+ .ds-247420 .agentchat-empty-suggestions {
4730
+ display: flex;
4731
+ flex-wrap: wrap;
4732
+ gap: .5em;
4733
+ justify-content: center;
4734
+ margin-top: .5em;
4735
+ }
4736
+ .ds-247420 .agentchat-empty-suggestion {
4737
+ cursor: pointer;
4738
+ font: inherit;
4739
+ font-size: .85em;
4740
+ padding: .4em .8em;
4741
+ border-radius: 999px;
4742
+ border: 1px solid color-mix(in srgb, var(--fg) 16%, transparent);
4743
+ background: color-mix(in srgb, var(--fg) 5%, transparent);
4744
+ color: var(--fg-2, var(--fg));
4745
+ }
4746
+ .ds-247420 .agentchat-empty-suggestion:hover { background: color-mix(in srgb, var(--accent, var(--fg)) 12%, transparent); }
4747
+ .ds-247420 .agentchat-empty-suggestion:focus-visible { outline: 2px solid var(--accent, var(--fg)); outline-offset: 2px; }
4748
+
4749
+ /* "working" tail: a long silent tool call shouldn't read as frozen. */
4750
+ .ds-247420 .agentchat-working {
4751
+ display: flex;
4752
+ align-items: center;
4753
+ gap: .5em;
4754
+ padding: .3em .2em;
4755
+ color: var(--fg-3);
4756
+ font-size: .85em;
4757
+ }
4758
+ .ds-247420 .agentchat-working-text { color: var(--fg-3); }
4759
+ /* Self-contained dots (chat-thinking-dots lives in a kit sheet not bundled
4760
+ into this DS distribution, so the agentchat tail draws its own). */
4761
+ .ds-247420 .agentchat-working .chat-thinking-dots { display: inline-flex; gap: 3px; }
4762
+ .ds-247420 .agentchat-working .chat-thinking-dots span {
4763
+ width: 5px; height: 5px; border-radius: 50%;
4764
+ background: var(--fg); opacity: .4;
4765
+ animation: agentchat-dot-bounce 1.2s infinite ease-in-out;
4766
+ }
4767
+ .ds-247420 .agentchat-working .chat-thinking-dots span:nth-child(2) { animation-delay: .15s; }
4768
+ .ds-247420 .agentchat-working .chat-thinking-dots span:nth-child(3) { animation-delay: .3s; }
4769
+ @keyframes agentchat-dot-bounce {
4770
+ 0%, 80%, 100% { transform: scale(.6); opacity: .3; }
4771
+ 40% { transform: scale(1); opacity: .9; }
4772
+ }
4773
+ @media (prefers-reduced-motion: reduce) {
4774
+ .ds-247420 .agentchat-working .chat-thinking-dots span { animation: none; opacity: .7; }
4775
+ }
4527
4776
 
4528
4777
  /* editor-primitives.css */
4529
4778
  /* editor-primitives.css — chrome for in-engine editors, inspectors, IDEs,
@@ -4531,6 +4780,71 @@
4531
4780
  resolved from colors_and_type.css: --panel-{0..3}, --panel-text(-2/-3),
4532
4781
  --accent, --accent-fg, --rule, --rule-strong, --r-1/-2, --ff-mono. */
4533
4782
 
4783
+ /* ---------------------------------------------------------------
4784
+ Docked panel — the engine-editor idiom: flush, square, dense,
4785
+ full-height. Unlike the dashboard .panel card (rounded, margined,
4786
+ shadowed) this docks edge-to-edge with a 1px --rule seam. Use for
4787
+ inspector / hierarchy / apps / events columns inside an editor.
4788
+ --------------------------------------------------------------- */
4789
+ .ds-247420 .ds-ep-panel {
4790
+ display: flex; flex-direction: column;
4791
+ min-height: 0; height: 100%;
4792
+ margin: 0; border-radius: 0; box-shadow: none;
4793
+ background: var(--panel-1);
4794
+ color: var(--panel-text);
4795
+ font: var(--fs-tiny, 12px)/var(--lh-base, 1.4) var(--ff-mono, monospace);
4796
+ overflow: hidden;
4797
+ }
4798
+ .ds-247420 .ds-ep-panel-head {
4799
+ flex-shrink: 0;
4800
+ display: flex; align-items: center; justify-content: space-between; gap: 8px;
4801
+ padding: 6px 10px;
4802
+ border-bottom: 1px solid var(--rule);
4803
+ font-size: var(--fs-micro, 11px); font-weight: 600;
4804
+ text-transform: uppercase; letter-spacing: 0.1em;
4805
+ color: var(--panel-text-3);
4806
+ white-space: nowrap;
4807
+ }
4808
+ .ds-247420 .ds-ep-panel-head > :last-child {
4809
+ font-weight: 500; letter-spacing: 0;
4810
+ color: var(--panel-text-2);
4811
+ overflow: hidden; text-overflow: ellipsis;
4812
+ }
4813
+ .ds-247420 .ds-ep-panel-body {
4814
+ flex: 1; min-height: 0; overflow: auto;
4815
+ padding: 6px 8px;
4816
+ }
4817
+ .ds-247420 .ds-ep-panel-body.flush { padding: 0; }
4818
+ /* A sub-section divider inside a docked panel (e.g. app-prop mount). Only
4819
+ shows its top seam when it actually has content — an empty section is
4820
+ collapsed so no stray dashed rule floats over an empty inspector. */
4821
+ .ds-247420 .ds-ep-panel-section {
4822
+ flex-shrink: 0;
4823
+ border-top: 1px solid var(--rule);
4824
+ overflow: auto;
4825
+ }
4826
+ .ds-247420 .ds-ep-panel-section:empty { display: none; border-top: 0; }
4827
+
4828
+ /* Dense status strip for editor chrome — thin, flush, bordered top. */
4829
+ .ds-247420 .ds-ep-statusbar {
4830
+ flex-shrink: 0;
4831
+ display: flex; align-items: center; justify-content: space-between; gap: 8px;
4832
+ min-height: 0; height: 26px;
4833
+ padding: 0 10px;
4834
+ border-top: 1px solid var(--rule);
4835
+ background: var(--panel-1);
4836
+ color: var(--panel-text-2);
4837
+ font: var(--fs-micro, 11px)/1 var(--ff-mono, monospace);
4838
+ }
4839
+ .ds-247420 .ds-ep-statusbar-left, .ds-247420 .ds-ep-statusbar-right { display: flex; align-items: center; gap: 8px; min-width: 0; }
4840
+ .ds-247420 .ds-ep-statusbar-left { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4841
+ /* Buttons inside the dense strip shrink to fit the 26px band. */
4842
+ .ds-247420 .ds-ep-statusbar button {
4843
+ min-height: 0; height: 20px; padding: 0 8px;
4844
+ border-radius: var(--r-1, 4px);
4845
+ font: var(--fs-micro, 11px)/1 var(--ff-mono, monospace);
4846
+ }
4847
+
4534
4848
  /* Toolbar */
4535
4849
  .ds-247420 .ds-ep-toolbar {
4536
4850
  display: flex; align-items: center; gap: 6px;
@@ -4568,7 +4882,24 @@
4568
4882
  color: var(--accent);
4569
4883
  border-bottom-color: var(--accent);
4570
4884
  }
4571
- .ds-247420 .ds-ep-tabs-body { flex: 1; min-height: 0; overflow: auto; }
4885
+ /* Flex column so a full-height docked child (e.g. an inspector panel) fills
4886
+ the tab body instead of collapsing under a block container. */
4887
+ .ds-247420 .ds-ep-tabs-body { flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; }
4888
+
4889
+ /* EventLog — dense console-style log rows (one event per line). */
4890
+ .ds-247420 .ds-ep-eventlog {
4891
+ display: flex; flex-direction: column;
4892
+ font: var(--fs-tiny, 12px)/1.4 var(--ff-mono, monospace);
4893
+ color: var(--panel-text);
4894
+ }
4895
+ .ds-247420 .ds-ep-eventrow {
4896
+ display: flex; align-items: baseline; gap: 8px;
4897
+ padding: 3px 8px;
4898
+ border-bottom: 1px solid color-mix(in oklab, var(--rule) 50%, transparent);
4899
+ }
4900
+ .ds-247420 .ds-ep-eventrow:hover { background: color-mix(in oklab, var(--accent) 6%, transparent); }
4901
+ .ds-247420 .ds-ep-eventrow-type { color: var(--panel-text); font-weight: 600; flex-shrink: 0; }
4902
+ .ds-247420 .ds-ep-eventrow-sub { color: var(--panel-text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
4572
4903
 
4573
4904
  /* TreeView / TreeItem */
4574
4905
  .ds-247420 .ds-ep-tree {
@@ -4656,6 +4987,84 @@
4656
4987
  font-size: 0.8em;
4657
4988
  color: var(--panel-text-3);
4658
4989
  }
4990
+ /* x/y/z packed on one row, each field equal width, no horizontal overflow. */
4991
+ .ds-247420 .ds-ep-vec3 {
4992
+ display: flex; gap: 4px; width: 100%; min-width: 0;
4993
+ }
4994
+ .ds-247420 .ds-ep-vec3 > * { flex: 1 1 0; min-width: 0; }
4995
+ /* Each axis cell (axis letter + scrub input) must show its full 3-decimal value
4996
+ without clipping. The axis letter is a fixed micro-glyph; the input flexes to
4997
+ fill the rest with tight padding and centered text so 0.000 / -0.0 / 1.000 are
4998
+ always legible even in the narrow 3-up layout. */
4999
+ .ds-247420 .ds-ep-vec3 > * {
5000
+ display: flex; align-items: center; gap: 2px;
5001
+ }
5002
+ .ds-247420 .ds-ep-vec3 .ds-ep-propfield-hint {
5003
+ flex: 0 0 auto; width: 9px; text-align: center;
5004
+ grid-column: auto; font-size: 0.8em; opacity: 0.7;
5005
+ }
5006
+ .ds-247420 .ds-ep-vec3 .ds-input-bare {
5007
+ flex: 1 1 auto; min-width: 0; width: auto;
5008
+ padding: 2px 4px; text-align: center; text-overflow: clip;
5009
+ }
5010
+ /* Dense numeric inputs in the inspector — compact, tight radius, mono. */
5011
+ .ds-247420 .ds-ep-propfield-value input,
5012
+ .ds-247420 .ds-ep-propfield-value .ds-input-bare {
5013
+ padding: 2px 6px;
5014
+ border-radius: var(--r-1, 4px);
5015
+ font: var(--fs-tiny, 12px)/1.3 var(--ff-mono, monospace);
5016
+ }
5017
+ .ds-247420 .ds-input-bare {
5018
+ appearance: none;
5019
+ background: var(--panel-2);
5020
+ color: var(--panel-text);
5021
+ border: 1px solid var(--rule);
5022
+ border-radius: var(--r-1, 4px);
5023
+ padding: 2px 6px;
5024
+ font: var(--fs-tiny, 12px)/1.3 var(--ff-mono, monospace);
5025
+ min-width: 0;
5026
+ }
5027
+ .ds-247420 .ds-input-bare:focus { outline: none; border-color: var(--accent); }
5028
+ /* A property field whose control spans the full panel width (label above,
5029
+ control below) — used for wide segmented controls that would clip in the
5030
+ narrow value column. */
5031
+ .ds-247420 .ds-ep-propfield.block {
5032
+ display: flex; flex-direction: column; align-items: stretch; gap: 4px;
5033
+ }
5034
+ .ds-247420 .ds-ep-propfield.block > .ds-ep-propfield-value { width: 100%; }
5035
+ .ds-247420 .ds-ep-propfield.block .ds-ep-btngrp { width: 100%; }
5036
+ .ds-247420 .ds-ep-propfield.block .ds-ep-btngrp-btn { flex: 1 1 0; text-align: center; }
5037
+
5038
+ /* Flush dense action bar docked at a panel bottom (inspector Edit/Delete etc.).
5039
+ Compact buttons, square-ish, bordered top — not big floating pills. */
5040
+ .ds-247420 .ds-ep-actionbar {
5041
+ flex-shrink: 0;
5042
+ display: flex; align-items: center; gap: 6px;
5043
+ padding: 6px 8px;
5044
+ border-top: 1px solid var(--rule);
5045
+ background: var(--panel-1);
5046
+ }
5047
+ .ds-247420 .ds-ep-actionbar > * { flex: 1 1 0; }
5048
+ .ds-247420 .ds-ep-actionbar button {
5049
+ width: 100%;
5050
+ min-height: 28px; height: 28px; padding: 0 10px;
5051
+ border-radius: var(--r-1, 4px);
5052
+ font: var(--fs-tiny, 12px)/1 var(--ff-mono, monospace);
5053
+ }
5054
+
5055
+ /* Inline buttons inside a tree row (e.g. app-list Place) and the editor toolbars
5056
+ are compact — small, square-ish, not big pills. Excludes the segmented
5057
+ IconButtonGroup which manages its own sizing. */
5058
+ .ds-247420 .ds-ep-tree-row button:not(.ds-ep-btngrp-btn),
5059
+ .ds-247420 .ds-ep-toolbar button:not(.ds-ep-btngrp-btn) {
5060
+ min-height: 24px; height: 24px; padding: 0 8px;
5061
+ border-radius: var(--r-1, 4px);
5062
+ font: var(--fs-tiny, 12px)/1 var(--ff-mono, monospace);
5063
+ }
5064
+ @media (pointer: coarse) {
5065
+ .ds-247420 .ds-ep-tree-row button:not(.ds-ep-btngrp-btn),
5066
+ .ds-247420 .ds-ep-toolbar button:not(.ds-ep-btngrp-btn) { min-height: 36px; height: 36px; }
5067
+ }
4659
5068
 
4660
5069
  /* Dock — 3x3 grid for in-engine overlay (canvas pass-through center) */
4661
5070
  .ds-247420 .ds-ep-dock {
@@ -4765,7 +5174,7 @@
4765
5174
  color: var(--panel-text, var(--fg-text));
4766
5175
  border: 1px solid var(--rule);
4767
5176
  border-radius: var(--r-2, 8px);
4768
- box-shadow: 0 8px 28px rgba(0,0,0,0.18);
5177
+ box-shadow: var(--shadow-2);
4769
5178
  padding: 4px;
4770
5179
  display: flex; flex-direction: column;
4771
5180
  outline: none;
@@ -4782,7 +5191,7 @@
4782
5191
  .ds-247420 .ds-ep-ctxmenu-item:focus-visible {
4783
5192
  background: var(--panel-2, var(--rule));
4784
5193
  }
4785
- .ds-247420 .ds-ep-ctxmenu-item.danger { color: var(--danger, #c33); }
5194
+ .ds-247420 .ds-ep-ctxmenu-item.danger { color: var(--danger); }
4786
5195
  .ds-247420 .ds-ep-ctxmenu-item.disabled { opacity: 0.45; cursor: not-allowed; }
4787
5196
  .ds-247420 .ds-ep-ctxmenu-icon { width: 16px; display: inline-flex; justify-content: center; }
4788
5197
  .ds-247420 .ds-ep-ctxmenu-sep { height: 1px; background: var(--rule); margin: 4px 6px; }
@@ -4792,13 +5201,13 @@
4792
5201
  --------------------------------------------------------------- */
4793
5202
  .ds-247420 .ds-ep-drawer-backdrop {
4794
5203
  position: fixed; inset: 0; z-index: 8500;
4795
- background: rgba(0,0,0,0.42);
5204
+ background: var(--scrim);
4796
5205
  }
4797
5206
  .ds-247420 .ds-ep-drawer {
4798
5207
  position: absolute;
4799
5208
  background: var(--panel-1, var(--panel-bg));
4800
5209
  color: var(--panel-text, var(--fg-text));
4801
- box-shadow: 0 12px 40px rgba(0,0,0,0.28);
5210
+ box-shadow: var(--shadow-overlay);
4802
5211
  outline: none;
4803
5212
  transition: transform 180ms ease;
4804
5213
  padding: 12px;
@@ -4819,7 +5228,7 @@
4819
5228
  --------------------------------------------------------------- */
4820
5229
  .ds-247420 .ds-ep-dialog-backdrop {
4821
5230
  position: fixed; inset: 0; z-index: 9500;
4822
- background: rgba(0,0,0,0.5);
5231
+ background: var(--scrim-strong);
4823
5232
  display: flex; align-items: center; justify-content: center;
4824
5233
  padding: 16px;
4825
5234
  }
@@ -4828,7 +5237,7 @@
4828
5237
  color: var(--panel-text, var(--fg-text));
4829
5238
  border: 1px solid var(--rule);
4830
5239
  border-radius: var(--r-2, 10px);
4831
- box-shadow: 0 20px 60px rgba(0,0,0,0.36);
5240
+ box-shadow: var(--shadow-overlay);
4832
5241
  min-width: 280px; max-width: min(560px, 100%);
4833
5242
  max-height: 90vh; overflow: auto;
4834
5243
  display: flex; flex-direction: column;
@@ -4852,7 +5261,7 @@
4852
5261
  background: var(--accent); color: var(--accent-fg); border-color: var(--accent);
4853
5262
  }
4854
5263
  .ds-247420 .ds-ep-dialog-btn.kind-danger {
4855
- background: var(--danger, #c33); color: #fff; border-color: var(--danger, #c33);
5264
+ background: var(--danger); color: var(--on-accent); border-color: var(--danger);
4856
5265
  }
4857
5266
 
4858
5267
  /* ---------------------------------------------------------------
@@ -4874,14 +5283,14 @@
4874
5283
  border-left: 3px solid var(--accent);
4875
5284
  border-radius: var(--r-1, 6px);
4876
5285
  padding: 10px 14px;
4877
- box-shadow: 0 8px 24px rgba(0,0,0,0.22);
5286
+ box-shadow: var(--shadow-3);
4878
5287
  min-width: 220px; max-width: 360px;
4879
5288
  opacity: 1;
4880
5289
  transition: opacity 180ms ease, transform 180ms ease;
4881
5290
  }
4882
- .ds-247420 .ds-ep-toast.kind-success { border-left-color: var(--success, #2a8); }
4883
- .ds-247420 .ds-ep-toast.kind-warn { border-left-color: var(--warn, #d90); }
4884
- .ds-247420 .ds-ep-toast.kind-error { border-left-color: var(--danger, #c33); }
5291
+ .ds-247420 .ds-ep-toast.kind-success { border-left-color: var(--success); }
5292
+ .ds-247420 .ds-ep-toast.kind-warn { border-left-color: var(--warn); }
5293
+ .ds-247420 .ds-ep-toast.kind-error { border-left-color: var(--danger); }
4885
5294
  .ds-247420 .ds-ep-toast.leaving { opacity: 0; transform: translateY(-6px); }
4886
5295
  @media (max-width: 480px) {
4887
5296
  .ds-247420 .ds-ep-toast-host { left: 16px; right: 16px; align-items: center; }
@@ -5041,7 +5450,7 @@
5041
5450
  font-weight: 500;
5042
5451
  }
5043
5452
  .ds-247420 .ds-field-required {
5044
- color: var(--danger, oklch(0.55 0.18 25));
5453
+ color: var(--danger);
5045
5454
  font-weight: 700;
5046
5455
  margin-left: 2px;
5047
5456
  }
@@ -5050,12 +5459,12 @@
5050
5459
  font-size: var(--fs-tiny, 12px);
5051
5460
  }
5052
5461
  .ds-247420 .ds-field-error {
5053
- color: var(--danger, oklch(0.55 0.18 25));
5462
+ color: var(--danger);
5054
5463
  font-size: var(--fs-tiny, 12px);
5055
5464
  font-weight: 500;
5056
5465
  }
5057
5466
  .ds-247420 .ds-field-wrap [aria-invalid="true"] {
5058
- border-color: var(--danger, oklch(0.55 0.18 25)) !important;
5467
+ border-color: var(--danger) !important;
5059
5468
  }
5060
5469
 
5061
5470
  .ds-247420 .sr-only {
@@ -5083,10 +5492,10 @@
5083
5492
  font-size: 12px;
5084
5493
  line-height: 1.4;
5085
5494
  max-width: 280px;
5086
- box-shadow: 0 6px 18px rgba(0,0,0,0.22);
5495
+ box-shadow: var(--shadow-3);
5087
5496
  pointer-events: none;
5088
5497
  }
5089
- .ds-247420 .ds-tooltip.kind-danger { border-color: var(--danger, #c33); color: var(--danger, #c33); }
5498
+ .ds-247420 .ds-tooltip.kind-danger { border-color: var(--danger); color: var(--danger); }
5090
5499
  @media (prefers-reduced-motion: no-preference) {
5091
5500
  .ds-247420 .ds-tooltip { transition: opacity 120ms ease; }
5092
5501
  }
@@ -5102,7 +5511,7 @@
5102
5511
  color: var(--panel-text, var(--fg-text));
5103
5512
  border: 1px solid var(--rule);
5104
5513
  border-radius: var(--r-2, 8px);
5105
- box-shadow: 0 8px 28px rgba(0,0,0,0.22);
5514
+ box-shadow: var(--shadow-3);
5106
5515
  padding: 0;
5107
5516
  outline: none;
5108
5517
  min-width: 160px;
@@ -5139,7 +5548,7 @@
5139
5548
  pointer-events: none;
5140
5549
  cursor: not-allowed;
5141
5550
  }
5142
- .ds-247420 .ds-dropdown-item.is-danger { color: var(--danger, #c33); }
5551
+ .ds-247420 .ds-dropdown-item.is-danger { color: var(--danger); }
5143
5552
  .ds-247420 .ds-dropdown-glyph { width: 16px; display: inline-flex; justify-content: center; flex-shrink: 0; }
5144
5553
  .ds-247420 .ds-dropdown-label { flex: 1; min-width: 0; }
5145
5554
  .ds-247420 .ds-dropdown-separator { height: 1px; background: var(--rule); margin: 4px 6px; }
@@ -5219,7 +5628,7 @@
5219
5628
  background: var(--bg-2); color: var(--fg);
5220
5629
  border: 1px solid var(--rule);
5221
5630
  border-radius: var(--r-2, 14px);
5222
- box-shadow: var(--shadow-3, 0 12px 32px rgba(0,0,0,0.3));
5631
+ box-shadow: var(--shadow-3);
5223
5632
  overflow: hidden;
5224
5633
  }
5225
5634
  .ds-247420 .ov-cmd-input {
@@ -5267,7 +5676,7 @@
5267
5676
  background: var(--bg-2); color: var(--fg);
5268
5677
  border: 1px solid var(--rule);
5269
5678
  border-radius: var(--r-2, 14px);
5270
- box-shadow: var(--shadow-3, 0 12px 32px rgba(0,0,0,0.3));
5679
+ box-shadow: var(--shadow-3);
5271
5680
  outline: none; overflow: hidden;
5272
5681
  }
5273
5682
  .ds-247420 .ov-emoji-tabs {
@@ -5347,7 +5756,7 @@
5347
5756
  background: var(--bg-2); color: var(--fg);
5348
5757
  border: 1px solid var(--rule);
5349
5758
  border-radius: var(--r-2, 14px);
5350
- box-shadow: var(--shadow-3, 0 12px 32px rgba(0,0,0,0.3));
5759
+ box-shadow: var(--shadow-3);
5351
5760
  outline: none; overflow: hidden;
5352
5761
  }
5353
5762
  .ds-247420 .ov-set-head {
@@ -5392,14 +5801,14 @@
5392
5801
  .ds-247420 .ov-auth-backdrop {
5393
5802
  position: fixed; inset: 0; z-index: var(--z-overlay, 1000);
5394
5803
  display: flex; align-items: center; justify-content: center;
5395
- background: rgba(0,0,0,.55);
5804
+ background: var(--scrim-strong);
5396
5805
  }
5397
5806
  .ds-247420 .ov-auth-panel {
5398
5807
  width: min(420px, 92vw);
5399
5808
  display: flex; flex-direction: column;
5400
5809
  background: var(--bg-2); color: var(--fg);
5401
5810
  border: 1px solid var(--rule); border-radius: var(--r-2, 8px);
5402
- box-shadow: var(--shadow-2, 0 12px 40px rgba(0,0,0,.4));
5811
+ box-shadow: var(--shadow-overlay);
5403
5812
  overflow: hidden;
5404
5813
  }
5405
5814
  .ds-247420 .ov-auth-head { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3); border-bottom: 1px solid var(--rule); }
@@ -5412,18 +5821,486 @@
5412
5821
  .ds-247420 .ov-auth-body { display: flex; flex-direction: column; gap: var(--space-2); padding: var(--space-3); }
5413
5822
  .ds-247420 .ov-auth-hint { margin: 0; font-size: var(--fs-0, 12px); color: var(--fg-2, var(--fg)); }
5414
5823
  .ds-247420 .ov-auth-input { padding: var(--space-2); border: 1px solid var(--rule-strong); border-radius: var(--r-1); background: var(--bg-3); color: var(--fg); }
5415
- .ds-247420 .ov-auth-primary { padding: var(--space-2); border: none; border-radius: var(--r-1); background: var(--accent); color: var(--accent-fg, #fff); font-weight: 700; cursor: pointer; }
5824
+ .ds-247420 .ov-auth-primary { padding: var(--space-2); border: none; border-radius: var(--r-1); background: var(--accent); color: var(--on-accent); font-weight: 700; cursor: pointer; }
5416
5825
  .ds-247420 .ov-auth-primary:disabled { opacity: .6; cursor: progress; }
5417
- .ds-247420 .ov-auth-error { margin: 0 var(--space-3) var(--space-3); padding: var(--space-2); border-radius: var(--r-1); background: var(--danger-bg, rgba(208,69,69,.15)); color: var(--danger, #d04545); font-size: var(--fs-0, 12px); }
5826
+ .ds-247420 .ov-auth-error { margin: 0 var(--space-3) var(--space-3); padding: var(--space-2); border-radius: var(--r-1); background: color-mix(in oklab, var(--danger) 15%, transparent); color: var(--danger); font-size: var(--fs-0, 12px); }
5418
5827
 
5419
5828
  /* VideoLightbox — ov-lightbox-* */
5420
5829
  .ds-247420 .ov-lightbox-backdrop {
5421
5830
  position: fixed; inset: 0; z-index: var(--z-overlay-top, 1100);
5422
5831
  display: flex; align-items: center; justify-content: center;
5423
- background: rgba(0,0,0,.85);
5832
+ background: var(--scrim-media);
5424
5833
  }
5425
- .ds-247420 .ov-lightbox-x { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border: none; border-radius: 50%; background: rgba(255,255,255,.12); color: #fff; font-size: 24px; line-height: 1; cursor: pointer; }
5426
- .ds-247420 .ov-lightbox-x:hover { background: rgba(255,255,255,.24); }
5834
+ .ds-247420 .ov-lightbox-x { position: absolute; top: 16px; right: 16px; width: 40px; height: 40px; border: none; border-radius: 50%; background: color-mix(in oklab, var(--on-color) 12%, transparent); color: var(--on-color); font-size: 24px; line-height: 1; cursor: pointer; }
5835
+ .ds-247420 .ov-lightbox-x:hover { background: color-mix(in oklab, var(--on-color) 24%, transparent); }
5427
5836
  .ds-247420 .ov-lightbox-stage { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); max-width: 92vw; max-height: 90vh; }
5428
- .ds-247420 .ov-lightbox-video { max-width: 92vw; max-height: 82vh; border-radius: var(--r-1); background: #000; }
5429
- .ds-247420 .ov-lightbox-label { color: #fff; font-size: var(--fs-0, 12px); opacity: .85; }
5837
+ .ds-247420 .ov-lightbox-video { max-width: 92vw; max-height: 82vh; border-radius: var(--r-1); background: #000; /* true black media letterbox, intentional */ }
5838
+ .ds-247420 .ov-lightbox-label { color: var(--on-color); font-size: var(--fs-0, 12px); opacity: .85; }
5839
+
5840
+ /* ---------------------------------------------------------------
5841
+ Editor-primitive scrollbars — thin, dark, themed so docked panels
5842
+ don't show a fat light OS scrollbar over the dark engine chrome.
5843
+ --------------------------------------------------------------- */
5844
+ .ds-247420 .ds-ep-panel,
5845
+ .ds-247420 .ds-ep-panel-body,
5846
+ .ds-247420 .ds-ep-tree,
5847
+ .ds-247420 .ds-ep-eventlog,
5848
+ .ds-247420 .ds-ep-drawer { scrollbar-width: thin; scrollbar-color: var(--rule) transparent; }
5849
+ .ds-247420 .ds-ep-panel ::-webkit-scrollbar,
5850
+ .ds-247420 .ds-ep-panel-body::-webkit-scrollbar,
5851
+ .ds-247420 .ds-ep-tree::-webkit-scrollbar,
5852
+ .ds-247420 .ds-ep-eventlog::-webkit-scrollbar { width: 8px; height: 8px; }
5853
+ .ds-247420 .ds-ep-panel ::-webkit-scrollbar-track,
5854
+ .ds-247420 .ds-ep-panel-body::-webkit-scrollbar-track,
5855
+ .ds-247420 .ds-ep-tree::-webkit-scrollbar-track,
5856
+ .ds-247420 .ds-ep-eventlog::-webkit-scrollbar-track { background: transparent; }
5857
+ .ds-247420 .ds-ep-panel ::-webkit-scrollbar-thumb,
5858
+ .ds-247420 .ds-ep-panel-body::-webkit-scrollbar-thumb,
5859
+ .ds-247420 .ds-ep-tree::-webkit-scrollbar-thumb,
5860
+ .ds-247420 .ds-ep-eventlog::-webkit-scrollbar-thumb {
5861
+ background: var(--rule); border-radius: var(--r-pill, 999px);
5862
+ border: 2px solid transparent; background-clip: padding-box;
5863
+ }
5864
+ .ds-247420 .ds-ep-panel ::-webkit-scrollbar-thumb:hover,
5865
+ .ds-247420 .ds-ep-panel-body::-webkit-scrollbar-thumb:hover {
5866
+ background: var(--panel-text-3, var(--rule)); background-clip: padding-box;
5867
+ }
5868
+
5869
+ /* ---------------------------------------------------------------
5870
+ Dense app-prop inputs — color swatch + checkbox sized to match the
5871
+ engine-editor density (raw browser controls otherwise read as jank).
5872
+ --------------------------------------------------------------- */
5873
+ /* Specificity bump (.ds-ep-propfield-value prefix) so the sized swatch/check win
5874
+ over the generic `.ds-ep-propfield-value input { width:100% }` rule — otherwise
5875
+ a color/checkbox app-prop stretches to the full field width and reads as jank. */
5876
+ .ds-247420 .ds-ep-propfield-value input.ds-input-color { width: 28px; flex: 0 0 auto; }
5877
+ .ds-247420 .ds-ep-propfield-value input.ds-input-check { width: 16px; flex: 0 0 auto; }
5878
+ .ds-247420 .ds-input-color {
5879
+ appearance: none; -webkit-appearance: none;
5880
+ width: 28px; height: 22px; padding: 0;
5881
+ border: 1px solid var(--rule); border-radius: var(--r-1, 4px);
5882
+ background: var(--panel-2); cursor: pointer; flex-shrink: 0;
5883
+ }
5884
+ .ds-247420 .ds-input-color::-webkit-color-swatch-wrapper { padding: 2px; }
5885
+ .ds-247420 .ds-input-color::-webkit-color-swatch { border: none; border-radius: 2px; }
5886
+ .ds-247420 .ds-input-color:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
5887
+ .ds-247420 .ds-input-check {
5888
+ appearance: none; -webkit-appearance: none;
5889
+ width: 16px; height: 16px; flex-shrink: 0;
5890
+ border: 1px solid var(--rule); border-radius: var(--r-1, 4px);
5891
+ background: var(--panel-2); cursor: pointer; position: relative;
5892
+ }
5893
+ .ds-247420 .ds-input-check:checked { background: var(--accent); border-color: var(--accent); }
5894
+ .ds-247420 .ds-input-check:checked::after {
5895
+ content: ''; position: absolute; left: 4px; top: 1px;
5896
+ width: 4px; height: 8px; border: solid var(--accent-fg, #fff);
5897
+ border-width: 0 2px 2px 0; transform: rotate(45deg);
5898
+ }
5899
+ .ds-247420 .ds-input-check:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
5900
+
5901
+ /* ---------------------------------------------------------------
5902
+ Tree drag-reparent affordance — clear drop target + dragging row.
5903
+ useDropTarget marks the active row with [data-drop-target-active]; the
5904
+ dragged source carries [data-dragging]. Both surfaced as visible state so a
5905
+ reparent drag shows exactly where it will land.
5906
+ --------------------------------------------------------------- */
5907
+ .ds-247420 .ds-ep-tree-item[data-drop-target-active] > .ds-ep-tree-row,
5908
+ .ds-247420 .ds-ep-tree-row[data-drop-target-active],
5909
+ .ds-247420 .ds-ep-tree-row.drag-over {
5910
+ background: color-mix(in oklab, var(--accent) 22%, transparent);
5911
+ box-shadow: inset 0 0 0 1px var(--accent);
5912
+ }
5913
+ .ds-247420 .ds-ep-panel-body[data-drop-target-active] {
5914
+ box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--accent) 50%, transparent);
5915
+ }
5916
+ .ds-247420 .ds-ep-tree-item[data-dragging] > .ds-ep-tree-row,
5917
+ .ds-247420 .ds-ep-tree-item.dragging > .ds-ep-tree-row { opacity: 0.5; }
5918
+
5919
+ /* ---------------------------------------------------------------
5920
+ Floating editor docks — the non-occluding idiom. The game/3D
5921
+ viewport fills the whole editor stage; the hierarchy + inspector
5922
+ ride over it as translucent, backdrop-blurred, collapsible cards
5923
+ so the play area stays visible (and clickable) behind them. The
5924
+ dock layer is pointer-events:none; only the dock cards capture
5925
+ input, so the exposed viewport gutter clicks through to the canvas.
5926
+ --------------------------------------------------------------- */
5927
+ .ds-247420 .ds-ep-stage { position: relative; flex: 1; min-height: 0; overflow: hidden; }
5928
+ .ds-247420 .ds-ep-dock-layer { display: block; }
5929
+ .ds-247420 .ds-ep-dock {
5930
+ position: absolute; top: 8px; bottom: 8px;
5931
+ display: flex; flex-direction: column;
5932
+ width: 280px; max-width: calc(50% - 12px);
5933
+ pointer-events: all;
5934
+ background: color-mix(in oklab, var(--panel-1) 82%, transparent);
5935
+ -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
5936
+ border: 1px solid var(--rule);
5937
+ border-radius: var(--r-2, 8px);
5938
+ box-shadow: 0 6px 24px color-mix(in oklab, #000 28%, transparent);
5939
+ color: var(--panel-text);
5940
+ overflow: hidden;
5941
+ }
5942
+ .ds-247420 .ds-ep-dock-left { left: 8px; }
5943
+ .ds-247420 .ds-ep-dock-right { right: 8px; }
5944
+ /* Collapsed: shrink to just the header strip, freeing the viewport. */
5945
+ .ds-247420 .ds-ep-dock.collapsed { bottom: auto; height: auto; }
5946
+ .ds-247420 .ds-ep-dock-head {
5947
+ display: flex; align-items: center; gap: 6px;
5948
+ flex: 0 0 auto; padding: 4px 6px 4px 10px;
5949
+ border-bottom: 1px solid var(--rule);
5950
+ background: color-mix(in oklab, var(--panel-1) 60%, transparent);
5951
+ }
5952
+ .ds-247420 .ds-ep-dock.collapsed .ds-ep-dock-head { border-bottom: 0; }
5953
+ .ds-247420 .ds-ep-dock-title {
5954
+ flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
5955
+ font: 8px/1 var(--ff-mono, monospace); text-transform: uppercase; letter-spacing: 0.12em;
5956
+ color: var(--panel-text-3);
5957
+ }
5958
+ .ds-247420 .ds-ep-dock-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; background: transparent; }
5959
+ .ds-247420 .ds-ep-dock-body.hidden { display: none; }
5960
+ /* The right dock's body reuses .ds-ep-panel but must stay transparent so the
5961
+ dock's own translucency/blur shows the game view through. */
5962
+ .ds-247420 .ds-ep-dock-body.ds-ep-panel { background: transparent; }
5963
+
5964
+ /* Mobile: docks become full-width bottom-anchored sheets so they don't crowd
5965
+ the narrow viewport side-by-side; the viewport still fills the stage behind. */
5966
+ @media (max-width: 760px) {
5967
+ .ds-247420 .ds-ep-dock { width: auto; max-width: none; left: 6px; right: 6px; top: auto; bottom: 6px; max-height: 46vh; }
5968
+ .ds-247420 .ds-ep-dock-left { bottom: calc(46vh + 12px); max-height: 40vh; }
5969
+ .ds-247420 .ds-ep-dock.collapsed { bottom: auto; }
5970
+ .ds-247420 .ds-ep-dock-left.collapsed { top: 6px; bottom: auto; }
5971
+ }
5972
+
5973
+ /* community-app.css */
5974
+ /* community-app.css — layout glue for mountCommunityApp (the full chat/community
5975
+ app GUI). Reuses the canonical app/body/main classes from app-shell.css and
5976
+ the community + voice component classes from community.css; this part only adds
5977
+ the app-composition wrapper, the server+channel rail pills, the voice view grid,
5978
+ and the category-color tokens the consumer avatars use. All scoped under
5979
+ .ds-247420. Additive — defines only the ca- prefix, group, rail-empty, vx-view
5980
+ classes plus the cat color tokens. */
5981
+
5982
+ .ds-247420.ds-247420 .ca-app {
5983
+ display: flex;
5984
+ flex-direction: column;
5985
+ height: 100vh;
5986
+ min-height: 0;
5987
+ overflow: hidden;
5988
+ }
5989
+ .ds-247420.ds-247420 .ca-app > .app-body {
5990
+ display: flex;
5991
+ flex-direction: row;
5992
+ flex: 1;
5993
+ min-height: 0;
5994
+ overflow: hidden;
5995
+ }
5996
+ .ds-247420.ds-247420 .ca-app > .app-body > .app-main {
5997
+ display: flex;
5998
+ flex-direction: column;
5999
+ flex: 1;
6000
+ min-width: 0;
6001
+ min-height: 0;
6002
+ overflow: hidden;
6003
+ padding: 0;
6004
+ }
6005
+
6006
+ /* server + channel rail */
6007
+ .ds-247420.ds-247420 .ca-rail {
6008
+ display: flex;
6009
+ flex-direction: column;
6010
+ gap: 2px;
6011
+ width: 220px;
6012
+ min-width: 220px;
6013
+ padding: 8px;
6014
+ overflow-y: auto;
6015
+ overflow-x: hidden;
6016
+ background: var(--bg-2, color-mix(in oklab, var(--bg) 92%, var(--fg)));
6017
+ scrollbar-width: thin;
6018
+ }
6019
+ .ds-247420.ds-247420 .ca-rail .group {
6020
+ font-size: 11px;
6021
+ font-weight: 600;
6022
+ letter-spacing: 0.04em;
6023
+ text-transform: uppercase;
6024
+ color: var(--fg-3, color-mix(in oklab, var(--fg) 55%, transparent));
6025
+ padding: 10px 8px 4px;
6026
+ }
6027
+ .ds-247420.ds-247420 .ca-rail a {
6028
+ display: flex;
6029
+ align-items: center;
6030
+ gap: 8px;
6031
+ padding: 6px 8px;
6032
+ border-radius: 6px;
6033
+ color: var(--fg-2, color-mix(in oklab, var(--fg) 78%, transparent));
6034
+ text-decoration: none;
6035
+ font-size: var(--fs-sm, 14px);
6036
+ line-height: 1.2;
6037
+ transition: background 0.1s, color 0.1s;
6038
+ }
6039
+ .ds-247420.ds-247420 .ca-rail a:hover { background: color-mix(in oklab, var(--fg) 8%, transparent); color: var(--fg); }
6040
+ .ds-247420.ds-247420 .ca-rail a.active { background: color-mix(in oklab, var(--accent) 22%, transparent); color: var(--fg); }
6041
+ .ds-247420.ds-247420 .ca-rail a .glyph {
6042
+ display: inline-flex;
6043
+ align-items: center;
6044
+ justify-content: center;
6045
+ width: 18px;
6046
+ flex-shrink: 0;
6047
+ color: var(--fg-3, currentColor);
6048
+ }
6049
+ .ds-247420.ds-247420 .ca-rail a > span:nth-child(2) { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
6050
+ .ds-247420.ds-247420 .ca-rail a .count {
6051
+ flex-shrink: 0;
6052
+ min-width: 18px;
6053
+ padding: 0 5px;
6054
+ border-radius: 9px;
6055
+ background: var(--accent);
6056
+ color: var(--on-accent);
6057
+ font-size: 11px;
6058
+ font-weight: 600;
6059
+ text-align: center;
6060
+ }
6061
+ .ds-247420.ds-247420 .ca-rail .rail-empty {
6062
+ padding: 8px;
6063
+ color: var(--fg-3, color-mix(in oklab, var(--fg) 50%, transparent));
6064
+ font-size: var(--fs-sm, 14px);
6065
+ font-style: italic;
6066
+ }
6067
+
6068
+ /* voice channel view */
6069
+ .ds-247420.ds-247420 .vx-view {
6070
+ display: flex;
6071
+ flex-direction: column;
6072
+ flex: 1;
6073
+ min-height: 0;
6074
+ overflow: hidden;
6075
+ }
6076
+ .ds-247420.ds-247420 .vx-view .vx-grid {
6077
+ display: grid;
6078
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
6079
+ gap: 12px;
6080
+ flex: 1;
6081
+ min-height: 0;
6082
+ padding: 16px;
6083
+ overflow-y: auto;
6084
+ align-content: start;
6085
+ }
6086
+
6087
+ /* spoint/loading-screen.css */
6088
+ /* Loading-screen kit styles. Scoped under .ds-247420 at build time.
6089
+ All colors reference design tokens (no raw literals) per the token-lint gate. */
6090
+ .ds-247420 .sp-loading {
6091
+ position: fixed;
6092
+ inset: 0;
6093
+ z-index: 10000;
6094
+ display: flex;
6095
+ align-items: center;
6096
+ justify-content: center;
6097
+ background: var(--bg);
6098
+ color: var(--fg);
6099
+ font-family: var(--ff-mono);
6100
+ transition: opacity var(--dur-slow) var(--ease);
6101
+ }
6102
+ .ds-247420 .sp-loading-fade { opacity: 0; pointer-events: none; }
6103
+ .ds-247420 .sp-loading-container {
6104
+ width: min(420px, 86vw);
6105
+ display: flex;
6106
+ flex-direction: column;
6107
+ gap: 20px;
6108
+ }
6109
+ .ds-247420 .sp-loading-header h1 {
6110
+ margin: 0;
6111
+ font-family: var(--ff-display);
6112
+ font-size: var(--fs-h2);
6113
+ letter-spacing: 0.04em;
6114
+ }
6115
+ .ds-247420 .sp-loading-label {
6116
+ margin: 4px 0 0;
6117
+ color: var(--fg-2);
6118
+ font-size: var(--fs-body);
6119
+ }
6120
+ .ds-247420 .sp-loading-bars { display: flex; flex-direction: column; gap: 10px; }
6121
+ .ds-247420 .sp-loading-bar-row {
6122
+ display: grid;
6123
+ grid-template-columns: 88px 1fr 44px;
6124
+ align-items: center;
6125
+ gap: 10px;
6126
+ }
6127
+ .ds-247420 .sp-loading-bar-name {
6128
+ color: var(--fg-3);
6129
+ font-size: var(--fs-small, 11px);
6130
+ text-transform: uppercase;
6131
+ letter-spacing: 0.1em;
6132
+ }
6133
+ .ds-247420 .sp-loading-bar-track {
6134
+ height: 6px;
6135
+ border-radius: 3px;
6136
+ background: var(--bg-3);
6137
+ overflow: hidden;
6138
+ }
6139
+ .ds-247420 .sp-loading-bar-fill {
6140
+ height: 100%;
6141
+ width: 0%;
6142
+ background: var(--accent);
6143
+ transition: width var(--dur-base) var(--ease);
6144
+ }
6145
+ .ds-247420 .sp-loading-bar-pct {
6146
+ color: var(--fg-2);
6147
+ font-size: var(--fs-small, 11px);
6148
+ text-align: right;
6149
+ }
6150
+ .ds-247420 .sp-loading-detail {
6151
+ min-height: 16px;
6152
+ color: var(--fg-3);
6153
+ font-size: var(--fs-small, 11px);
6154
+ }
6155
+
6156
+ /* spoint/game-hud.css */
6157
+ /* Game-HUD kit styles. Scoped under .ds-247420 at build time.
6158
+ Colors from semantic tokens (no raw literals) per the token-lint gate. */
6159
+ .ds-247420 .sp-hud { pointer-events: none; font-family: var(--ff-mono); }
6160
+ .ds-247420 .sp-hud-crosshair {
6161
+ position: fixed;
6162
+ top: 50%;
6163
+ left: 50%;
6164
+ transform: translate(-50%, -50%);
6165
+ font-size: 24px;
6166
+ color: var(--fg);
6167
+ text-shadow: 0 0 2px var(--bg);
6168
+ }
6169
+ .ds-247420 .sp-hud-ammo {
6170
+ position: fixed;
6171
+ bottom: 50px;
6172
+ right: 20px;
6173
+ font-size: 24px;
6174
+ font-weight: bold;
6175
+ color: var(--fg);
6176
+ text-shadow: 0 0 4px var(--bg);
6177
+ }
6178
+ .ds-247420 .sp-hud-ammo-reloading { color: var(--warn); }
6179
+ .ds-247420 .sp-hud-health {
6180
+ position: fixed;
6181
+ bottom: 20px;
6182
+ left: 50%;
6183
+ transform: translateX(-50%);
6184
+ width: 200px;
6185
+ height: 20px;
6186
+ background: var(--bg-3);
6187
+ border-radius: 4px;
6188
+ overflow: hidden;
6189
+ }
6190
+ .ds-247420 .sp-hud-health-fill {
6191
+ height: 100%;
6192
+ transition: width var(--dur-snap) var(--ease);
6193
+ }
6194
+ .ds-247420 .sp-hud-hp-high { background: var(--success); }
6195
+ .ds-247420 .sp-hud-hp-mid { background: var(--warn); }
6196
+ .ds-247420 .sp-hud-hp-low { background: var(--danger); }
6197
+ .ds-247420 .sp-hud-health-num {
6198
+ position: absolute;
6199
+ width: 100%;
6200
+ text-align: center;
6201
+ color: var(--fg);
6202
+ font-size: 12px;
6203
+ line-height: 20px;
6204
+ }
6205
+ .ds-247420 .sp-hud-boost {
6206
+ position: fixed;
6207
+ top: 80px;
6208
+ right: 20px;
6209
+ padding: 8px 16px;
6210
+ background: var(--accent);
6211
+ color: var(--accent-fg);
6212
+ font-weight: bold;
6213
+ border-radius: 6px;
6214
+ font-size: 14px;
6215
+ }
6216
+
6217
+ /* spoint/host-join-lobby.css */
6218
+ /* Host/join lobby kit styles. Scoped under .ds-247420 at build time.
6219
+ Token-only colors (no raw literals) per the token-lint gate. */
6220
+ .ds-247420 .sp-lobby {
6221
+ position: fixed;
6222
+ inset: 0;
6223
+ z-index: 9500;
6224
+ display: flex;
6225
+ align-items: center;
6226
+ justify-content: center;
6227
+ background: color-mix(in srgb, var(--bg) 70%, transparent);
6228
+ font-family: var(--ff-mono);
6229
+ }
6230
+ .ds-247420 .sp-lobby-card {
6231
+ position: relative;
6232
+ width: min(360px, 88vw);
6233
+ display: flex;
6234
+ flex-direction: column;
6235
+ gap: 12px;
6236
+ padding: 24px;
6237
+ background: var(--bg-2);
6238
+ border: 1px solid var(--bw-rule, var(--rule));
6239
+ border-radius: var(--r-2, 10px);
6240
+ color: var(--fg);
6241
+ }
6242
+ .ds-247420 .sp-lobby-title {
6243
+ margin: 0;
6244
+ font-family: var(--ff-display);
6245
+ font-size: var(--fs-h3);
6246
+ }
6247
+ .ds-247420 .sp-lobby-sub {
6248
+ margin: 0;
6249
+ color: var(--fg-3);
6250
+ font-size: var(--fs-small, 12px);
6251
+ }
6252
+ .ds-247420 .sp-lobby-btn {
6253
+ appearance: none;
6254
+ border: 1px solid var(--bw-rule, var(--rule));
6255
+ background: var(--bg-3);
6256
+ color: var(--fg);
6257
+ font-family: var(--ff-mono);
6258
+ font-size: var(--fs-body);
6259
+ padding: 10px 14px;
6260
+ border-radius: var(--r-1, 6px);
6261
+ cursor: pointer;
6262
+ }
6263
+ .ds-247420 .sp-lobby-btn:hover { background: var(--bg-2); }
6264
+ .ds-247420 .sp-lobby-btn:disabled { opacity: 0.6; cursor: default; }
6265
+ .ds-247420 .sp-lobby-btn-primary {
6266
+ background: var(--accent);
6267
+ color: var(--accent-fg);
6268
+ border-color: var(--accent);
6269
+ }
6270
+ .ds-247420 .sp-lobby-join { display: flex; gap: 8px; }
6271
+ .ds-247420 .sp-lobby-input {
6272
+ flex: 1;
6273
+ min-width: 0;
6274
+ background: var(--bg);
6275
+ color: var(--fg);
6276
+ border: 1px solid var(--bw-rule, var(--rule));
6277
+ border-radius: var(--r-1, 6px);
6278
+ padding: 8px 10px;
6279
+ font: var(--fs-body) var(--ff-mono);
6280
+ outline: none;
6281
+ }
6282
+ .ds-247420 .sp-lobby-input:focus { border-color: var(--accent); }
6283
+ .ds-247420 .sp-lobby-link { font-size: var(--fs-small, 11px); }
6284
+ .ds-247420 .sp-lobby-code {
6285
+ font-family: var(--ff-display);
6286
+ font-size: var(--fs-h2);
6287
+ letter-spacing: 0.12em;
6288
+ text-align: center;
6289
+ color: var(--accent);
6290
+ padding: 8px;
6291
+ background: var(--bg);
6292
+ border-radius: var(--r-1, 6px);
6293
+ }
6294
+ .ds-247420 .sp-lobby-err { min-height: 16px; color: var(--danger); font-size: var(--fs-small, 11px); }
6295
+ .ds-247420 .sp-lobby-close {
6296
+ position: absolute;
6297
+ top: 10px;
6298
+ right: 12px;
6299
+ appearance: none;
6300
+ background: none;
6301
+ border: none;
6302
+ color: var(--fg-3);
6303
+ font-size: 16px;
6304
+ cursor: pointer;
6305
+ line-height: 1;
6306
+ }