cozyclay 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +31 -0
  3. package/THIRD_PARTY_NOTICES.md +37 -1
  4. package/bin/cozyclay.mjs +51 -2
  5. package/dist/ai-camera-control/index.html +406 -0
  6. package/dist/app/index.html +5 -5
  7. package/dist/assets/app-B3U5aut1.js +4811 -0
  8. package/dist/assets/app-BrRF0wso.css +1 -0
  9. package/dist/assets/vision_bundle-jFkh-fIS.js +41 -0
  10. package/dist/fonts/InstrumentSerif-OFL.txt +93 -0
  11. package/dist/fonts/Inter-OFL.txt +92 -0
  12. package/dist/fonts/README.md +15 -0
  13. package/dist/index.html +60 -16
  14. package/dist/sitemap.xml +7 -1
  15. package/mcp/LIVE-PROTOCOL.md +63 -0
  16. package/mcp/README.md +142 -0
  17. package/mcp/ardy-prompts.mjs +170 -0
  18. package/mcp/live-hub.mjs +105 -0
  19. package/mcp/package.json +24 -0
  20. package/mcp/server.mjs +1394 -0
  21. package/package.json +122 -90
  22. package/src/App.jsx +2957 -514
  23. package/src/ardy/cskel27.js +7 -2
  24. package/src/ardy/ik.js +25 -15
  25. package/src/ardy/npz.js +64 -3
  26. package/src/ardy/playback.js +31 -1
  27. package/src/ardy/prompt-clips.js +7 -2
  28. package/src/ardy/retime.js +211 -0
  29. package/src/ardy/timeline-coordinates.js +13 -0
  30. package/src/ardy/timeline.jsx +124 -5
  31. package/src/ardy/to-cskel27.js +34 -12
  32. package/src/ardy/trim.js +33 -0
  33. package/src/asset-pane.jsx +36 -0
  34. package/src/dualview.jsx +14 -8
  35. package/src/hierarchy-model.js +95 -13
  36. package/src/hierarchy-panel.jsx +139 -6
  37. package/src/live-control.js +122 -0
  38. package/src/matte-editor.js +543 -0
  39. package/src/matte.js +503 -0
  40. package/src/multimodel-ingest.js +344 -0
  41. package/src/object-gizmo.jsx +43 -15
  42. package/src/planview.jsx +43 -32
  43. package/src/pose-extract/detector.js +75 -0
  44. package/src/pose-extract/index.js +3 -0
  45. package/src/pose-extract/take.js +87 -0
  46. package/src/pose-extract/video-frames.js +91 -0
  47. package/src/pose-thumbs.js +152 -0
  48. package/src/posestudio.jsx +361 -11
  49. package/src/project-browser.jsx +135 -0
  50. package/src/project.js +289 -0
  51. package/src/props.jsx +69 -3
  52. package/src/room.jsx +14 -35
  53. package/src/scene-asset-cache.js +125 -0
  54. package/src/scene-assets.js +288 -0
  55. package/src/scene-objects.js +245 -7
  56. package/src/scenes.js +207 -26
  57. package/src/shot-authoring.js +55 -13
  58. package/src/styles.css +1296 -129
  59. package/tools/ardy/BRIDGE.md +3 -2
  60. package/tools/ardy/README.md +9 -5
  61. package/tools/ardy/bridge.mjs +57 -1
  62. package/tools/ardy/bvh-cskel27.mjs +1209 -0
  63. package/tools/ardy/cclay_constrained_generate.py +123 -11
  64. package/tools/ardy/cclay_sequence_generate.py +49 -0
  65. package/tools/ardy/extract.mjs +367 -0
  66. package/tools/ardy/footage.mjs +462 -0
  67. package/tools/ardy/npz.mjs +74 -9
  68. package/tools/ardy/run-on-box.sh +25 -0
  69. package/tools/ardy/run-sequence-on-box.sh +15 -0
  70. package/tools/ardy/runners/remote.mjs +8 -2
  71. package/dist/assets/app-Cgpk2hwX.js +0 -4803
  72. package/dist/assets/app-DgZvaAE1.css +0 -1
package/src/styles.css CHANGED
@@ -129,6 +129,262 @@ select {
129
129
  gap: 6px;
130
130
  }
131
131
 
132
+ /* Project menu (game-engine file workflow) */
133
+ .project-menu-wrap {
134
+ position: relative;
135
+ margin-left: 14px;
136
+ align-self: center;
137
+ }
138
+
139
+ .project-menu-trigger {
140
+ display: inline-flex;
141
+ align-items: center;
142
+ gap: 6px;
143
+ padding: 4px 10px;
144
+ border-radius: 8px;
145
+ border: 1px solid var(--line2);
146
+ background: var(--card2);
147
+ color: var(--fg);
148
+ font-size: 12px;
149
+ font-weight: 600;
150
+ cursor: pointer;
151
+ max-width: 300px;
152
+ white-space: nowrap;
153
+ overflow: hidden;
154
+ text-overflow: ellipsis;
155
+ }
156
+
157
+ .project-menu-trigger:hover {
158
+ border-color: var(--accent);
159
+ }
160
+
161
+ .project-menu-trigger .caret {
162
+ color: var(--muted2);
163
+ font-size: 10px;
164
+ }
165
+
166
+ .project-dirty-dot {
167
+ width: 8px;
168
+ height: 8px;
169
+ border-radius: 50%;
170
+ background: #f5b453;
171
+ flex: none;
172
+ }
173
+
174
+ .project-menu {
175
+ position: absolute;
176
+ top: calc(100% + 6px);
177
+ left: 0;
178
+ z-index: 60;
179
+ display: flex;
180
+ flex-direction: column;
181
+ min-width: 200px;
182
+ padding: 4px;
183
+ background: var(--panel);
184
+ border: 1px solid var(--line2);
185
+ border-radius: 10px;
186
+ box-shadow: 0 8px 30px rgba(0, 0, 0, .5);
187
+ }
188
+
189
+ .project-menu button {
190
+ text-align: left;
191
+ padding: 8px 10px;
192
+ border: none;
193
+ border-radius: 7px;
194
+ background: none;
195
+ color: var(--fg);
196
+ font-size: 12px;
197
+ cursor: pointer;
198
+ }
199
+
200
+ .project-menu button:hover {
201
+ background: var(--hover);
202
+ }
203
+
204
+ /* Project header at the top of the hierarchy column (Project > Scene). */
205
+ .hierarchy-project {
206
+ display: flex;
207
+ align-items: center;
208
+ gap: 7px;
209
+ padding: 9px 12px 8px;
210
+ border-bottom: 1px solid var(--line);
211
+ }
212
+
213
+ .hierarchy-project-label {
214
+ font-size: 10px;
215
+ font-weight: 700;
216
+ letter-spacing: .08em;
217
+ text-transform: uppercase;
218
+ color: var(--muted2);
219
+ }
220
+
221
+ .hierarchy-project strong {
222
+ flex: 1;
223
+ font-size: 12.5px;
224
+ white-space: nowrap;
225
+ overflow: hidden;
226
+ text-overflow: ellipsis;
227
+ }
228
+
229
+ .hierarchy-project button {
230
+ padding: 3px 9px;
231
+ font-size: 11px;
232
+ border-radius: 6px;
233
+ border: 1px solid var(--line2);
234
+ background: var(--card2);
235
+ color: var(--fg);
236
+ cursor: pointer;
237
+ }
238
+
239
+ .hierarchy-project button:hover {
240
+ border-color: var(--accent);
241
+ }
242
+
243
+ /* Project browser modal */
244
+ .project-browser-backdrop {
245
+ position: fixed;
246
+ inset: 0;
247
+ z-index: 200;
248
+ display: flex;
249
+ align-items: center;
250
+ justify-content: center;
251
+ background: rgba(0, 0, 0, .55);
252
+ }
253
+
254
+ .project-browser {
255
+ width: min(560px, 92vw);
256
+ max-height: 80vh;
257
+ display: flex;
258
+ flex-direction: column;
259
+ gap: 14px;
260
+ padding: 16px;
261
+ background: var(--panel);
262
+ border: 1px solid var(--line2);
263
+ border-radius: 14px;
264
+ box-shadow: 0 16px 60px rgba(0, 0, 0, .6);
265
+ overflow-y: auto;
266
+ }
267
+
268
+ .project-browser-head {
269
+ display: flex;
270
+ align-items: center;
271
+ justify-content: space-between;
272
+ font-size: 15px;
273
+ }
274
+
275
+ .project-browser-head .x {
276
+ background: none;
277
+ border: none;
278
+ color: var(--muted);
279
+ font-size: 16px;
280
+ cursor: pointer;
281
+ padding: 2px 6px;
282
+ }
283
+
284
+ .project-browser section {
285
+ display: flex;
286
+ flex-direction: column;
287
+ gap: 6px;
288
+ }
289
+
290
+ .project-browser-section-head {
291
+ display: flex;
292
+ align-items: center;
293
+ justify-content: space-between;
294
+ font-size: 11px;
295
+ font-weight: 700;
296
+ letter-spacing: .06em;
297
+ text-transform: uppercase;
298
+ color: var(--muted);
299
+ }
300
+
301
+ .project-browser-section-head .row-actions {
302
+ display: flex;
303
+ gap: 6px;
304
+ }
305
+
306
+ .project-browser-section-head button {
307
+ font-size: 10px;
308
+ padding: 2px 8px;
309
+ border-radius: 6px;
310
+ border: 1px solid var(--line2);
311
+ background: none;
312
+ color: var(--fg);
313
+ cursor: pointer;
314
+ }
315
+
316
+ .project-browser-empty {
317
+ font-size: 11px;
318
+ color: var(--muted2);
319
+ padding: 8px 10px;
320
+ background: var(--card2);
321
+ border-radius: 8px;
322
+ }
323
+
324
+ .project-browser-list {
325
+ list-style: none;
326
+ margin: 0;
327
+ padding: 0;
328
+ display: flex;
329
+ flex-direction: column;
330
+ gap: 3px;
331
+ }
332
+
333
+ .project-browser-list li {
334
+ display: flex;
335
+ align-items: stretch;
336
+ gap: 4px;
337
+ }
338
+
339
+ .project-browser-list li > button:first-child {
340
+ flex: 1;
341
+ display: flex;
342
+ align-items: center;
343
+ justify-content: space-between;
344
+ gap: 10px;
345
+ padding: 8px 10px;
346
+ border: 1px solid var(--line);
347
+ border-radius: 8px;
348
+ background: var(--card2);
349
+ color: var(--fg);
350
+ font-size: 12px;
351
+ cursor: pointer;
352
+ text-align: left;
353
+ }
354
+
355
+ .project-browser-list li > button:first-child span {
356
+ font-size: 10px;
357
+ color: var(--muted2);
358
+ flex: none;
359
+ }
360
+
361
+ .project-browser-list li.active > button:first-child {
362
+ border-color: var(--accent);
363
+ }
364
+
365
+ .project-browser-list li > button:first-child:hover {
366
+ border-color: var(--accent);
367
+ }
368
+
369
+ .project-browser-list .del {
370
+ border: none;
371
+ background: none;
372
+ color: var(--muted2);
373
+ cursor: pointer;
374
+ padding: 0 6px;
375
+ font-size: 11px;
376
+ }
377
+
378
+ .project-browser-foot {
379
+ display: flex;
380
+ justify-content: space-between;
381
+ gap: 8px;
382
+ }
383
+
384
+ .project-browser-foot .btn {
385
+ flex: 1;
386
+ }
387
+
132
388
  .locale-toggle {
133
389
  display: inline-flex;
134
390
  align-items: center;
@@ -398,7 +654,7 @@ select {
398
654
  pointer-events: auto;
399
655
  }
400
656
  .vp-inset.shot {
401
- aspect-ratio: 16 / 9;
657
+ aspect-ratio: var(--shot-aspect, 16 / 9);
402
658
  }
403
659
  .vp-inset-tag {
404
660
  position: absolute;
@@ -723,56 +979,244 @@ select {
723
979
  .pose-studio.closing {
724
980
  animation: studioOut .2s var(--ease) both;
725
981
  }
726
- .pose-studio:before {
727
- content: "";
728
- position: absolute;
729
- left: 0;
730
- right: 0;
731
- top: 0;
732
- height: 2px;
733
- border-radius: 18px 18px 0 0;
734
- background: linear-gradient(90deg, #2b3cf5, #4d7bff 50%, #79c9ff);
735
- background-size: 200% 100%;
736
- animation: stripeShift 6s linear infinite;
737
- opacity: .9;
738
- }
739
982
 
740
- .studio-head {
741
- display: flex;
742
- align-items: center;
743
- justify-content: space-between;
744
- }
745
- .studio-head span {
746
- font-family: var(--display);
747
- font-weight: 720;
748
- font-size: 18px;
749
- letter-spacing: -.025em;
750
- color: var(--fg);
751
- }
752
- .studio-head .x {
753
- background: none;
754
- border: none;
755
- color: var(--muted);
756
- font-size: 17px;
757
- cursor: pointer;
758
- padding: 3px 8px;
759
- border-radius: 8px;
760
- transition: color var(--fast), background var(--fast);
983
+ /* Compact pass: tighter chrome so more of the panel is pose tiles. Scoped
984
+ to the studio so global buttons elsewhere keep their rhythm. */
985
+ .pose-studio {
986
+ gap: 8px;
987
+ padding: 10px;
761
988
  }
762
- .studio-head .x:hover {
763
- color: var(--fg);
764
- background: var(--card2);
989
+
990
+ .pose-studio .studio-head span {
991
+ font-size: 13px;
992
+ font-weight: 650;
765
993
  }
766
994
 
767
- .studio-hint {
768
- font-size: 11.5px;
769
- color: var(--muted);
770
- margin: -2px 0 0;
771
- line-height: 1.45;
995
+ .pose-studio .studio-actions {
996
+ flex-direction: row;
997
+ gap: 6px;
772
998
  }
773
999
 
774
- .studio-actions {
775
- display: flex;
1000
+ .pose-studio .studio-actions .btn {
1001
+ flex: 1;
1002
+ width: auto;
1003
+ height: 28px;
1004
+ padding: 0 8px;
1005
+ font-size: 11px;
1006
+ font-weight: 600;
1007
+ }
1008
+
1009
+ .pose-studio .studio-hint {
1010
+ font-size: 10px;
1011
+ margin: 0;
1012
+ line-height: 1.35;
1013
+ }
1014
+
1015
+ .pose-studio .studio-filters {
1016
+ flex-wrap: nowrap;
1017
+ overflow-x: auto;
1018
+ gap: 4px;
1019
+ scrollbar-width: none;
1020
+ }
1021
+
1022
+ .pose-studio .studio-filters::-webkit-scrollbar {
1023
+ display: none;
1024
+ }
1025
+
1026
+ .pose-studio .studio-filters .btn {
1027
+ flex: 0 0 auto;
1028
+ width: auto;
1029
+ min-width: 0;
1030
+ height: 24px;
1031
+ padding: 0 10px;
1032
+ font-size: 10px;
1033
+ }
1034
+
1035
+ .pose-studio .pose-grid {
1036
+ gap: 6px;
1037
+ }
1038
+
1039
+ /* Ghost (other characters') clips and pins on the timeline lanes: visible
1040
+ for schedule awareness, never interactive. */
1041
+ .tl-chip.ghost {
1042
+ opacity: 0.42;
1043
+ pointer-events: none;
1044
+ border-style: dashed;
1045
+ }
1046
+
1047
+ .tl-chip-ghost-label {
1048
+ font-size: 9px;
1049
+ padding: 0 4px;
1050
+ white-space: nowrap;
1051
+ overflow: hidden;
1052
+ text-overflow: ellipsis;
1053
+ display: block;
1054
+ }
1055
+
1056
+ .tl-marker.wp.ghost {
1057
+ opacity: 0.42;
1058
+ pointer-events: none;
1059
+ }
1060
+
1061
+ /* ARDY row: duration + seed side by side (Motion tab compacting). */
1062
+ .ardy-row {
1063
+ display: flex;
1064
+ gap: 8px;
1065
+ }
1066
+
1067
+ .ardy-row > * {
1068
+ flex: 1;
1069
+ min-width: 0;
1070
+ }
1071
+
1072
+ /* Per-character motion layer status in the Motion tab. */
1073
+ .gen-layers {
1074
+ list-style: none;
1075
+ margin: 0;
1076
+ padding: 4px 6px;
1077
+ display: flex;
1078
+ flex-direction: column;
1079
+ gap: 2px;
1080
+ background: var(--card2, rgba(255,255,255,.04));
1081
+ border: 1px solid var(--line);
1082
+ border-radius: 8px;
1083
+ }
1084
+
1085
+ .gen-layers li {
1086
+ display: flex;
1087
+ align-items: center;
1088
+ gap: 8px;
1089
+ font-size: 11px;
1090
+ color: var(--muted);
1091
+ padding: 2px 4px;
1092
+ border-radius: 5px;
1093
+ }
1094
+
1095
+ .gen-layers li.active {
1096
+ color: var(--fg);
1097
+ background: var(--hover, rgba(255,255,255,.06));
1098
+ }
1099
+
1100
+ .gen-layers-name {
1101
+ font-weight: 700;
1102
+ color: var(--cyan, #5a9bd4);
1103
+ width: 22px;
1104
+ flex: none;
1105
+ }
1106
+
1107
+ .gen-layers-state {
1108
+ flex: 1;
1109
+ }
1110
+
1111
+ .gen-layers-state.running { color: #f5b453; }
1112
+ .gen-layers-state.queued { color: var(--muted2); }
1113
+ .gen-layers-state.error { color: #e06c6c; }
1114
+ .gen-layers-state.loaded { color: #7bc98b; }
1115
+
1116
+ .gen-layers li button {
1117
+ background: none;
1118
+ border: none;
1119
+ color: var(--muted2);
1120
+ cursor: pointer;
1121
+ font-size: 10px;
1122
+ padding: 0 2px;
1123
+ }
1124
+
1125
+ /* Timeline track owner chip: which character's layer a Prompts/2D Root
1126
+ track belongs to. */
1127
+ .tl-track-owner {
1128
+ font-style: normal;
1129
+ font-size: 9px;
1130
+ font-weight: 700;
1131
+ color: var(--cyan, #5a9bd4);
1132
+ border: 1px solid var(--cyan, #5a9bd4);
1133
+ border-radius: 4px;
1134
+ padding: 0 3px;
1135
+ margin-left: 4px;
1136
+ vertical-align: 1px;
1137
+ }
1138
+
1139
+ /* 2D Root leg speed readout: green-ish in the natural gait band, amber
1140
+ outside it so a bad path is caught before generation. */
1141
+ .tl-path-speed {
1142
+ font-style: normal;
1143
+ font-size: 9px;
1144
+ font-weight: 600;
1145
+ color: #7bc98b;
1146
+ margin-left: 6px;
1147
+ vertical-align: 1px;
1148
+ }
1149
+
1150
+ .tl-path-speed.warn {
1151
+ color: #f5b453;
1152
+ }
1153
+
1154
+ /* Docked variant: the panel lives in-flow at the bottom of the inspector
1155
+ sidebar instead of floating over the shot pane. */
1156
+ .pose-studio.docked {
1157
+ position: relative;
1158
+ top: auto;
1159
+ right: auto;
1160
+ bottom: auto;
1161
+ left: auto;
1162
+ width: auto;
1163
+ flex: none;
1164
+ height: min(52vh, 560px);
1165
+ z-index: 1;
1166
+ margin: 8px 10px 10px;
1167
+ border-radius: 10px;
1168
+ box-shadow: none;
1169
+ }
1170
+ .pose-studio:before {
1171
+ content: "";
1172
+ position: absolute;
1173
+ left: 0;
1174
+ right: 0;
1175
+ top: 0;
1176
+ height: 2px;
1177
+ border-radius: 18px 18px 0 0;
1178
+ background: linear-gradient(90deg, #2b3cf5, #4d7bff 50%, #79c9ff);
1179
+ background-size: 200% 100%;
1180
+ animation: stripeShift 6s linear infinite;
1181
+ opacity: .9;
1182
+ }
1183
+
1184
+ .studio-head {
1185
+ display: flex;
1186
+ align-items: center;
1187
+ justify-content: space-between;
1188
+ }
1189
+ .studio-head span {
1190
+ font-family: var(--display);
1191
+ font-weight: 720;
1192
+ font-size: 18px;
1193
+ letter-spacing: -.025em;
1194
+ color: var(--fg);
1195
+ }
1196
+ .studio-head .x {
1197
+ background: none;
1198
+ border: none;
1199
+ color: var(--muted);
1200
+ font-size: 17px;
1201
+ cursor: pointer;
1202
+ padding: 3px 8px;
1203
+ border-radius: 8px;
1204
+ transition: color var(--fast), background var(--fast);
1205
+ }
1206
+ .studio-head .x:hover {
1207
+ color: var(--fg);
1208
+ background: var(--card2);
1209
+ }
1210
+
1211
+ .studio-hint {
1212
+ font-size: 11.5px;
1213
+ color: var(--muted);
1214
+ margin: -2px 0 0;
1215
+ line-height: 1.45;
1216
+ }
1217
+
1218
+ .studio-actions {
1219
+ display: flex;
776
1220
  flex-direction: column;
777
1221
  gap: 8px;
778
1222
  }
@@ -797,8 +1241,8 @@ select {
797
1241
  min-height: 0;
798
1242
  overflow-y: auto;
799
1243
  display: grid;
800
- grid-template-columns: 1fr 1fr;
801
- gap: 10px;
1244
+ grid-template-columns: 1fr 1fr 1fr;
1245
+ gap: 8px;
802
1246
  align-content: start;
803
1247
  grid-auto-rows: min-content;
804
1248
  padding-right: 3px;
@@ -841,7 +1285,7 @@ select {
841
1285
  right: 0;
842
1286
  bottom: 0;
843
1287
  background: linear-gradient(transparent, #06060aeb);
844
- font-size: 11px;
1288
+ font-size: 10px;
845
1289
  font-weight: 700;
846
1290
  color: #fff;
847
1291
  text-align: center;
@@ -1051,7 +1495,11 @@ select {
1051
1495
  }
1052
1496
 
1053
1497
  .scene-list-item.active > button { background: rgba(87, 111, 221, .16); color: var(--fg); }
1054
- .scene-document-icon { width: 8px; height: 10px; border: 1px solid #7284bd; border-radius: 1px; }
1498
+ .scene-document-icon {
1499
+ width: 15px;
1500
+ height: 15px;
1501
+ color: #8fa8ff;
1502
+ }
1055
1503
  .scene-rename-input {
1056
1504
  width: 100%;
1057
1505
  height: 23px;
@@ -1114,8 +1562,10 @@ select {
1114
1562
  flex: 0 0 20px;
1115
1563
  display: grid;
1116
1564
  place-items: center;
1117
- color: #7d8596;
1118
- font-size: 11px;
1565
+ color: #929bad;
1566
+ font-size: 14px;
1567
+ font-weight: 700;
1568
+ line-height: 1;
1119
1569
  cursor: pointer;
1120
1570
  }
1121
1571
 
@@ -1134,26 +1584,22 @@ select {
1134
1584
 
1135
1585
  .hierarchy-icon {
1136
1586
  flex: none;
1137
- width: 9px;
1138
- height: 9px;
1139
- border: 1px solid #65708b;
1140
- border-radius: 2px;
1141
- background: rgba(111, 127, 165, .12);
1587
+ width: 15px;
1588
+ height: 15px;
1589
+ color: #82909d;
1590
+ overflow: visible;
1142
1591
  }
1143
1592
 
1144
- .hierarchy-icon.shot { border-radius: 50%; border-color: #8a9cff; box-shadow: inset 0 0 0 2px #222a52; }
1145
- .hierarchy-icon.camera { border-color: #72a9ff; transform: skewX(-8deg); }
1146
- .hierarchy-icon.character { border-radius: 50% 50% 3px 3px; border-color: #8ed4c0; }
1147
- .hierarchy-icon.motion,
1148
- .hierarchy-icon.clip,
1149
- .hierarchy-icon.prompt { border-color: #7687ff; background: rgba(69, 88, 226, .3); }
1150
- .hierarchy-icon.key { border-color: #ffb45f; transform: rotate(45deg) scale(.72); }
1593
+ .hierarchy-icon.scene { color: #8fa8ff; }
1594
+ .hierarchy-icon.camera { color: #e1a84b; }
1595
+ .hierarchy-icon.group,
1596
+ .hierarchy-icon.character { color: #82c9ad; }
1151
1597
  .hierarchy-icon.rig,
1152
- .hierarchy-icon.bone { border-radius: 50%; border-color: #d39cff; }
1153
- .hierarchy-icon.path { width: 11px; height: 5px; border-color: #60c7d0; border-radius: 999px; }
1154
- .hierarchy-icon.environment { border-radius: 50%; border-color: #77a878; }
1155
- .hierarchy-icon.props { border-color: #b8936b; }
1156
- .hierarchy-icon.object { border-color: #d0a36f; background: rgba(188, 126, 63, .22); transform: rotate(45deg) scale(.78); }
1598
+ .hierarchy-icon.bone { color: #bd94d4; }
1599
+ .hierarchy-icon.environment { color: #75b692; }
1600
+ .hierarchy-icon.props,
1601
+ .hierarchy-icon.object { color: #d18b70; }
1602
+ .selected .hierarchy-icon { filter: brightness(1.2); }
1157
1603
 
1158
1604
  .hierarchy-label {
1159
1605
  min-width: 0;
@@ -1827,6 +2273,16 @@ input[type=range]::-moz-range-thumb {
1827
2273
  flex: none;
1828
2274
  }
1829
2275
 
2276
+ .sb-color {
2277
+ width: 26px;
2278
+ height: 25px;
2279
+ padding: 1px;
2280
+ border: 1px solid var(--line2);
2281
+ border-radius: 8px;
2282
+ background: #ffffff05;
2283
+ cursor: pointer;
2284
+ }
2285
+
1830
2286
  .cam-toggle {
1831
2287
  width: 30px;
1832
2288
  height: 25px;
@@ -2633,6 +3089,61 @@ input[type=range]::-moz-range-thumb {
2633
3089
  }
2634
3090
 
2635
3091
 
3092
+ .tl-motion-clip {
3093
+ box-sizing: border-box;
3094
+ position: absolute;
3095
+ top: 50%;
3096
+ height: min(20px, calc(100% - 6px));
3097
+ transform: translateY(-50%);
3098
+ left: calc(var(--tl-f-start) * 100%);
3099
+ width: calc((var(--tl-f-end) - var(--tl-f-start)) * 100%);
3100
+ display: flex;
3101
+ align-items: center;
3102
+ padding: 0 8px;
3103
+ background: linear-gradient(103deg, rgba(126, 208, 143, .28), rgba(126, 208, 143, .14));
3104
+ border: 1px solid rgba(126, 208, 143, .45);
3105
+ border-radius: 5px;
3106
+ color: #9fe0a7;
3107
+ font-size: 9px;
3108
+ font-weight: 600;
3109
+ letter-spacing: .02em;
3110
+ white-space: nowrap;
3111
+ overflow: hidden;
3112
+ pointer-events: none; /* passive: IK markers on this lane stay clickable */
3113
+ }
3114
+
3115
+ .tl-motion-clip.trimming {
3116
+ background: linear-gradient(103deg, rgba(126, 208, 143, .45), rgba(126, 208, 143, .25));
3117
+ border-color: rgba(126, 208, 143, .8);
3118
+ }
3119
+
3120
+ .tl-motion-clip-label {
3121
+ flex: 1;
3122
+ overflow: hidden;
3123
+ text-overflow: ellipsis;
3124
+ text-align: center;
3125
+ }
3126
+
3127
+ /* the strip body stays click-through (IK markers live on this lane); only
3128
+ the trim handles take the pointer */
3129
+ .tl-motion-clip-handle {
3130
+ pointer-events: auto;
3131
+ flex: none;
3132
+ width: 8px;
3133
+ align-self: stretch;
3134
+ margin: 0;
3135
+ padding: 0;
3136
+ border: none;
3137
+ background: rgba(126, 208, 143, .55);
3138
+ border-radius: 3px;
3139
+ cursor: ew-resize;
3140
+ touch-action: none;
3141
+ }
3142
+
3143
+ .tl-motion-clip-handle:hover {
3144
+ background: rgba(126, 208, 143, .95);
3145
+ }
3146
+
2636
3147
  .tl-chip {
2637
3148
  box-sizing: border-box;
2638
3149
  position: absolute;
@@ -3735,30 +4246,19 @@ input[type=range]::-moz-range-thumb {
3735
4246
  }
3736
4247
 
3737
4248
  .hierarchy-icon {
3738
- border-color: #71818d;
3739
- background: rgba(255, 255, 255, .04);
3740
- }
3741
-
3742
- .hierarchy-icon.shot {
3743
- border-color: #3a7cbf;
3744
- box-shadow: inset 0 0 0 2px #3c3c3c;
4249
+ color: #82909d;
3745
4250
  }
3746
4251
 
3747
- .hierarchy-icon.camera { border-color: #d4972d; }
3748
- .hierarchy-icon.character { border-color: #6f9f86; }
3749
- .hierarchy-icon.motion,
3750
- .hierarchy-icon.clip,
3751
- .hierarchy-icon.prompt {
3752
- border-color: #3a7cbf;
3753
- background: rgba(58, 124, 191, .13);
3754
- }
3755
- .hierarchy-icon.key { border-color: #d65f55; }
4252
+ .hierarchy-icon.scene { color: #78a8dc; }
4253
+ .hierarchy-icon.camera { color: #d9a34a; }
4254
+ .hierarchy-icon.group,
4255
+ .hierarchy-icon.character { color: #73aa8d; }
3756
4256
  .hierarchy-icon.rig,
3757
- .hierarchy-icon.bone { border-color: #8a759d; }
3758
- .hierarchy-icon.path { border-color: #6f9f86; }
3759
- .hierarchy-icon.environment { border-color: #6f9f86; }
4257
+ .hierarchy-icon.bone { color: #a98cc0; }
4258
+ .hierarchy-icon.environment { color: #73aa8d; }
3760
4259
  .hierarchy-icon.props,
3761
- .hierarchy-icon.object { border-color: #c7836f; }
4260
+ .hierarchy-icon.object { color: #cb826b; }
4261
+ .selected .hierarchy-icon { filter: brightness(1.25); }
3762
4262
 
3763
4263
  .inspector-scroll {
3764
4264
  background: #282828;
@@ -5090,6 +5590,90 @@ input[type=range]::-moz-range-thumb {
5090
5590
  font-size: 11px;
5091
5591
  }
5092
5592
 
5593
+ .assets-pane {
5594
+ height: var(--timeline-height);
5595
+ min-height: 110px;
5596
+ max-height: 58vh;
5597
+ overflow-y: auto;
5598
+ padding: 10px 12px;
5599
+ background: var(--panel);
5600
+ }
5601
+
5602
+ .assets-grid {
5603
+ display: flex;
5604
+ flex-wrap: wrap;
5605
+ gap: 10px;
5606
+ }
5607
+
5608
+ .asset-card {
5609
+ display: flex;
5610
+ flex-direction: column;
5611
+ align-items: center;
5612
+ gap: 6px;
5613
+ width: 108px;
5614
+ padding: 12px 8px 10px;
5615
+ background: var(--panel2, #1d1d1f);
5616
+ border: 1px solid var(--line);
5617
+ border-radius: 8px;
5618
+ color: var(--fg);
5619
+ cursor: grab;
5620
+ user-select: none;
5621
+ touch-action: none;
5622
+ }
5623
+
5624
+ .asset-card:hover {
5625
+ border-color: var(--accent, #d8a24a);
5626
+ }
5627
+
5628
+ .asset-card:active {
5629
+ cursor: grabbing;
5630
+ }
5631
+
5632
+ .asset-card-swatch {
5633
+ width: 44px;
5634
+ height: 44px;
5635
+ border-radius: 10px;
5636
+ background: #f2eee6;
5637
+ }
5638
+
5639
+ .asset-card-swatch[data-model="x-bot-tpose"] {
5640
+ background: #faf8f2;
5641
+ border: 1px solid #d8d2c4;
5642
+ }
5643
+
5644
+ .asset-card-label {
5645
+ font-size: 12px;
5646
+ font-weight: 600;
5647
+ }
5648
+
5649
+ .asset-card-kind {
5650
+ font-size: 10px;
5651
+ color: var(--muted2);
5652
+ }
5653
+
5654
+ .asset-drag-ghost {
5655
+ position: fixed;
5656
+ z-index: 1000;
5657
+ display: flex;
5658
+ align-items: center;
5659
+ gap: 8px;
5660
+ padding: 8px 12px;
5661
+ border-radius: 8px;
5662
+ background: var(--panel2, #1d1d1f);
5663
+ border: 1px solid var(--accent, #d8a24a);
5664
+ color: var(--fg);
5665
+ font-size: 12px;
5666
+ pointer-events: none;
5667
+ transform: translate(-50%, -120%);
5668
+ opacity: 0.92;
5669
+ }
5670
+
5671
+ .asset-drag-ghost .asset-card-swatch {
5672
+ width: 22px;
5673
+ height: 22px;
5674
+ border-radius: 6px;
5675
+ }
5676
+
5093
5677
  .console-empty {
5094
5678
  margin: 8px 4px;
5095
5679
  color: var(--muted2);
@@ -5232,11 +5816,24 @@ input[type=range]::-moz-range-thumb {
5232
5816
  }
5233
5817
 
5234
5818
  /* Unity pane tabs (Scene / PlayView) — the pane's title strip */
5235
- .pane-tabs {
5819
+ .viewport-titlebar {
5236
5820
  position: absolute;
5237
5821
  top: 0;
5238
5822
  left: 0;
5823
+ right: 0;
5239
5824
  z-index: 8;
5825
+ height: 27px;
5826
+ display: flex;
5827
+ align-items: stretch;
5828
+ min-width: 0;
5829
+ overflow: hidden;
5830
+ background: var(--panel);
5831
+ border-bottom: 1px solid var(--line);
5832
+ }
5833
+
5834
+ .pane-tabs {
5835
+ position: static;
5836
+ flex: none;
5240
5837
  display: flex;
5241
5838
  }
5242
5839
 
@@ -5245,7 +5842,7 @@ input[type=range]::-moz-range-thumb {
5245
5842
  padding: 0 14px;
5246
5843
  border: 0;
5247
5844
  border-right: 1px solid var(--line);
5248
- border-bottom: 1px solid var(--line);
5845
+ border-bottom: 2px solid transparent;
5249
5846
  background: var(--panel);
5250
5847
  color: var(--muted);
5251
5848
  font: inherit;
@@ -5261,7 +5858,7 @@ input[type=range]::-moz-range-thumb {
5261
5858
  .pane-tabs button.active {
5262
5859
  background: #232323;
5263
5860
  color: var(--fg);
5264
- border-bottom-color: #232323;
5861
+ border-bottom-color: #3a7cbf;
5265
5862
  }
5266
5863
 
5267
5864
  /* the Shot/Top-View toggle sits right of the pane tabs in Scene view */
@@ -5602,45 +6199,303 @@ input[type=range]::-moz-range-thumb {
5602
6199
  margin: 0;
5603
6200
  }
5604
6201
 
5605
- .foldout-head:hover {
5606
- background: rgba(255, 255, 255, .04);
6202
+ .foldout-head:hover {
6203
+ background: rgba(255, 255, 255, .04);
6204
+ }
6205
+
6206
+ .foldout-arrow {
6207
+ font-size: 8px;
6208
+ width: 12px;
6209
+ }
6210
+
6211
+ .foldout-body {
6212
+ padding: 4px 12px 0;
6213
+ }
6214
+
6215
+ /* property rows: label left, value right, 22px tall */
6216
+ .row {
6217
+ display: flex;
6218
+ align-items: center;
6219
+ gap: 8px;
6220
+ min-height: 22px;
6221
+ margin: 3px 0;
6222
+ font-size: 11px;
6223
+ }
6224
+
6225
+ .row > span:first-child {
6226
+ width: 84px;
6227
+ flex: none;
6228
+ color: var(--muted);
6229
+ font-size: 11px;
6230
+ }
6231
+
6232
+ .row .val {
6233
+ width: auto;
6234
+ min-width: 34px;
6235
+ font-size: 11px;
6236
+ }
6237
+
6238
+ /* sliders hug their row */
6239
+ input[type=range] {
6240
+ height: 3px;
6241
+ }
6242
+
6243
+ .multimodel-card {
6244
+ padding: 8px;
6245
+ border: 1px solid rgba(58, 124, 191, .38);
6246
+ background: linear-gradient(180deg, rgba(58, 124, 191, .12), rgba(255, 255, 255, .025));
6247
+ border-radius: 3px;
6248
+ }
6249
+
6250
+ .multimodel-card-head {
6251
+ display: flex;
6252
+ align-items: flex-start;
6253
+ justify-content: space-between;
6254
+ gap: 8px;
6255
+ }
6256
+
6257
+ .multimodel-card-head strong,
6258
+ .multimodel-card-head span {
6259
+ display: block;
6260
+ }
6261
+
6262
+ .multimodel-card-head strong {
6263
+ font-size: 11px;
6264
+ color: #dce7ff;
6265
+ }
6266
+
6267
+ .multimodel-card-head div > span {
6268
+ margin-top: 2px;
6269
+ color: var(--muted);
6270
+ font-size: 9px;
6271
+ }
6272
+
6273
+ .multimodel-status {
6274
+ padding: 2px 5px;
6275
+ border: 1px solid var(--line);
6276
+ color: var(--muted);
6277
+ font-family: var(--mono);
6278
+ font-size: 8px;
6279
+ letter-spacing: .08em;
6280
+ }
6281
+
6282
+ .multimodel-status.ready {
6283
+ border-color: rgba(126, 208, 143, .55);
6284
+ color: #9fe0a7;
6285
+ }
6286
+
6287
+ .multimodel-status.error {
6288
+ border-color: rgba(229, 72, 77, .65);
6289
+ color: #ff9b9f;
6290
+ }
6291
+
6292
+ .multimodel-source-row,
6293
+ .multimodel-url-row {
6294
+ display: flex;
6295
+ align-items: center;
6296
+ gap: 6px;
6297
+ margin-top: 8px;
6298
+ }
6299
+
6300
+ .multimodel-input-block {
6301
+ margin-top: 9px;
6302
+ padding: 8px;
6303
+ border: 1px solid rgba(255, 255, 255, .1);
6304
+ background: rgba(0, 0, 0, .12);
6305
+ }
6306
+
6307
+ .multimodel-input-block + .multimodel-input-block {
6308
+ margin-top: 6px;
6309
+ }
6310
+
6311
+ .multimodel-input-label {
6312
+ display: flex;
6313
+ align-items: baseline;
6314
+ justify-content: space-between;
6315
+ gap: 8px;
6316
+ }
6317
+
6318
+ .multimodel-input-label strong {
6319
+ color: #c9d8f7;
6320
+ font-size: 10px;
6321
+ font-weight: 600;
6322
+ }
6323
+
6324
+ .multimodel-input-label span {
6325
+ color: var(--muted2);
6326
+ font-size: 8px;
6327
+ white-space: nowrap;
6328
+ }
6329
+
6330
+ .multimodel-file-input {
6331
+ display: none;
6332
+ }
6333
+
6334
+ .multimodel-file-name {
6335
+ min-width: 0;
6336
+ overflow: hidden;
6337
+ color: var(--muted2);
6338
+ font-size: 9px;
6339
+ text-overflow: ellipsis;
6340
+ white-space: nowrap;
6341
+ }
6342
+
6343
+ .multimodel-url-input {
6344
+ display: block;
6345
+ box-sizing: border-box;
6346
+ width: 100%;
6347
+ margin-top: 7px;
6348
+ height: 26px;
6349
+ padding: 2px 8px;
6350
+ border: 1px solid var(--line);
6351
+ background: var(--card2);
6352
+ color: var(--fg);
6353
+ font-family: var(--mono);
6354
+ font-size: 10px;
6355
+ }
6356
+
6357
+ .multimodel-url-input::placeholder {
6358
+ color: var(--muted2);
6359
+ }
6360
+
6361
+ .multimodel-url-input:focus {
6362
+ outline: none;
6363
+ border-color: var(--accent);
6364
+ box-shadow: 0 0 0 1px var(--accent);
6365
+ }
6366
+
6367
+ .multimodel-url-actions {
6368
+ display: flex;
6369
+ align-items: center;
6370
+ gap: 6px;
6371
+ margin-top: 6px;
6372
+ }
6373
+
6374
+ .multimodel-url-actions .btn {
6375
+ flex: 1;
6376
+ }
6377
+
6378
+ .multimodel-status.busy {
6379
+ border-color: rgba(126, 160, 224, .55);
6380
+ color: #a8c4f2;
6381
+ }
6382
+
6383
+ .multimodel-progress {
6384
+ display: flex;
6385
+ align-items: center;
6386
+ gap: 7px;
6387
+ margin-top: 9px;
6388
+ }
6389
+
6390
+ .multimodel-progress-track {
6391
+ flex: 1;
6392
+ height: 4px;
6393
+ background: rgba(0, 0, 0, .35);
6394
+ overflow: hidden;
6395
+ }
6396
+
6397
+ .multimodel-progress-bar {
6398
+ height: 100%;
6399
+ width: 0;
6400
+ background: var(--accent);
6401
+ transition: width .12s linear;
6402
+ }
6403
+
6404
+ .multimodel-progress-bar.indeterminate {
6405
+ width: 35%;
6406
+ animation: multimodel-slide 1.1s ease-in-out infinite;
6407
+ }
6408
+
6409
+ @keyframes multimodel-slide {
6410
+ 0% { transform: translateX(-100%); }
6411
+ 100% { transform: translateX(300%); }
6412
+ }
6413
+
6414
+ .multimodel-progress span {
6415
+ flex: none;
6416
+ min-width: 62px;
6417
+ text-align: right;
6418
+ color: var(--muted2);
6419
+ font-family: var(--mono);
6420
+ font-size: 9px;
6421
+ }
6422
+
6423
+ .multimodel-error {
6424
+ margin: 9px 0 0;
6425
+ padding: 6px 8px;
6426
+ border: 1px solid rgba(229, 72, 77, .45);
6427
+ background: rgba(229, 72, 77, .1);
6428
+ color: #ff9b9f;
6429
+ font-size: 9.5px;
6430
+ line-height: 1.45;
6431
+ }
6432
+
6433
+ .multimodel-receipt {
6434
+ display: flex;
6435
+ gap: 8px;
6436
+ margin-top: 9px;
6437
+ padding: 7px;
6438
+ border: 1px solid rgba(126, 208, 143, .3);
6439
+ background: rgba(126, 208, 143, .07);
6440
+ }
6441
+
6442
+ .multimodel-preview {
6443
+ flex: none;
6444
+ width: 76px;
6445
+ height: 44px;
6446
+ object-fit: cover;
6447
+ background: #000;
6448
+ border: 1px solid rgba(255, 255, 255, .12);
6449
+ }
6450
+
6451
+ .multimodel-receipt-body {
6452
+ min-width: 0;
6453
+ display: flex;
6454
+ flex-direction: column;
6455
+ gap: 2px;
6456
+ }
6457
+
6458
+ .multimodel-receipt-body strong {
6459
+ overflow: hidden;
6460
+ color: #dbe8ff;
6461
+ font-size: 10px;
6462
+ text-overflow: ellipsis;
6463
+ white-space: nowrap;
5607
6464
  }
5608
6465
 
5609
- .foldout-arrow {
5610
- font-size: 8px;
5611
- width: 12px;
6466
+ .multimodel-receipt-body span {
6467
+ color: var(--muted2);
6468
+ font-family: var(--mono);
6469
+ font-size: 9px;
5612
6470
  }
5613
6471
 
5614
- .foldout-body {
5615
- padding: 4px 12px 0;
6472
+ .multimodel-receipt-timeline {
6473
+ color: #9fe0a7 !important;
5616
6474
  }
5617
6475
 
5618
- /* property rows: label left, value right, 22px tall */
5619
- .row {
5620
- display: flex;
5621
- align-items: center;
5622
- gap: 8px;
5623
- min-height: 22px;
5624
- margin: 3px 0;
5625
- font-size: 11px;
6476
+ .multimodel-extract {
6477
+ margin-top: 9px;
5626
6478
  }
5627
6479
 
5628
- .row > span:first-child {
5629
- width: 84px;
5630
- flex: none;
5631
- color: var(--muted);
5632
- font-size: 11px;
6480
+ .multimodel-extract .btn {
6481
+ width: 100%;
5633
6482
  }
5634
6483
 
5635
- .row .val {
5636
- width: auto;
5637
- min-width: 34px;
5638
- font-size: 11px;
6484
+ .multimodel-extract-receipt {
6485
+ margin: 8px 0 0;
6486
+ padding: 6px 8px;
6487
+ border: 1px solid rgba(126, 208, 143, .3);
6488
+ background: rgba(126, 208, 143, .07);
6489
+ color: #9fe0a7;
6490
+ font-size: 9.5px;
6491
+ line-height: 1.45;
5639
6492
  }
5640
6493
 
5641
- /* sliders hug their row */
5642
- input[type=range] {
5643
- height: 3px;
6494
+ .multimodel-note {
6495
+ margin: 8px 0 0;
6496
+ color: var(--muted2);
6497
+ font-size: 9px;
6498
+ line-height: 1.45;
5644
6499
  }
5645
6500
 
5646
6501
  /* readouts: single quiet line */
@@ -5865,22 +6720,26 @@ input[type=range] {
5865
6720
  border-radius: 2px;
5866
6721
  }
5867
6722
 
5868
- /* ------------------------------------------------ Unity scene tools overlay --- */
5869
- /* Unity puts the transform tools in the scene view's top-left corner, under
5870
- the pane tab — not in a window toolbar. */
6723
+ /* ------------------------------------------------ Unity scene title bar --- */
6724
+ /* View tabs and their context tools share one uninterrupted horizontal bar. */
5871
6725
  .editor-toolbar.scene-tools {
5872
- position: absolute;
5873
- top: 27px;
5874
- left: 0;
5875
- z-index: 8;
6726
+ position: static;
6727
+ flex: 1;
6728
+ height: 27px;
5876
6729
  display: flex;
6730
+ justify-content: flex-start;
5877
6731
  gap: 0;
6732
+ min-width: 0;
6733
+ overflow-x: auto;
6734
+ overflow-y: hidden;
6735
+ scrollbar-width: none;
5878
6736
  background: var(--panel);
5879
- border-right: 1px solid var(--line);
5880
- border-bottom: 1px solid var(--line);
5881
6737
  }
5882
6738
 
6739
+ .editor-toolbar.scene-tools::-webkit-scrollbar { display: none; }
6740
+
5883
6741
  .editor-toolbar.scene-tools .tool-switch {
6742
+ flex: none;
5884
6743
  border: 0;
5885
6744
  border-radius: 0;
5886
6745
  padding: 0;
@@ -5896,6 +6755,24 @@ input[type=range] {
5896
6755
  background: transparent;
5897
6756
  }
5898
6757
 
6758
+ .editor-toolbar.scene-tools .tool-switch button {
6759
+ width: 29px;
6760
+ padding: 0;
6761
+ gap: 0;
6762
+ font-size: 0;
6763
+ justify-content: center;
6764
+ }
6765
+
6766
+ .editor-toolbar.scene-tools .tool-switch .tool-icon {
6767
+ width: 14px;
6768
+ height: 14px;
6769
+ }
6770
+
6771
+ .editor-toolbar.scene-tools .snap-switch {
6772
+ padding: 0 6px;
6773
+ font-size: 8px;
6774
+ }
6775
+
5899
6776
  .editor-toolbar.scene-tools .tool-switch button.active {
5900
6777
  background: #2d5c8a;
5901
6778
  color: #fff;
@@ -5906,6 +6783,122 @@ input[type=range] {
5906
6783
  color: var(--fg);
5907
6784
  }
5908
6785
 
6786
+ .viewport-toolbar-separator {
6787
+ flex: 0 0 1px;
6788
+ align-self: stretch;
6789
+ background: var(--line);
6790
+ }
6791
+
6792
+ .editor-toolbar.scene-tools .settings-separator {
6793
+ margin-left: auto;
6794
+ }
6795
+
6796
+ .viewport-toolbar-field,
6797
+ .viewport-fov-control {
6798
+ flex: none;
6799
+ height: 26px;
6800
+ display: flex;
6801
+ align-items: center;
6802
+ gap: 4px;
6803
+ padding: 0 4px;
6804
+ border-right: 1px solid var(--line);
6805
+ color: #9aa0a6;
6806
+ font-size: 9px;
6807
+ white-space: nowrap;
6808
+ }
6809
+
6810
+ .viewport-toolbar-field > span { display: none; }
6811
+
6812
+ .viewport-toolbar-field select {
6813
+ height: 21px;
6814
+ min-width: 0;
6815
+ padding: 0 18px 0 5px;
6816
+ border: 1px solid #494949;
6817
+ border-radius: 2px;
6818
+ background: #242424;
6819
+ color: #dedede;
6820
+ font: inherit;
6821
+ font-size: 10px;
6822
+ }
6823
+
6824
+ .viewport-toolbar-field.shot-field select { width: 92px; }
6825
+ .viewport-toolbar-field.ratio-field select { width: 64px; }
6826
+
6827
+ .viewport-fov-control input {
6828
+ width: 54px;
6829
+ accent-color: #4b8bc4;
6830
+ }
6831
+
6832
+ .viewport-fov-control output {
6833
+ min-width: 25px;
6834
+ color: #efefef;
6835
+ font-size: 10px;
6836
+ text-align: right;
6837
+ }
6838
+
6839
+ .viewport-fov-control small {
6840
+ color: #9aa0a6;
6841
+ font-size: 9px;
6842
+ }
6843
+
6844
+ .viewport-toolbar-spacer {
6845
+ display: none;
6846
+ }
6847
+
6848
+ .editor-toolbar.scene-tools > button,
6849
+ .editor-toolbar.play-tools > button {
6850
+ flex: none;
6851
+ height: 26px;
6852
+ padding: 0 6px;
6853
+ border: 0;
6854
+ border-right: 1px solid var(--line);
6855
+ background: transparent;
6856
+ color: #bdbdbd;
6857
+ font: inherit;
6858
+ font-size: 9px;
6859
+ cursor: pointer;
6860
+ white-space: nowrap;
6861
+ }
6862
+
6863
+ .editor-toolbar.scene-tools > button:hover,
6864
+ .editor-toolbar.play-tools > button:hover {
6865
+ background: #363636;
6866
+ color: #fff;
6867
+ }
6868
+
6869
+ .editor-toolbar.play-tools > button:disabled {
6870
+ opacity: .38;
6871
+ cursor: default;
6872
+ }
6873
+
6874
+ .editor-toolbar.play-tools {
6875
+ position: static;
6876
+ flex: 1;
6877
+ min-width: 0;
6878
+ height: 27px;
6879
+ display: flex;
6880
+ align-items: center;
6881
+ justify-content: flex-end;
6882
+ gap: 0;
6883
+ background: var(--panel);
6884
+ }
6885
+
6886
+ .viewport-readout {
6887
+ flex: none;
6888
+ height: 26px;
6889
+ display: inline-flex;
6890
+ align-items: center;
6891
+ padding: 0 8px;
6892
+ border-right: 1px solid var(--line);
6893
+ color: #b7b7b7;
6894
+ font-size: 9px;
6895
+ white-space: nowrap;
6896
+ }
6897
+
6898
+ .editor-toolbar.play-tools > button.recording {
6899
+ color: #ff8d86;
6900
+ }
6901
+
5909
6902
  /* ----------------------------------------------------- Unity axis colors --- */
5910
6903
  /* X red / Y green / Z blue — Unity's axis colour-coding (class-Transform). */
5911
6904
  .vec3-row .number-field:nth-of-type(1) .axis { color: #e5484d; }
@@ -5914,8 +6907,8 @@ input[type=range] {
5914
6907
 
5915
6908
  /* ----------------------------------------------------- Unity tree polish --- */
5916
6909
  .hierarchy-toggle {
5917
- font-size: 8px;
5918
- color: #8a8a8a;
6910
+ font-size: 11px;
6911
+ color: #a0a0a0;
5919
6912
  }
5920
6913
 
5921
6914
  .hierarchy-row-wrap {
@@ -6438,3 +7431,177 @@ input[type=range] {
6438
7431
  .inspector-scroll > .card {
6439
7432
  flex-shrink: 0;
6440
7433
  }
7434
+
7435
+ /* ---------------------------------------------------------- background --- */
7436
+ /* The matte editor: the picture with everything that will be removed painted
7437
+ violet. Purple never occurs in a photographed set, so a stray purple blob on
7438
+ the subject — or a patch of wall that stayed its own colour — reads at a
7439
+ glance, which a finished cutout cannot show you. */
7440
+
7441
+ .matte-editor {
7442
+ display: flex;
7443
+ flex-direction: column;
7444
+ gap: 6px;
7445
+ margin: 6px 0 2px;
7446
+ }
7447
+
7448
+ .matte-canvas {
7449
+ display: block;
7450
+ /* A stage, not a framed picture: the canvas fills this box and paints its
7451
+ own ground, so the picture sits ON it and nothing outside the canvas can
7452
+ crop the picture once it is zoomed past fit. */
7453
+ width: 100%;
7454
+ height: 240px;
7455
+ background: #141819;
7456
+ border: 1px solid var(--line);
7457
+ border-radius: 3px;
7458
+ touch-action: none;
7459
+ cursor: crosshair;
7460
+ }
7461
+
7462
+ .presets.matte-modes {
7463
+ display: flex;
7464
+ flex-wrap: wrap;
7465
+ gap: 6px;
7466
+ }
7467
+
7468
+ /* ------------------------------------------------------------ drop it --- */
7469
+ /* A picture dropped on the Props branch, the Props inspector or the shot view
7470
+ becomes a cutout. A drop zone that gives no sign it is armed reads as dead
7471
+ area, so each one lights its own edge while a file is over it. */
7472
+
7473
+ .props-drop {
7474
+ display: flex;
7475
+ flex-direction: column;
7476
+ gap: 8px;
7477
+ border: 1px dashed transparent;
7478
+ border-radius: 4px;
7479
+ padding: 2px;
7480
+ transition: border-color 120ms ease, background 120ms ease;
7481
+ }
7482
+
7483
+ .props-drop[data-drop="over"],
7484
+ .hierarchy-row-wrap[data-drop="over"] {
7485
+ border-color: var(--accent, #e7b557);
7486
+ background: rgba(231, 181, 87, 0.1);
7487
+ }
7488
+
7489
+ .hierarchy-row-wrap[data-drop="over"] {
7490
+ border: 1px dashed var(--accent, #e7b557);
7491
+ border-radius: 3px;
7492
+ }
7493
+
7494
+ .viewport[data-drop="over"] {
7495
+ outline: 2px dashed var(--accent, #e7b557);
7496
+ outline-offset: -6px;
7497
+ }
7498
+
7499
+ @media (prefers-reduced-motion: reduce) {
7500
+ .props-drop { transition: none; }
7501
+ }
7502
+
7503
+ /* The matte editor's two dials. A bare range in a dark panel is nearly
7504
+ invisible — no accent, intrinsic width, no label alignment — so both get a
7505
+ real row: name, a full-width track, and a box you can type an exact number
7506
+ into. Tolerance especially: 0.18 and 0.22 are different answers, and a drag
7507
+ along an unlabelled track cannot tell you which one you have. */
7508
+
7509
+ .matte-slider {
7510
+ display: grid;
7511
+ grid-template-columns: auto 1fr 4.6rem;
7512
+ align-items: center;
7513
+ gap: 10px;
7514
+ margin: 8px 0;
7515
+ }
7516
+
7517
+ .matte-slider label {
7518
+ font-size: 11.5px;
7519
+ color: var(--muted);
7520
+ }
7521
+
7522
+ .matte-slider input[type="range"] {
7523
+ width: 100%;
7524
+ min-width: 0;
7525
+ accent-color: var(--accent);
7526
+ }
7527
+
7528
+ .matte-slider input[type="number"] {
7529
+ width: 100%;
7530
+ padding: 5px 6px;
7531
+ background: var(--card2);
7532
+ border: 1px solid var(--line);
7533
+ border-radius: 4px;
7534
+ color: var(--fg);
7535
+ font-size: 12px;
7536
+ font-variant-numeric: tabular-nums;
7537
+ text-align: right;
7538
+ }
7539
+
7540
+ .btn.matte-apply {
7541
+ margin-top: 4px;
7542
+ }
7543
+
7544
+ .btn.matte-apply[disabled] {
7545
+ opacity: 0.5;
7546
+ cursor: not-allowed;
7547
+ }
7548
+
7549
+ .inspector-hint.matte-state {
7550
+ padding: 6px 8px;
7551
+ border-left: 2px solid var(--accent);
7552
+ background: var(--card2);
7553
+ border-radius: 0 3px 3px 0;
7554
+ }
7555
+
7556
+
7557
+ /* The matte tools read as two hands: what the brush does on the left, what to
7558
+ do about what it did on the right. Clear sits under Undo/Redo because it is
7559
+ the same kind of act — taking work back — only all of it.
7560
+
7561
+ The buttons are one fixed size and the SPACE between the two groups is what
7562
+ flexes, so the panel can be dragged wider without five buttons growing into
7563
+ five different shapes. */
7564
+
7565
+ .matte-tools {
7566
+ display: flex;
7567
+ align-items: flex-start;
7568
+ justify-content: space-between;
7569
+ gap: 12px;
7570
+ margin: 8px 0;
7571
+ }
7572
+
7573
+ .matte-history {
7574
+ display: flex;
7575
+ flex-direction: column;
7576
+ align-items: flex-end;
7577
+ gap: 6px;
7578
+ }
7579
+
7580
+ .matte-tools .presets.matte-modes {
7581
+ display: flex;
7582
+ flex-wrap: nowrap;
7583
+ gap: 6px;
7584
+ margin: 0;
7585
+ }
7586
+
7587
+ .matte-tools .presets.matte-modes button {
7588
+ /* Fixed width, centred label: the panel resizes by moving the two groups
7589
+ apart, never by restyling five buttons into five shapes. */
7590
+ display: flex;
7591
+ align-items: center;
7592
+ justify-content: center;
7593
+ flex: 0 0 auto;
7594
+ width: 4rem;
7595
+ padding: 9px 2px;
7596
+ font-size: 11.5px;
7597
+ line-height: 1.2;
7598
+ text-align: center;
7599
+ white-space: nowrap;
7600
+ }
7601
+
7602
+ /* Undo, redo and clear are icons — a symbol the width of a glyph, not a word
7603
+ that has to be read. They keep their names in the tooltip. */
7604
+ .matte-tools .presets.matte-icons button {
7605
+ width: 2.3rem;
7606
+ font-size: 13px;
7607
+ }