@tikagent/video-editor-cli 0.0.0-stage → 1.5.0-preview.1

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 (87) hide show
  1. package/LICENSE +82 -0
  2. package/THIRD-PARTY-NOTICES.md +21 -0
  3. package/dist/bin/tik-video-editor-cli.js +2 -0
  4. package/dist/lib/asr.js +1 -0
  5. package/dist/lib/audio.js +1 -0
  6. package/dist/lib/auth.js +1 -0
  7. package/dist/lib/browser-zip.js +1 -0
  8. package/dist/lib/browser.js +1 -0
  9. package/dist/lib/cli.js +1 -0
  10. package/dist/lib/doctor.js +1 -0
  11. package/dist/lib/download.js +1 -0
  12. package/dist/lib/export-progress.js +1 -0
  13. package/dist/lib/import-video.js +1 -0
  14. package/dist/lib/local.js +1 -0
  15. package/dist/lib/media.js +1 -0
  16. package/dist/lib/operation.js +1 -0
  17. package/dist/lib/preset.js +1 -0
  18. package/dist/lib/processes.js +1 -0
  19. package/dist/lib/self.js +1 -0
  20. package/dist/lib/service-urls.js +1 -0
  21. package/dist/lib/storage.js +1 -0
  22. package/dist/runtime/LICENSE +21 -0
  23. package/dist/runtime/analyze.js +1 -0
  24. package/dist/runtime/app.js +1 -0
  25. package/dist/runtime/cli/lib/browser-zip.js +1 -0
  26. package/dist/runtime/cli/lib/browser.js +1 -0
  27. package/dist/runtime/cli/lib/processes.js +1 -0
  28. package/dist/runtime/export-audio.js +1 -0
  29. package/dist/runtime/export-cache.js +1 -0
  30. package/dist/runtime/export-encoder.js +1 -0
  31. package/dist/runtime/export-save.js +1 -0
  32. package/dist/runtime/export-worker.js +1 -0
  33. package/dist/runtime/favicon.svg +14 -0
  34. package/dist/runtime/i18n.js +1 -0
  35. package/dist/runtime/icons/favicon-32.png +0 -0
  36. package/dist/runtime/icons/tik-logo.png +0 -0
  37. package/dist/runtime/index.html +320 -0
  38. package/dist/runtime/library/README.md +12 -0
  39. package/dist/runtime/library/elements/bokeh-drift.svg +19 -0
  40. package/dist/runtime/library/elements/light-leak-cool.svg +16 -0
  41. package/dist/runtime/library/elements/light-leak-warm.svg +22 -0
  42. package/dist/runtime/library/elements/vhs-scanlines.svg +18 -0
  43. package/dist/runtime/library/elements/vignette-frame.svg +14 -0
  44. package/dist/runtime/library/fonts//351/230/277/351/207/214/345/267/264/345/267/264/346/231/256/346/203/240/344/275/223-/344/270/255/351/273/221.woff2 +0 -0
  45. package/dist/runtime/library/fonts//351/230/277/351/207/214/345/267/264/345/267/264/346/231/256/346/203/240/344/275/223-/345/270/270/350/247/204.woff2 +0 -0
  46. package/dist/runtime/library/fonts//351/230/277/351/207/214/345/267/264/345/267/264/346/231/256/346/203/240/344/275/223-/347/262/227/344/275/223.woff2 +0 -0
  47. package/dist/runtime/library/sfx/README.md +13 -0
  48. package/dist/runtime/library/svg/arrow-bounce.svg +18 -0
  49. package/dist/runtime/library/svg/arrow-scribble.svg +13 -0
  50. package/dist/runtime/library/svg/burst-lines.svg +30 -0
  51. package/dist/runtime/library/svg/checkmark-success.svg +19 -0
  52. package/dist/runtime/library/svg/confetti-burst.svg +23 -0
  53. package/dist/runtime/library/svg/countdown-ring.svg +92 -0
  54. package/dist/runtime/library/svg/equalizer.svg +18 -0
  55. package/dist/runtime/library/svg/glow-orbs.svg +29 -0
  56. package/dist/runtime/library/svg/heart-pop.svg +26 -0
  57. package/dist/runtime/library/svg/loading-dots.svg +16 -0
  58. package/dist/runtime/library/svg/location-pin.svg +25 -0
  59. package/dist/runtime/library/svg/lower-third.svg +17 -0
  60. package/dist/runtime/library/svg/new-badge.svg +18 -0
  61. package/dist/runtime/library/svg/progress-bar.svg +16 -0
  62. package/dist/runtime/library/svg/radial-pulse.svg +19 -0
  63. package/dist/runtime/library/svg/rating-stars.svg +25 -0
  64. package/dist/runtime/library/svg/rec-indicator.svg +41 -0
  65. package/dist/runtime/library/svg/sparkles.svg +17 -0
  66. package/dist/runtime/library/svg/speech-bubble.svg +23 -0
  67. package/dist/runtime/library/svg/subscribe-bell.svg +29 -0
  68. package/dist/runtime/library/svg/subscribe-pill.svg +22 -0
  69. package/dist/runtime/library/svg/swipe-up.svg +46 -0
  70. package/dist/runtime/library/svg/underline-swoosh.svg +15 -0
  71. package/dist/runtime/manifest.json +40 -0
  72. package/dist/runtime/meter-worklet.js +1 -0
  73. package/dist/runtime/optimized-encoder-worker.js +1 -0
  74. package/dist/runtime/optimized-export.js +1 -0
  75. package/dist/runtime/paths.js +1 -0
  76. package/dist/runtime/project-store.js +1 -0
  77. package/dist/runtime/ruler-worker.js +1 -0
  78. package/dist/runtime/server.js +1 -0
  79. package/dist/runtime/style.css +2126 -0
  80. package/dist/runtime/timeline.js +1 -0
  81. package/dist/runtime/waveform.js +1 -0
  82. package/package.json +37 -4
  83. package/scripts/build-package.js +69 -0
  84. package/scripts/next-version.js +56 -0
  85. package/scripts/pack-runtime.js +26 -0
  86. package/scripts/release-channel.js +115 -0
  87. package/README.md +0 -3
@@ -0,0 +1,2126 @@
1
+ /* ══════════════════ FableCut — Premiere-style dark theme ══════════════════ */
2
+ :root {
3
+ --bg: #0e0e10;
4
+ --panel: #1b1b1f;
5
+ --panel-2: #232329;
6
+ --border: #2d2d34;
7
+ --text: #d7d7dc;
8
+ --dim: #8b8b93;
9
+ --accent: #7b6cff;
10
+ --accent-2: #4f8cff;
11
+ --danger: #e5484d;
12
+ --clip-video: var(--panel-2);
13
+ --track-h-video: 58px;
14
+ --track-h-audio: 42px;
15
+ --side-panel-w: 320px;
16
+ }
17
+
18
+ * {
19
+ box-sizing: border-box;
20
+ margin: 0;
21
+ padding: 0;
22
+ user-select: none;
23
+ }
24
+
25
+ html,
26
+ body {
27
+ height: 100%;
28
+ overflow: hidden;
29
+ }
30
+
31
+ body {
32
+ background: var(--bg);
33
+ color: var(--text);
34
+ font: 13px/1.45 "Segoe UI", system-ui, -apple-system, sans-serif;
35
+ }
36
+
37
+ .app {
38
+ display: flex;
39
+ flex-direction: column;
40
+ height: 100vh;
41
+ gap: 6px;
42
+ padding: 6px;
43
+ }
44
+
45
+ .topbar {
46
+ flex: 0 0 auto;
47
+ min-height: 46px;
48
+ }
49
+
50
+ .upper {
51
+ flex: 1 1 0;
52
+ min-height: 140px;
53
+ min-width: 0;
54
+ }
55
+
56
+ .timeline-panel {
57
+ flex: 0 0 var(--timeline-h, 400px);
58
+ min-height: 180px;
59
+ overflow: hidden;
60
+ }
61
+
62
+ .v-split {
63
+ flex: 0 0 6px;
64
+ cursor: ns-resize;
65
+ position: relative;
66
+ z-index: 5;
67
+ border-radius: 3px;
68
+ }
69
+
70
+ .v-split::after {
71
+ content: "";
72
+ position: absolute;
73
+ left: 18%;
74
+ right: 18%;
75
+ top: 2px;
76
+ height: 2px;
77
+ border-radius: 1px;
78
+ background: var(--border);
79
+ transition: background .15s;
80
+ }
81
+
82
+ .v-split:hover::after,
83
+ .v-split.dragging::after {
84
+ background: var(--accent);
85
+ }
86
+
87
+ body.resizing-panels {
88
+ cursor: ns-resize !important;
89
+ }
90
+
91
+ body.resizing-panels * {
92
+ cursor: ns-resize !important;
93
+ user-select: none !important;
94
+ }
95
+
96
+ .hidden {
97
+ display: none !important;
98
+ }
99
+
100
+ /* Module visibility is applied from settings, independently of transient UI state. */
101
+ [data-ui-setting]:not([data-ui-visible]) {
102
+ display: none !important;
103
+ }
104
+
105
+ .dim {
106
+ color: var(--dim);
107
+ display: inline-flex;
108
+ }
109
+
110
+ .flex-spacer {
111
+ flex: 1;
112
+ }
113
+
114
+ /* Visually hidden but still activatable (file picker via <label for>) */
115
+ .sr-only {
116
+ position: absolute;
117
+ width: 1px;
118
+ height: 1px;
119
+ padding: 0;
120
+ margin: -1px;
121
+ overflow: hidden;
122
+ clip: rect(0, 0, 0, 0);
123
+ white-space: nowrap;
124
+ border: 0;
125
+ }
126
+
127
+ /* ── Top bar ── */
128
+ .topbar {
129
+ display: flex;
130
+ flex-wrap: wrap;
131
+ align-items: center;
132
+ gap: 12px;
133
+ padding: 7px 12px;
134
+ background: var(--panel);
135
+ border: 1px solid var(--border);
136
+ border-radius: 8px;
137
+ }
138
+
139
+ .logo {
140
+ display: flex;
141
+ flex: none;
142
+ white-space: nowrap;
143
+ align-items: center;
144
+ font-size: 15px;
145
+ letter-spacing: .3px;
146
+ color: #fff;
147
+ }
148
+
149
+ .logo b {
150
+ color: var(--accent);
151
+ }
152
+
153
+ .logo-mark {
154
+ display: block;
155
+ flex: none;
156
+ width: 28px;
157
+ height: 28px;
158
+ object-fit: contain;
159
+ margin-right: 6px;
160
+ }
161
+
162
+ .topbar-center {
163
+ flex: 1 1 80px;
164
+ min-width: 0;
165
+ display: flex;
166
+ align-items: center;
167
+ justify-content: center;
168
+ gap: 8px;
169
+ color: var(--dim);
170
+ }
171
+
172
+ .current-project-name {
173
+ min-width: 0;
174
+ overflow: hidden;
175
+ text-overflow: ellipsis;
176
+ white-space: nowrap;
177
+ color: var(--text);
178
+ }
179
+
180
+ .topbar-center:has(#projectSelect[data-ui-visible]) .current-project-name {
181
+ display: none;
182
+ }
183
+
184
+ .project-select {
185
+ min-width: 0;
186
+ width: 100%;
187
+ max-width: 280px;
188
+ height: 28px;
189
+ border: 1px solid var(--border);
190
+ border-radius: 5px;
191
+ padding: 0 28px 0 9px;
192
+ background: var(--panel-2);
193
+ color: var(--text);
194
+ font: inherit;
195
+ }
196
+
197
+ .connection-status { font-size: 11px; white-space: nowrap; }
198
+
199
+ .topbar-right {
200
+ display: flex;
201
+ flex: none;
202
+ flex-wrap: wrap;
203
+ max-width: 100%;
204
+ margin-left: auto;
205
+ gap: 8px;
206
+ align-items: center;
207
+ }
208
+
209
+ #btnExport {
210
+ flex: none;
211
+ white-space: nowrap;
212
+ }
213
+
214
+ .layout-tools {
215
+ display: flex;
216
+ align-items: center;
217
+ gap: 6px;
218
+ margin-right: 4px;
219
+ }
220
+
221
+ .btn-group {
222
+ display: inline-flex;
223
+ gap: 0px;
224
+ }
225
+
226
+ .btn-group .btn:first-child {
227
+ border-radius: 5px 0 0 5px;
228
+ }
229
+
230
+ .btn-group .btn:not(:first-child):not(:last-child) {
231
+ border-radius: 0;
232
+ margin: 0;
233
+ }
234
+
235
+ .btn-group .btn:last-child {
236
+ border-radius: 0 5px 5px 0;
237
+ }
238
+
239
+ .btn-group .btn.on {
240
+ border-color: var(--accent);
241
+ z-index: 1;
242
+ }
243
+
244
+ body.track-size-s .clip .clip-label {
245
+ font-size: 10px;
246
+ padding: 0 6px;
247
+ }
248
+
249
+ body.track-size-s .clip .fade {
250
+ display: none;
251
+ }
252
+
253
+ body.track-size-s .clip.c-audio .clip-body::after {
254
+ height: 12px;
255
+ }
256
+
257
+ body.track-size-s .clip {
258
+ border-width: 1px;
259
+ border-radius: 2px;
260
+ box-shadow: none;
261
+ }
262
+
263
+ body.track-size-s .clip .handle.l {
264
+ border-left-width: 1px;
265
+ }
266
+
267
+ body.track-size-s .clip .handle.r {
268
+ border-right-width: 1px;
269
+ }
270
+
271
+ body.track-size-s .clip.selected {
272
+ outline-width: 1px;
273
+ box-shadow: 0 0 0 1px #7b6cff55;
274
+ }
275
+
276
+ /* ── Title-style picker (inspector) ── */
277
+ .style-picker-btn {
278
+ flex: 1;
279
+ min-width: 0;
280
+ text-align: left;
281
+ overflow: hidden;
282
+ text-overflow: ellipsis;
283
+ }
284
+
285
+ .style-menu {
286
+ position: fixed;
287
+ z-index: 100;
288
+ min-width: 190px;
289
+ max-height: 330px;
290
+ overflow-y: auto;
291
+ background: var(--panel-2);
292
+ border: 1px solid var(--border);
293
+ border-radius: 8px;
294
+ padding: 4px;
295
+ box-shadow: 0 12px 32px #000c;
296
+ }
297
+
298
+ .style-opt {
299
+ padding: 7px 10px;
300
+ border-radius: 5px;
301
+ font-size: 15px;
302
+ line-height: 1.25;
303
+ color: var(--text);
304
+ cursor: pointer;
305
+ white-space: nowrap;
306
+ }
307
+
308
+ .style-opt:hover {
309
+ background: #7b6cff26;
310
+ }
311
+
312
+ .style-opt.on {
313
+ color: #cfc8ff;
314
+ background: #7b6cff14;
315
+ }
316
+
317
+ .ctx-menu {
318
+ position: fixed;
319
+ z-index: 200;
320
+ min-width: 160px;
321
+ background: var(--panel-2);
322
+ border: 1px solid var(--border);
323
+ border-radius: 8px;
324
+ padding: 4px;
325
+ box-shadow: 0 12px 32px #000c;
326
+ }
327
+ .ctx-opt {
328
+ padding: 7px 12px;
329
+ border-radius: 5px;
330
+ font-size: 13px;
331
+ color: var(--text);
332
+ cursor: pointer;
333
+ white-space: nowrap;
334
+ }
335
+ .ctx-opt:hover {
336
+ background: #7b6cff26;
337
+ }
338
+ /* media-replace picker reuses .style-menu/.style-opt but lists plain file
339
+ names, not font previews — match the app's normal UI text size */
340
+ .style-opt.media-opt {
341
+ font-size: 12px;
342
+ line-height: 1.3;
343
+ max-width: 260px;
344
+ overflow: hidden;
345
+ text-overflow: ellipsis;
346
+ }
347
+
348
+ /* ── Buttons ── */
349
+ .btn {
350
+ display: inline-block;
351
+ background: var(--panel-2);
352
+ color: var(--text);
353
+ border: 1px solid var(--border);
354
+ border-radius: 6px;
355
+ padding: 6px 12px;
356
+ font: inherit;
357
+ cursor: pointer;
358
+ white-space: nowrap;
359
+ }
360
+
361
+ .btn:hover {
362
+ background: #2c2c34;
363
+ border-color: #3c3c46;
364
+ }
365
+
366
+ .btn:active {
367
+ transform: translateY(1px);
368
+ }
369
+
370
+ .btn.primary {
371
+ background: linear-gradient(135deg, var(--accent), var(--accent-2));
372
+ border: none;
373
+ color: #fff;
374
+ font-weight: 600;
375
+ }
376
+
377
+ .btn.primary:hover {
378
+ filter: brightness(1.12);
379
+ }
380
+
381
+ .btn.ghost {
382
+ background: transparent;
383
+ }
384
+
385
+ .btn.tiny {
386
+ padding: 3px 9px;
387
+ font-size: 12px;
388
+ border-radius: 5px;
389
+ }
390
+
391
+ .btn:disabled {
392
+ opacity: .4;
393
+ cursor: not-allowed;
394
+ }
395
+
396
+ .btn .ico {
397
+ display: inline-block;
398
+ vertical-align: -2px;
399
+ margin-right: 2px;
400
+ }
401
+
402
+ .btn.tiny.accent {
403
+ border-color: var(--accent);
404
+ color: #cfc8ff;
405
+ }
406
+
407
+ .btn.icon {
408
+ width: 34px;
409
+ padding: 6px 0;
410
+ text-align: center;
411
+ }
412
+
413
+ .btn.icon.big {
414
+ width: 44px;
415
+ font-size: 15px;
416
+ }
417
+
418
+ .btn.toggle.on {
419
+ border-color: var(--accent);
420
+ color: #cfc8ff;
421
+ background: #7b6cff1a;
422
+ }
423
+
424
+ /* ── Panels ── */
425
+ .panel {
426
+ background: var(--panel);
427
+ border: 1px solid var(--border);
428
+ border-radius: 8px;
429
+ display: flex;
430
+ flex-direction: column;
431
+ min-height: 0;
432
+ min-width: 0;
433
+ }
434
+
435
+ .panel-head {
436
+ display: flex;
437
+ align-items: center;
438
+ justify-content: space-between;
439
+ padding: 7px 10px;
440
+ font-size: 12px;
441
+ font-weight: 600;
442
+ letter-spacing: .4px;
443
+ color: var(--dim);
444
+ text-transform: uppercase;
445
+ border-bottom: 1px solid var(--border);
446
+ }
447
+
448
+ .panel-head-title {
449
+ display: inline-flex;
450
+ align-items: center;
451
+ gap: 8px;
452
+ min-width: 0;
453
+ }
454
+
455
+ .panel-head-title .btn {
456
+ text-transform: none;
457
+ letter-spacing: normal;
458
+ font-weight: 600;
459
+ }
460
+
461
+ .panel-head-actions {
462
+ display: flex;
463
+ gap: 6px;
464
+ text-transform: none;
465
+ flex-wrap: wrap;
466
+ justify-content: flex-end;
467
+ align-items: center;
468
+ }
469
+
470
+ .upper {
471
+ display: grid;
472
+ grid-template-columns: minmax(0, 1fr);
473
+ gap: 6px;
474
+ min-height: 0;
475
+ }
476
+
477
+ .panel.bin,
478
+ .panel.inspector {
479
+ min-width: 0;
480
+ overflow: hidden;
481
+ }
482
+
483
+ .panel.bin {
484
+ z-index: 1;
485
+ }
486
+
487
+ /* keep overflowing head buttons above the monitor */
488
+
489
+ /* ── Media bin ── */
490
+ .bin-tabs {
491
+ display: flex;
492
+ gap: 2px;
493
+ padding: 6px 8px 0;
494
+ border-bottom: 1px solid var(--border);
495
+ }
496
+
497
+ .bin-tabs button {
498
+ flex: 1;
499
+ background: none;
500
+ border: none;
501
+ border-bottom: 2px solid transparent;
502
+ color: var(--dim);
503
+ font: 600 11px/1.2 "Segoe UI", sans-serif;
504
+ padding: 5px 2px 7px;
505
+ cursor: pointer;
506
+ letter-spacing: .2px;
507
+ white-space: nowrap;
508
+ }
509
+
510
+ .bin-tabs button:hover {
511
+ color: var(--text);
512
+ }
513
+
514
+ .bin-tabs button.on {
515
+ color: #cfc8ff;
516
+ border-bottom-color: var(--accent);
517
+ }
518
+
519
+ .bin-list {
520
+ flex: 1;
521
+ overflow-y: auto;
522
+ padding: 8px;
523
+ display: flex;
524
+ flex-direction: column;
525
+ gap: 4px;
526
+ }
527
+
528
+ .lib-item .lib-play,
529
+ .lib-item .lib-add {
530
+ flex: none;
531
+ width: 26px;
532
+ padding: 3px 0;
533
+ text-align: center;
534
+ }
535
+
536
+ .bin-thumb.svg {
537
+ background-color: #2a2a33;
538
+ background-size: contain;
539
+ background-repeat: no-repeat;
540
+ background-position: center;
541
+ }
542
+
543
+ .bin-empty {
544
+ margin: auto;
545
+ text-align: center;
546
+ color: var(--dim);
547
+ padding: 20px 10px;
548
+ }
549
+
550
+ .bin-empty-icon {
551
+ font-size: 34px;
552
+ margin-bottom: 10px;
553
+ opacity: .8;
554
+ }
555
+
556
+ .bin-empty .hint {
557
+ margin-top: 8px;
558
+ font-size: 11px;
559
+ opacity: .7;
560
+ }
561
+
562
+ .bin-item,
563
+ .bin-folder {
564
+ display: flex;
565
+ gap: 8px;
566
+ align-items: center;
567
+ padding: 6px;
568
+ padding-left: calc(6px + var(--bin-depth, 0) * 14px);
569
+ border-radius: 6px;
570
+ background: var(--panel-2);
571
+ border: 1px solid var(--border);
572
+ cursor: grab;
573
+ }
574
+
575
+ .bin-item:hover,
576
+ .bin-folder:hover {
577
+ border-color: #454552;
578
+ }
579
+
580
+ .bin-item.selected {
581
+ border-color: var(--accent);
582
+ background: #7b6cff18;
583
+ box-shadow: inset 0 0 0 1px #7b6cff44;
584
+ }
585
+
586
+ .bin-item:active,
587
+ .bin-folder:active {
588
+ cursor: grabbing;
589
+ }
590
+
591
+ .bin-item.bin-dragging,
592
+ .bin-folder.bin-dragging {
593
+ opacity: .45;
594
+ }
595
+
596
+ .bin-folder {
597
+ background: #1a1a20;
598
+ cursor: default;
599
+ }
600
+
601
+ .bin-folder .bin-folder-twist {
602
+ flex: none;
603
+ width: 18px;
604
+ height: 22px;
605
+ padding: 0;
606
+ border: 0;
607
+ background: transparent;
608
+ color: var(--dim);
609
+ cursor: pointer;
610
+ font-size: 9px;
611
+ line-height: 22px;
612
+ }
613
+
614
+ .bin-folder-icon {
615
+ flex: none;
616
+ font-size: 14px;
617
+ line-height: 1;
618
+ }
619
+
620
+ .bin-folder-name {
621
+ flex: 1;
622
+ min-width: 0;
623
+ font-size: 12px;
624
+ font-weight: 600;
625
+ white-space: nowrap;
626
+ overflow: hidden;
627
+ text-overflow: ellipsis;
628
+ outline: none;
629
+ border-radius: 3px;
630
+ }
631
+
632
+ .bin-folder-name[contenteditable="true"] {
633
+ background: var(--panel);
634
+ border: 1px solid var(--accent);
635
+ padding: 1px 4px;
636
+ cursor: text;
637
+ }
638
+
639
+ .bin-folder-count {
640
+ flex: none;
641
+ font-size: 10px;
642
+ color: var(--dim);
643
+ font-variant-numeric: tabular-nums;
644
+ }
645
+
646
+ .bin-folder-add {
647
+ flex: none;
648
+ width: 20px;
649
+ height: 20px;
650
+ padding: 0;
651
+ border: 0;
652
+ border-radius: 4px;
653
+ background: transparent;
654
+ color: var(--dim);
655
+ cursor: pointer;
656
+ opacity: 0;
657
+ font-size: 14px;
658
+ line-height: 20px;
659
+ }
660
+
661
+ .bin-folder:hover .bin-folder-add {
662
+ opacity: 1;
663
+ }
664
+
665
+ .bin-folder-add:hover {
666
+ color: var(--text);
667
+ background: #2a2a33;
668
+ }
669
+
670
+ .bin-item.bin-drop-over,
671
+ .bin-folder.bin-drop-over,
672
+ .bin-drop-root.bin-drop-over {
673
+ border-color: var(--accent);
674
+ box-shadow: inset 0 0 0 1px var(--accent);
675
+ background: #7b6cff18;
676
+ }
677
+
678
+ .bin-drop-root {
679
+ margin-top: 4px;
680
+ padding: 8px;
681
+ border-radius: 6px;
682
+ border: 1px dashed transparent;
683
+ color: var(--dim);
684
+ font-size: 11px;
685
+ text-align: center;
686
+ opacity: 0;
687
+ transition: opacity .12s, border-color .12s;
688
+ pointer-events: none;
689
+ }
690
+
691
+ .bin-list:has(.bin-dragging) .bin-drop-root {
692
+ opacity: 1;
693
+ pointer-events: auto;
694
+ border-color: #454552;
695
+ }
696
+
697
+ .bin-thumb {
698
+ width: 58px;
699
+ height: 34px;
700
+ border-radius: 4px;
701
+ flex: none;
702
+ background: #000 center/cover no-repeat;
703
+ display: flex;
704
+ align-items: center;
705
+ justify-content: center;
706
+ font-size: 16px;
707
+ }
708
+
709
+ .bin-thumb-video {
710
+ background-size: contain;
711
+ }
712
+
713
+ /* 丢失提示只覆盖编辑器界面,不进入预览/导出的共享合成画布。 */
714
+ .missing-media-notice:not([hidden]) { display: flex; }
715
+ .missing-media-notice { position: absolute; inset: 0; z-index: 6; display: none; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 16px; background: #450f12; color: #ffe7e7; text-align: center; line-height: 1.5; overflow: auto; }
716
+ .missing-media-icon { font-size: 28px; color: #ffaaa4; }
717
+ .missing-media-notice strong { font-size: 18px; }
718
+ #missingMediaNames { max-width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 12px; }
719
+ #missingMediaHelp { max-width: 360px; color: #e7b3b5; font-size: 12px; }
720
+ .missing-media-notice .btn { flex-shrink: 0; }
721
+ .bin-item.media-missing .bin-thumb { background: #651e24; color: #ffc0bb; }
722
+ .bin-item.media-missing .bin-sub { color: #ffaaa4; }
723
+ .clip.media-missing .clip-body { background: #651e24 !important; }
724
+ .clip.media-missing .fade { display: none; }
725
+ .clip.media-missing .clip-label { color: #ffe7e7; }
726
+
727
+ .bin-meta {
728
+ min-width: 0;
729
+ flex: 1;
730
+ }
731
+
732
+ .bin-name {
733
+ font-size: 12px;
734
+ white-space: nowrap;
735
+ overflow: hidden;
736
+ text-overflow: ellipsis;
737
+ color: #e8e8ee;
738
+ }
739
+
740
+ .bin-sub {
741
+ font-size: 11px;
742
+ color: var(--dim);
743
+ white-space: nowrap;
744
+ overflow: hidden;
745
+ text-overflow: ellipsis;
746
+ }
747
+
748
+ .bin-del {
749
+ flex: none;
750
+ align-self: flex-start;
751
+ color: var(--dim);
752
+ cursor: pointer;
753
+ font-size: 12px;
754
+ line-height: 1;
755
+ padding: 2px 4px;
756
+ opacity: 0;
757
+ pointer-events: none;
758
+ transition: opacity .12s;
759
+ }
760
+
761
+ .bin-item:hover .bin-del,
762
+ .bin-folder:hover .bin-del {
763
+ opacity: 1;
764
+ pointer-events: auto;
765
+ }
766
+
767
+ .bin-del:hover {
768
+ color: var(--danger);
769
+ }
770
+
771
+ /* ── Monitor ── */
772
+ .monitor-stage {
773
+ flex: 1;
774
+ display: flex;
775
+ flex-direction: column;
776
+ background: #000;
777
+ min-height: 0;
778
+ margin: 8px;
779
+ border-radius: 6px;
780
+ overflow: hidden;
781
+ position: relative;
782
+ }
783
+
784
+ .monitor-scroll {
785
+ flex: 1;
786
+ min-height: 0;
787
+ min-width: 0;
788
+ display: flex;
789
+ align-items: center;
790
+ justify-content: center;
791
+ overflow: hidden;
792
+ }
793
+
794
+ .monitor-scroll.is-zoomed {
795
+ display: block;
796
+ overflow: auto;
797
+ cursor: grab;
798
+ }
799
+
800
+ .monitor-scroll.is-zoomed.is-panning {
801
+ cursor: grabbing;
802
+ }
803
+
804
+ .monitor-zoom-inner {
805
+ position: relative;
806
+ line-height: 0;
807
+ flex-shrink: 0;
808
+ }
809
+
810
+ /* Fit mode: fill the scrollport so #preview max-% resolves against the stage */
811
+ .monitor-scroll:not(.is-zoomed) .monitor-zoom-inner {
812
+ width: 100%;
813
+ height: 100%;
814
+ display: flex;
815
+ align-items: center;
816
+ justify-content: center;
817
+ }
818
+
819
+ .monitor-scroll.is-zoomed .monitor-zoom-inner {
820
+ display: inline-block;
821
+ }
822
+
823
+ #preview {
824
+ max-width: 100%;
825
+ max-height: 100%;
826
+ display: block;
827
+ background: #000;
828
+ }
829
+
830
+ .monitor-scroll.is-zoomed #preview {
831
+ max-width: none;
832
+ max-height: none;
833
+ }
834
+
835
+ /* ── Keyframe graphs (left gutter of program monitor) ── */
836
+ .kf-graphs {
837
+ position: absolute;
838
+ left: 6px;
839
+ top: 6px;
840
+ bottom: 6px;
841
+ width: min(168px, 28%);
842
+ z-index: 4;
843
+ display: flex;
844
+ flex-direction: column;
845
+ gap: 6px;
846
+ overflow-x: hidden;
847
+ overflow-y: auto;
848
+ pointer-events: none;
849
+ }
850
+ .kf-graphs[hidden] { display: none; }
851
+ .kf-graph {
852
+ pointer-events: auto;
853
+ flex: 0 0 auto;
854
+ background: #000a;
855
+ border: 1px solid #ffffff18;
856
+ border-radius: 4px;
857
+ padding: 4px 5px 3px;
858
+ user-select: none;
859
+ }
860
+ .kf-graph-head {
861
+ display: flex;
862
+ align-items: center;
863
+ justify-content: space-between;
864
+ gap: 4px;
865
+ margin-bottom: 2px;
866
+ font: 700 9px/1 ui-sans-serif, system-ui, sans-serif;
867
+ letter-spacing: .35px;
868
+ color: #c8c8d0;
869
+ }
870
+ .kf-graph-head button {
871
+ margin: 0;
872
+ padding: 0 3px;
873
+ border: 0;
874
+ background: transparent;
875
+ color: #8b8b93;
876
+ font: 700 11px/1 ui-sans-serif, system-ui, sans-serif;
877
+ cursor: pointer;
878
+ opacity: .75;
879
+ }
880
+ .kf-graph-head button:hover { color: #fff; opacity: 1; }
881
+ .kf-graph canvas {
882
+ display: block;
883
+ width: 100%;
884
+ height: 52px;
885
+ cursor: crosshair;
886
+ border-radius: 2px;
887
+ background: #0a0a0ccc;
888
+ }
889
+
890
+ .insp-row label.kf-graph-toggle {
891
+ cursor: pointer;
892
+ border-radius: 3px;
893
+ margin: -1px -2px;
894
+ padding: 1px 2px;
895
+ }
896
+ .insp-row label.kf-graph-toggle:hover {
897
+ color: #cfc8ff;
898
+ background: #7b6cff22;
899
+ }
900
+ .insp-row label.kf-graph-toggle.on {
901
+ color: #b9baff;
902
+ background: #7b6cff33;
903
+ }
904
+ .insp-row label.kf-graph-toggle.has-kf::after {
905
+ content: " ◆";
906
+ font-size: 8px;
907
+ opacity: .7;
908
+ }
909
+ /* ── Per-track VU (RMS / LUFS / Peak) ── */
910
+ .vu-meter {
911
+ position: absolute;
912
+ right: 8px;
913
+ bottom: 10px;
914
+ display: flex;
915
+ flex-direction: column;
916
+ align-items: stretch;
917
+ gap: 4px;
918
+ z-index: 4;
919
+ pointer-events: auto;
920
+ padding: 5px 5px 4px;
921
+ background: #000a;
922
+ user-select: none;
923
+ }
924
+ .vu-mode {
925
+ display: block;
926
+ width: 100%;
927
+ margin: 0;
928
+ padding: 2px 0 2px 14px;
929
+ border: 0;
930
+ background: transparent;
931
+ color: #c8c8d0;
932
+ font: 700 9px/1 ui-sans-serif, system-ui, sans-serif;
933
+ letter-spacing: .6px;
934
+ text-align: center;
935
+ cursor: pointer;
936
+ opacity: .85;
937
+ }
938
+ .vu-mode:hover { opacity: 1; color: #fff; }
939
+ .vu-channels {
940
+ display: flex;
941
+ align-items: flex-start;
942
+ gap: 2px;
943
+ }
944
+ .vu-scale {
945
+ position: relative;
946
+ /* Match .vu-segs height: 16×12px + 15×2px gap */
947
+ width: 16px;
948
+ height: 222px;
949
+ margin-right: 0px;
950
+ pointer-events: none;
951
+ }
952
+ .vu-scale-tick {
953
+ position: absolute;
954
+ right: 0;
955
+ transform: translateY(-50%);
956
+ font: 700 8px/1 ui-sans-serif, system-ui, sans-serif;
957
+ color: #8b8b93;
958
+ letter-spacing: .2px;
959
+ white-space: nowrap;
960
+ }
961
+ .vu-scale-tick:first-child { transform: translateY(0); }
962
+ .vu-scale-tick:last-child { transform: translateY(-100%); }
963
+ .vu-channel {
964
+ display: flex;
965
+ flex-direction: column;
966
+ align-items: center;
967
+ gap: 3px;
968
+ }
969
+ .vu-segs {
970
+ display: block;
971
+ /* size is set inline via JS (makeMeterCanvas) to match devicePixelRatio */
972
+ }
973
+ .vu-label {
974
+ font-size: 9px;
975
+ font-weight: 700;
976
+ color: #8b8b93;
977
+ letter-spacing: .3px;
978
+ line-height: 1;
979
+ }
980
+
981
+ .head-select {
982
+ background: var(--panel-2);
983
+ border: 1px solid var(--border);
984
+ color: var(--text);
985
+ border-radius: 5px;
986
+ padding: 2px 6px;
987
+ font: 12px "Segoe UI", sans-serif;
988
+ max-width: 170px;
989
+ }
990
+ #fpsSel.head-select { max-width: 88px; }
991
+
992
+ /* ── Safe-area guides (positioned over the canvas by JS) ── */
993
+ #safeOverlay {
994
+ position: absolute;
995
+ pointer-events: none;
996
+ z-index: 5;
997
+ }
998
+
999
+ #safeOverlay .sa-action {
1000
+ position: absolute;
1001
+ inset: 5%;
1002
+ border: 1px dashed #ffffff59;
1003
+ }
1004
+
1005
+ #safeOverlay .sa-title {
1006
+ position: absolute;
1007
+ inset: 10%;
1008
+ border: 1px dashed #ffffff30;
1009
+ }
1010
+
1011
+ #safeOverlay .sa-ui-bottom,
1012
+ #safeOverlay .sa-ui-right {
1013
+ display: none;
1014
+ }
1015
+
1016
+ #safeOverlay.vertical .sa-ui-bottom {
1017
+ display: block;
1018
+ position: absolute;
1019
+ left: 0;
1020
+ right: 0;
1021
+ bottom: 0;
1022
+ height: 34%;
1023
+ background: repeating-linear-gradient(45deg, #ff4d6a14 0 8px, transparent 8px 16px);
1024
+ border-top: 1px dashed #ff4d6a80;
1025
+ }
1026
+
1027
+ #safeOverlay.vertical .sa-ui-right {
1028
+ display: block;
1029
+ position: absolute;
1030
+ top: 30%;
1031
+ right: 0;
1032
+ bottom: 0;
1033
+ width: 13%;
1034
+ background: repeating-linear-gradient(45deg, #ff4d6a14 0 8px, transparent 8px 16px);
1035
+ border-left: 1px dashed #ff4d6a80;
1036
+ }
1037
+
1038
+ .transport {
1039
+ display: flex;
1040
+ align-items: center;
1041
+ justify-content: space-between;
1042
+ padding: 4px 14px 10px;
1043
+ gap: 12px;
1044
+ }
1045
+
1046
+ .transport-btns {
1047
+ display: flex;
1048
+ align-items: center;
1049
+ gap: 4px;
1050
+ }
1051
+
1052
+ .transport-btns .btn.icon {
1053
+ width: 26px;
1054
+ height: 26px;
1055
+ padding: 0;
1056
+ font-size: 11px;
1057
+ display: inline-flex;
1058
+ align-items: center;
1059
+ justify-content: center;
1060
+ line-height: 1;
1061
+ }
1062
+
1063
+ .transport-btns .btn.icon.big {
1064
+ width: 40px;
1065
+ height: 34px;
1066
+ font-size: 16px;
1067
+ }
1068
+
1069
+ #btnPlay.on {
1070
+ background: #7b6cff;
1071
+ border-color: #9a8fff;
1072
+ color: #fff;
1073
+ font-size: 19.2px; /* 16px × 1.2 — pause glyph reads smaller than ▶ */
1074
+ /* ⏸ sits low in the em-box; padding shifts the flex content up to optical center */
1075
+ padding-bottom: 3px;
1076
+ }
1077
+
1078
+ #btnPlay.on:hover {
1079
+ background: #8d80ff;
1080
+ border-color: #b0a6ff;
1081
+ }
1082
+
1083
+ .timecode {
1084
+ font: 600 14px/1 "Consolas", monospace;
1085
+ color: #b9b3ff;
1086
+ min-width: 86px;
1087
+ height: 14px;
1088
+ line-height: 14px;
1089
+ align-self: center;
1090
+ }
1091
+
1092
+ .timecode.dim {
1093
+ color: var(--dim);
1094
+ text-align: right;
1095
+ }
1096
+
1097
+ /* ── Inspector ── */
1098
+ .inspector-body {
1099
+ flex: 1;
1100
+ min-width: 0;
1101
+ overflow-x: hidden;
1102
+ overflow-y: auto;
1103
+ padding: 10px;
1104
+ }
1105
+
1106
+ .inspector-empty {
1107
+ margin: auto;
1108
+ text-align: center;
1109
+ color: var(--dim);
1110
+ padding-top: 40px;
1111
+ }
1112
+
1113
+ .insp-multi {
1114
+ margin-bottom: 12px;
1115
+ padding: 7px 9px;
1116
+ border-radius: 6px;
1117
+ font-size: 11px;
1118
+ color: #cfd0ff;
1119
+ background: #7b6cff1c;
1120
+ border: 1px solid #7b6cff44;
1121
+ }
1122
+
1123
+ .insp-section {
1124
+ margin-bottom: 14px;
1125
+ }
1126
+
1127
+ .insp-section h3 {
1128
+ font-size: 11px;
1129
+ text-transform: uppercase;
1130
+ letter-spacing: .5px;
1131
+ color: var(--dim);
1132
+ border-bottom: 1px solid var(--border);
1133
+ padding-bottom: 4px;
1134
+ margin-bottom: 8px;
1135
+ }
1136
+
1137
+ .insp-row {
1138
+ display: flex;
1139
+ align-items: center;
1140
+ gap: 8px;
1141
+ margin-bottom: 6px;
1142
+ min-width: 0;
1143
+ }
1144
+
1145
+ .insp-row label {
1146
+ flex: 0 0 72px;
1147
+ font-size: 12px;
1148
+ color: var(--dim);
1149
+ }
1150
+
1151
+ .insp-row label.insp-reset {
1152
+ cursor: help;
1153
+ }
1154
+
1155
+ .insp-row label.insp-reset:hover {
1156
+ color: #cfc8ff;
1157
+ }
1158
+
1159
+ .insp-ctrls {
1160
+ display: flex;
1161
+ flex: 1;
1162
+ min-width: 0;
1163
+ gap: 6px;
1164
+ align-items: center;
1165
+ }
1166
+
1167
+ .insp-ctrls select,
1168
+ .insp-ctrls input[type=number] {
1169
+ flex: 1;
1170
+ min-width: 0;
1171
+ }
1172
+
1173
+ .insp-ctrls .insp-dur {
1174
+ flex: none;
1175
+ width: 52px;
1176
+ }
1177
+
1178
+ .insp-ctrls input[type=color],
1179
+ .insp-ctrls .btn {
1180
+ flex: none;
1181
+ }
1182
+
1183
+ .insp-row input[type=range] {
1184
+ flex: 1;
1185
+ }
1186
+
1187
+ .insp-row .val {
1188
+ width: 42px;
1189
+ flex: none;
1190
+ text-align: right;
1191
+ font-size: 11px;
1192
+ color: var(--text);
1193
+ font-family: Consolas, monospace;
1194
+ }
1195
+
1196
+ .insp-row input[type=number],
1197
+ .insp-row input[type=text],
1198
+ .insp-row select {
1199
+ flex: 1;
1200
+ min-width: 0;
1201
+ background: var(--panel-2);
1202
+ border: 1px solid var(--border);
1203
+ color: var(--text);
1204
+ border-radius: 4px;
1205
+ padding: 4px 6px;
1206
+ font: inherit;
1207
+ }
1208
+
1209
+ .insp-row input[type=color] {
1210
+ width: 40px;
1211
+ height: 26px;
1212
+ padding: 0;
1213
+ border: 1px solid var(--border);
1214
+ border-radius: 4px;
1215
+ background: none;
1216
+ }
1217
+
1218
+ .insp-row textarea {
1219
+ flex: 1;
1220
+ background: var(--panel-2);
1221
+ border: 1px solid var(--border);
1222
+ color: var(--text);
1223
+ border-radius: 4px;
1224
+ padding: 4px 6px;
1225
+ font: inherit;
1226
+ resize: vertical;
1227
+ min-height: 48px;
1228
+ }
1229
+
1230
+ input[type=range] {
1231
+ accent-color: var(--accent);
1232
+ height: 18px;
1233
+ }
1234
+
1235
+ .kf-ctl {
1236
+ display: flex;
1237
+ gap: 2px;
1238
+ flex: none;
1239
+ }
1240
+
1241
+ .kf-btn {
1242
+ background: none;
1243
+ border: 1px solid var(--border);
1244
+ color: var(--dim);
1245
+ border-radius: 4px;
1246
+ font-size: 10px;
1247
+ padding: 2px 5px;
1248
+ cursor: pointer;
1249
+ line-height: 1;
1250
+ }
1251
+
1252
+ .kf-btn:hover {
1253
+ color: #fff;
1254
+ border-color: #4a4a56;
1255
+ }
1256
+
1257
+ .kf-btn.has {
1258
+ color: #ffd166;
1259
+ border-color: #ffd16666;
1260
+ }
1261
+
1262
+ /* ── Timeline ── */
1263
+ .thumbnail-progress {
1264
+ display: flex;
1265
+ align-items: center;
1266
+ gap: 6px;
1267
+ color: var(--dim);
1268
+ font-size: 11px;
1269
+ white-space: nowrap;
1270
+ }
1271
+ .thumbnail-progress[hidden] { display: none; }
1272
+ .thumbnail-progress progress { width: 64px; height: 5px; accent-color: var(--accent); }
1273
+ .timeline-toolbar {
1274
+ display: flex;
1275
+ flex-wrap: wrap;
1276
+ align-items: center;
1277
+ gap: 8px;
1278
+ padding: 6px 10px;
1279
+ border-bottom: 1px solid var(--border);
1280
+ }
1281
+
1282
+ .tiny-label {
1283
+ font-size: 11px;
1284
+ }
1285
+
1286
+ #zoomSlider {
1287
+ width: 130px;
1288
+ }
1289
+
1290
+ .timeline {
1291
+ flex: 1;
1292
+ display: flex;
1293
+ min-height: 0;
1294
+ }
1295
+
1296
+ .track-headers {
1297
+ width: 128px;
1298
+ flex: none;
1299
+ border-right: 1px solid var(--border);
1300
+ padding-top: 26px;
1301
+ background: var(--panel);
1302
+ z-index: 2;
1303
+ overflow: hidden;
1304
+ }
1305
+
1306
+ .track-head {
1307
+ display: flex;
1308
+ align-items: center;
1309
+ gap: 4px;
1310
+ min-width: 0;
1311
+ padding: 0 6px;
1312
+ border-bottom: 1px solid #232328;
1313
+ font-size: 11px;
1314
+ font-weight: 700;
1315
+ color: var(--dim);
1316
+ letter-spacing: .5px;
1317
+ }
1318
+
1319
+ .track-head.disabled {
1320
+ opacity: .55;
1321
+ }
1322
+
1323
+ .track-id {
1324
+ min-width: 0;
1325
+ overflow: hidden;
1326
+ white-space: nowrap;
1327
+ text-overflow: ellipsis;
1328
+ }
1329
+
1330
+ .track-toggle {
1331
+ display: inline-flex;
1332
+ align-items: center;
1333
+ justify-content: center;
1334
+ flex: none;
1335
+ margin: 0;
1336
+ padding: 2px;
1337
+ border: 0;
1338
+ background: transparent;
1339
+ cursor: pointer;
1340
+ border-radius: 4px;
1341
+ color: inherit;
1342
+ }
1343
+
1344
+ .track-toggle:hover {
1345
+ background: #ffffff12;
1346
+ }
1347
+
1348
+ .track-toggle .track-ico {
1349
+ display: block;
1350
+ width: 15px;
1351
+ height: 15px;
1352
+ pointer-events: none;
1353
+ }
1354
+
1355
+ .track-toggle .track-ico-off {
1356
+ display: none;
1357
+ }
1358
+
1359
+ .track-toggle[aria-pressed="false"] {
1360
+ color: var(--dim) !important;
1361
+ }
1362
+
1363
+ .track-toggle[aria-pressed="false"] .track-ico-off {
1364
+ display: block;
1365
+ }
1366
+
1367
+ .track.disabled {
1368
+ opacity: .4;
1369
+ }
1370
+
1371
+ .timeline-scroll {
1372
+ flex: 1;
1373
+ overflow-x: auto;
1374
+ overflow-y: auto;
1375
+ position: relative;
1376
+ }
1377
+
1378
+ .ruler {
1379
+ position: sticky;
1380
+ top: 0;
1381
+ left: 0;
1382
+ display: block;
1383
+ height: 26px;
1384
+ z-index: 3;
1385
+ cursor: ew-resize;
1386
+ background: var(--panel-2);
1387
+ }
1388
+
1389
+ .tracks-content {
1390
+ position: relative;
1391
+ }
1392
+ .work-dim {
1393
+ position: absolute;
1394
+ top: 0;
1395
+ bottom: 0;
1396
+ background: #00000066;
1397
+ pointer-events: none;
1398
+ z-index: 1;
1399
+ }
1400
+ .work-dim-l {
1401
+ left: 0;
1402
+ border-right: 1px solid #5eead4aa;
1403
+ }
1404
+ .work-dim-r {
1405
+ border-left: 1px solid #fb923caa;
1406
+ }
1407
+ .work-dim.hidden {
1408
+ display: none;
1409
+ }
1410
+
1411
+ .track {
1412
+ position: relative;
1413
+ border-bottom: 1px solid #232328;
1414
+ background: repeating-linear-gradient(90deg, transparent 0 59px, #ffffff05 59px 60px);
1415
+ }
1416
+
1417
+ .track.drop-hint {
1418
+ background-color: #7b6cff14;
1419
+ }
1420
+
1421
+ /* ── Clips ── */
1422
+ .clip {
1423
+ position: absolute;
1424
+ top: 3px;
1425
+ bottom: 3px;
1426
+ border-radius: 5px;
1427
+ overflow: visible;
1428
+ border: 1px solid #0007;
1429
+ cursor: grab;
1430
+ min-width: 8px;
1431
+ box-shadow: 0 1px 3px #0006;
1432
+ }
1433
+
1434
+ /* rounded clip content — trans wedges sit outside this so corners stay sharp */
1435
+ .clip-body {
1436
+ position: absolute;
1437
+ inset: 0;
1438
+ border-radius: inherit;
1439
+ overflow: hidden;
1440
+ }
1441
+
1442
+ .clip:active {
1443
+ cursor: grabbing;
1444
+ }
1445
+
1446
+ .clip.selected {
1447
+ outline: 2px solid #b9baff;
1448
+ outline-offset: -1px;
1449
+ box-shadow: 0 0 0 3px #7b6cff55;
1450
+ }
1451
+
1452
+ .clip.selected.primary {
1453
+ outline-color: #fff;
1454
+ }
1455
+
1456
+ /* rubber-band selection box drawn while dragging on empty timeline area */
1457
+ .marquee {
1458
+ position: absolute;
1459
+ z-index: 5;
1460
+ pointer-events: none;
1461
+ border: 1px solid #7b6cffcc;
1462
+ background: #7b6cff22;
1463
+ border-radius: 2px;
1464
+ }
1465
+
1466
+ .clip .clip-label {
1467
+ position: absolute;
1468
+ inset: 0;
1469
+ display: flex;
1470
+ align-items: center;
1471
+ padding: 0 8px;
1472
+ font-size: 11px;
1473
+ font-weight: 600;
1474
+ line-height: 1;
1475
+ color: #fff;
1476
+ text-shadow: 0 1px 2px #000c;
1477
+ white-space: nowrap;
1478
+ overflow: hidden;
1479
+ text-overflow: ellipsis;
1480
+ pointer-events: none;
1481
+ z-index: 3;
1482
+ }
1483
+
1484
+ /* Keyframe diamonds on the clip — same size/color as ruler beat markers */
1485
+ .clip .clip-kfs {
1486
+ position: absolute;
1487
+ left: 0;
1488
+ right: 0;
1489
+ bottom: 1px;
1490
+ height: 8px;
1491
+ pointer-events: none;
1492
+ z-index: 6;
1493
+ }
1494
+ .clip .clip-kf {
1495
+ position: absolute;
1496
+ top: 0;
1497
+ /* rotated square → ~8×8 tip-to-tip, matching ruler markers */
1498
+ width: 6px;
1499
+ height: 6px;
1500
+ margin-left: -3px;
1501
+ background: #ffd166;
1502
+ transform: rotate(45deg);
1503
+ pointer-events: auto;
1504
+ cursor: pointer;
1505
+ }
1506
+ .clip .clip-kf:hover {
1507
+ background: #ffe28a;
1508
+ }
1509
+ /* Count badge when ≥2 channels share this time (diamond stays rotated; numeral counter-rotates) */
1510
+ .clip .clip-kf.multi {
1511
+ width: 8px;
1512
+ height: 8px;
1513
+ margin-left: -4px;
1514
+ top: -1px;
1515
+ }
1516
+ .clip .clip-kf-n {
1517
+ position: absolute;
1518
+ inset: 0;
1519
+ display: flex;
1520
+ align-items: center;
1521
+ justify-content: center;
1522
+ transform: rotate(-45deg);
1523
+ font: 700 7px/1 ui-sans-serif, system-ui, sans-serif;
1524
+ color: #1a1a1e;
1525
+ pointer-events: none;
1526
+ user-select: none;
1527
+ }
1528
+ body.track-size-s .clip .clip-kf-n {
1529
+ font-size: 6px;
1530
+ }
1531
+
1532
+ /* transition wedges — width from transition duration × pps (see transitionMarksHtml) */
1533
+ .clip .trans-mark {
1534
+ position: absolute;
1535
+ top: 0;
1536
+ bottom: 0;
1537
+ height: auto;
1538
+ pointer-events: none;
1539
+ z-index: 5;
1540
+ overflow: hidden;
1541
+ }
1542
+ .clip .trans-mark svg {
1543
+ display: block;
1544
+ width: 100%;
1545
+ height: 100%;
1546
+ pointer-events: none;
1547
+ }
1548
+ .clip .trans-mark.in {
1549
+ left: 0;
1550
+ border-top-left-radius: inherit;
1551
+ border-bottom-left-radius: inherit;
1552
+ }
1553
+ .clip .trans-mark.out {
1554
+ right: 0;
1555
+ border-top-right-radius: inherit;
1556
+ border-bottom-right-radius: inherit;
1557
+ }
1558
+ .clip .trans-mark polygon {
1559
+ fill: #ffffff55;
1560
+ stroke: #ffffffcc;
1561
+ stroke-width: 1;
1562
+ vector-effect: non-scaling-stroke;
1563
+ pointer-events: auto;
1564
+ cursor: pointer;
1565
+ }
1566
+ .clip .trans-mark.focused polygon {
1567
+ fill: #7b6cff88;
1568
+ stroke: #cfc8ff;
1569
+ stroke-width: 1.5;
1570
+ }
1571
+ /* duration handle — invisible drag strip at the wedge edge */
1572
+ .clip .trans-dur-handle {
1573
+ position: absolute;
1574
+ top: 0;
1575
+ bottom: 0;
1576
+ width: 10px;
1577
+ cursor: ew-resize;
1578
+ pointer-events: auto;
1579
+ z-index: 3;
1580
+ }
1581
+ .clip .trans-mark.in .trans-dur-handle {
1582
+ right: 0;
1583
+ }
1584
+ .clip .trans-mark.out .trans-dur-handle {
1585
+ left: 0;
1586
+ }
1587
+
1588
+ .insp-row.trans-active {
1589
+ background: #7b6cff18;
1590
+ border-radius: 6px;
1591
+ margin: 0 -6px;
1592
+ padding: 2px 6px;
1593
+ }
1594
+
1595
+ .clip .fade {
1596
+ position: absolute;
1597
+ inset: 0;
1598
+ background: linear-gradient(180deg, #ffffff1f, transparent 40%);
1599
+ pointer-events: none;
1600
+ z-index: 0;
1601
+ }
1602
+
1603
+ .clip .handle {
1604
+ position: absolute;
1605
+ top: 0;
1606
+ bottom: 0;
1607
+ width: 8px;
1608
+ max-width: 25%;
1609
+ cursor: ew-resize;
1610
+ z-index: 7;
1611
+ }
1612
+
1613
+ .clip .handle.l {
1614
+ left: 0;
1615
+ box-shadow: inset 3px 0 #ffffff55;
1616
+ }
1617
+
1618
+ .clip .handle.r {
1619
+ right: 0;
1620
+ box-shadow: inset -3px 0 #ffffff55;
1621
+ }
1622
+
1623
+ .clip:hover .handle.l, .clip.selected .handle.l { box-shadow: inset 3px 0 #cfc8ff; }
1624
+ .clip:hover .handle.r, .clip.selected .handle.r { box-shadow: inset -3px 0 #cfc8ff; }
1625
+ .clip .handle.trim-hover { background: #cfc8ff88; box-shadow: inset 0 0 0 1px #fff; }
1626
+ .tracks-content[data-gesture="trim-l"] .clip.primary .handle.l,
1627
+ .tracks-content[data-gesture="trim-r"] .clip.primary .handle.r { background: #cfc8ff88; }
1628
+ .timeline-gesture-hint {
1629
+ position: fixed;
1630
+ z-index: 210;
1631
+ pointer-events: none;
1632
+ max-width: min(420px, calc(100vw - 16px));
1633
+ padding: 8px 12px;
1634
+ border: 1px solid #6ee7b7;
1635
+ border-radius: 6px;
1636
+ background: #17171cf2;
1637
+ color: #e8e8ee;
1638
+ box-shadow: 0 4px 18px #0006;
1639
+ font-size: 12px;
1640
+ line-height: 1.6;
1641
+ white-space: pre-line;
1642
+ font-variant-numeric: tabular-nums;
1643
+ }
1644
+ .timeline-gesture-hint.limited { border-color: #fbbf24; }
1645
+ .timeline-menu { width: min(300px, calc(100vw - 16px)); max-height: calc(100vh - 16px); overflow: auto; }
1646
+ .timeline-menu-heading { padding: 7px 10px; color: var(--dim); font-size: 11px; border-bottom: 1px solid var(--border); }
1647
+ .timeline-menu .ctx-opt {
1648
+ display: grid;
1649
+ grid-template-columns: 1fr auto;
1650
+ gap: 3px 12px;
1651
+ width: 100%;
1652
+ border: 0;
1653
+ background: transparent;
1654
+ text-align: left;
1655
+ font: inherit;
1656
+ font-size: 12px;
1657
+ white-space: normal;
1658
+ }
1659
+ .timeline-menu .ctx-opt kbd { color: var(--dim); font: inherit; }
1660
+ .timeline-menu .ctx-opt small { grid-column: 1 / -1; color: var(--dim); font-size: 10px; }
1661
+ .timeline-menu .ctx-opt:hover:not(:disabled), .timeline-menu .ctx-opt:focus-visible { background: #7b6cff26; outline: 1px solid #7b6cff77; }
1662
+ .timeline-menu .ctx-opt:disabled { opacity: .5; cursor: default; }
1663
+ .timeline-gap-preview { position: absolute; background: #fbbf242b; border-inline: 1px dashed #fbbf24; pointer-events: none; z-index: 5; }
1664
+ .timeline-zoom-controls { display: flex; align-items: center; gap: 8px; margin-left: auto; }
1665
+ .timeline-toolbar .zoom-step { min-width: 24px; padding: 2px 5px; }
1666
+ @media (max-width: 700px) {
1667
+ .timeline-toolbar #zoomSlider { width: 70px; }
1668
+ }
1669
+
1670
+ .clip.c-video .clip-body {
1671
+ background: var(--clip-video);
1672
+ }
1673
+
1674
+ .clip-thumb-strip {
1675
+ position: absolute;
1676
+ inset: 0;
1677
+ /* 整条胶片统一透明度,重叠边缘不会因为重复叠加而变亮。 */
1678
+ opacity: .88;
1679
+ pointer-events: none;
1680
+ }
1681
+
1682
+ .clip.c-video .thumbs, .drop-ghost.c-video .thumbs {
1683
+ position: absolute;
1684
+ top: 0;
1685
+ bottom: 0;
1686
+ background-repeat: no-repeat;
1687
+ /* 等比填满每格,避免轨道边框和缩略图尺寸取整在拼接处露出底色。 */
1688
+ background-size: cover;
1689
+ background-position: center;
1690
+ pointer-events: none;
1691
+ }
1692
+
1693
+ .clip.c-image .clip-body {
1694
+ background: linear-gradient(180deg, #2dbd8533, #2dbd8511), #1d5b45;
1695
+ }
1696
+
1697
+ .clip.c-audio .clip-body {
1698
+ background: linear-gradient(180deg, #7ec24933, #7ec24911), #33531f;
1699
+ }
1700
+
1701
+ .clip.c-audio .clip-body::after {
1702
+ content: "";
1703
+ position: absolute;
1704
+ left: 0;
1705
+ right: 0;
1706
+ top: 50%;
1707
+ height: 22px;
1708
+ transform: translateY(-50%);
1709
+ background: repeating-linear-gradient(90deg, #a5e07588 0 2px, transparent 2px 5px);
1710
+ clip-path: polygon(0 50%, 5% 20%, 10% 70%, 15% 35%, 20% 80%, 25% 25%, 30% 60%, 35% 15%, 40% 75%, 45% 40%, 50% 85%, 55% 30%, 60% 65%, 65% 20%, 70% 78%, 75% 42%, 80% 68%, 85% 25%, 90% 72%, 95% 38%, 100% 50%, 100% 100%, 0 100%);
1711
+ opacity: .55;
1712
+ pointer-events: none;
1713
+ }
1714
+
1715
+ .clip.c-audio.has-wave .clip-body::after {
1716
+ display: none;
1717
+ }
1718
+
1719
+ /* real waveform replaces the CSS placeholder */
1720
+ .clip .wave {
1721
+ position: absolute;
1722
+ inset: 3px 0;
1723
+ width: 100%;
1724
+ height: calc(100% - 6px);
1725
+ pointer-events: none;
1726
+ }
1727
+
1728
+ .clip.c-text .clip-body {
1729
+ background: linear-gradient(180deg, #ff7ac833, #ff7ac811), #6b2a53;
1730
+ }
1731
+
1732
+ .clip.c-svg .clip-body {
1733
+ background: linear-gradient(180deg, #ffd16633, #ffd16611), #6b5420;
1734
+ }
1735
+
1736
+ .clip.c-adjust .clip-body {
1737
+ background: repeating-linear-gradient(135deg, #38bdf822 0 10px, transparent 10px 20px), #155e75;
1738
+ }
1739
+
1740
+ /* ── Playhead ── */
1741
+ .playhead {
1742
+ position: absolute;
1743
+ top: 0;
1744
+ bottom: 0;
1745
+ width: 1px;
1746
+ background: #ff4d6a;
1747
+ z-index: 4;
1748
+ cursor: ew-resize;
1749
+ touch-action: none;
1750
+ }
1751
+
1752
+ .playhead::before {
1753
+ content: "";
1754
+ position: absolute;
1755
+ top: 0;
1756
+ bottom: 0;
1757
+ left: -5px;
1758
+ right: -5px;
1759
+ }
1760
+
1761
+ .playhead-cap {
1762
+ position: absolute;
1763
+ top: 0;
1764
+ left: -6px;
1765
+ width: 13px;
1766
+ height: 14px;
1767
+ background: #ff4d6a;
1768
+ clip-path: polygon(0 0, 100% 0, 100% 55%, 50% 100%, 0 55%);
1769
+ }
1770
+
1771
+ /* ── Overlays / dialogs ── */
1772
+ .project-load-dialog { margin: auto; max-width: min(440px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); box-sizing: border-box; color: var(--text); overflow: auto; }
1773
+ .project-load-dialog::backdrop { background: #000b; }
1774
+ .project-load-dialog p { line-height: 1.7; overflow-wrap: anywhere; }
1775
+ .project-load-dialog h2 { color: #ffaaa4; }
1776
+ .project-load-dialog .project-load-id, .project-load-dialog details { font-size: 12px; color: var(--dim); }
1777
+ .overlay {
1778
+ position: fixed;
1779
+ inset: 0;
1780
+ background: #000a;
1781
+ backdrop-filter: blur(3px);
1782
+ display: flex;
1783
+ align-items: center;
1784
+ justify-content: center;
1785
+ z-index: 50;
1786
+ }
1787
+
1788
+ .dialog {
1789
+ background: var(--panel);
1790
+ border: 1px solid var(--border);
1791
+ border-radius: 12px;
1792
+ padding: 24px 28px;
1793
+ width: 420px;
1794
+ box-shadow: 0 20px 60px #000a;
1795
+ }
1796
+
1797
+ .dialog h2 {
1798
+ font-size: 16px;
1799
+ margin-bottom: 6px;
1800
+ color: #fff;
1801
+ }
1802
+
1803
+ .dialog p {
1804
+ margin-bottom: 16px;
1805
+ }
1806
+
1807
+ .progress {
1808
+ height: 8px;
1809
+ border-radius: 4px;
1810
+ background: var(--panel-2);
1811
+ overflow: hidden;
1812
+ margin-bottom: 18px;
1813
+ }
1814
+
1815
+ .progress-fill {
1816
+ height: 100%;
1817
+ width: 0%;
1818
+ background: linear-gradient(90deg, var(--accent), var(--accent-2));
1819
+ transition: width .2s;
1820
+ }
1821
+
1822
+ .dialog-actions {
1823
+ display: flex;
1824
+ justify-content: flex-end;
1825
+ gap: 8px;
1826
+ }
1827
+
1828
+ .export-dialog { width: min(526px, calc(100vw - 32px)); max-height: calc(100dvh - 32px); padding: 0; overflow: auto; border-radius: 20px; background: #1e2028; border-color: #30333f; color: #e8e9ef; }
1829
+ .export-header { display: flex; align-items: flex-start; gap: 12px; padding: 20px 24px 18px; border-bottom: 1px solid #2b2e38; }
1830
+ .export-header-icon { flex: none; color: #5868ff; margin-top: 1px; }
1831
+ .export-heading { min-width: 0; flex: 1; }
1832
+ .export-heading h2 { font-size: 17px; line-height: 1.45; margin: 0 0 4px; color: #e8e9ef; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1833
+ .export-heading p { color: #969bac; font-size: 14px; line-height: 1.5; margin: 0; }
1834
+ .export-close { flex: none; border: 0; background: none; color: #969bac; cursor: pointer; font-size: 27px; line-height: 28px; width: 32px; height: 32px; margin: 6px -6px 0 0; border-radius: 6px; }
1835
+ .export-close:hover { color: #fff; background: #ffffff0d; }
1836
+ .export-body { display: flex; justify-content: center; padding: 26px 24px 38px; }
1837
+ .export-preview { position: relative; width: min(100%, var(--export-preview-width, 224px)); aspect-ratio: var(--export-aspect, 9 / 16); border-radius: 14px; overflow: hidden; background: #111218; }
1838
+ .export-preview video { width: 100%; height: 100%; display: block; object-fit: contain; }
1839
+ .export-play { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; border: 0; background: #1c1512bb; color: #fff; cursor: pointer; }
1840
+ .export-play:disabled { cursor: default; opacity: .8; }
1841
+ .export-play svg { margin-left: 3px; }
1842
+ .export-time { position: absolute; right: 10px; bottom: 10px; padding: 5px 10px; border-radius: 7px; background: #1a1616c9; color: #fff; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
1843
+ .export-footer { padding: 0 25px 22px; }
1844
+ .export-status-row { display: flex; gap: 9px; align-items: center; margin-bottom: 11px; font-size: 14px; line-height: 1.5; }
1845
+ #exportNote { flex: 1; min-width: 0; color: #9ca1b3; overflow-wrap: anywhere; }
1846
+ #exportPercent { font-size: 14px; font-variant-numeric: tabular-nums; flex: none; margin-left: 10px; }
1847
+ .export-status-icon { width: 16px; height: 16px; border: 2px solid #353b50; border-right-color: #6573ff; border-radius: 50%; flex: none; animation: export-spin 1s linear infinite; }
1848
+ .export-footer .progress { margin: 0; background: #2b2e39; height: 8px; }
1849
+ .export-footer .progress-fill { background: linear-gradient(90deg, #4f6bff, #9258f7); }
1850
+ #exportOverlay[data-status="complete"] #exportNote { color: #4ed7a2; }
1851
+ #exportOverlay[data-status="complete"] .export-status-icon { animation: none; border-color: #4ed7a2; position: relative; }
1852
+ #exportOverlay[data-status="complete"] .export-status-icon::after { content: ""; position: absolute; width: 6px; height: 3px; border-left: 1.5px solid #4ed7a2; border-bottom: 1.5px solid #4ed7a2; transform: rotate(-45deg); left: 3px; top: 3px; }
1853
+ #exportOverlay[data-status="error"] #exportNote, #exportOverlay[data-status="error"] #exportPercent { color: #ff7373; }
1854
+ #exportOverlay[data-status="error"] .export-status-icon { animation: none; border-color: #ff7373; color: #ff7373; position: relative; }
1855
+ #exportOverlay[data-status="error"] .export-status-icon::after { content: "!"; position: absolute; inset: 0; text-align: center; font-size: 11px; line-height: 12px; font-weight: 700; }
1856
+ #exportOverlay[data-status="error"] .progress-fill { background: linear-gradient(90deg, #ff6b6b, #ff9460); }
1857
+ .export-recovery .dialog-actions:has(button:not([hidden])) { margin-top: 12px; flex-wrap: wrap; }
1858
+ .export-recovery .export-quick { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 43px; border: 0; border-radius: 11px; background: linear-gradient(90deg, #4f6bff, #7055f5); color: #fff; font-size: 14px; font-weight: 600; box-shadow: 0 6px 18px #4f6bff33; }
1859
+ .export-recovery .export-quick:hover { filter: brightness(1.08); }
1860
+ .export-recovery .export-quick:disabled { cursor: wait; opacity: .65; filter: none; }
1861
+ .export-save-note { margin: 12px 0 0; color: #9ca1b3; font-size: 12px; line-height: 1.5; overflow-wrap: anywhere; }
1862
+ .export-save-note.error { color: #ff7373; }
1863
+ .export-dialog [hidden] { display: none !important; }
1864
+ .export-dialog button:focus-visible { outline: 2px solid #9b92ff; outline-offset: 3px; }
1865
+ .export-dialog .export-track-warn { margin: 14px 0 0; }
1866
+ .export-cancel-dialog { margin: auto; width: min(420px, calc(100vw - 32px)); color: var(--text); }
1867
+ .export-cancel-dialog::backdrop { background: #0009; }
1868
+ .export-cancel-dialog p { color: var(--dim); line-height: 1.6; }
1869
+ .btn.export-cancel-confirm { color: #fff; background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: transparent; transition: filter .15s ease; }
1870
+ .btn.export-cancel-confirm:hover { filter: brightness(1.05); }
1871
+ .export-cancel-dialog button:focus-visible { outline: 2px solid #9b92ff; outline-offset: 3px; }
1872
+ @keyframes export-spin { to { transform: rotate(360deg); } }
1873
+ @media (prefers-reduced-motion: reduce) { .export-status-icon { animation: none; } .export-footer .progress-fill { transition: none; } }
1874
+ @media (max-width: 420px), (max-height: 600px) {
1875
+ .export-header { padding: 16px; gap: 9px; }
1876
+ .export-heading h2 { font-size: 15px; }
1877
+ .export-heading p { font-size: 12px; }
1878
+ .export-body { padding: 18px 16px 24px; }
1879
+ .export-footer { padding: 0 16px 18px; }
1880
+ .export-status-row { font-size: 12px; }
1881
+ }
1882
+
1883
+ .export-track-warn {
1884
+ margin: 0 0 12px;
1885
+ padding: 9px 12px;
1886
+ border: 1px solid #8a6a28;
1887
+ border-radius: 8px;
1888
+ background: #3a2e12;
1889
+ color: #f0c14a;
1890
+ font-size: 12px;
1891
+ line-height: 1.4;
1892
+ }
1893
+
1894
+ .export-track-warn.hidden {
1895
+ display: none;
1896
+ }
1897
+
1898
+ .dialog.help {
1899
+ width: min(820px, 94vw);
1900
+ max-height: min(90vh, 640px);
1901
+ overflow: auto;
1902
+ }
1903
+
1904
+ .dialog.settings {
1905
+ width: min(440px, 92vw);
1906
+ max-height: 90vh;
1907
+ overflow: auto;
1908
+ }
1909
+
1910
+ .dialog.settings .settings-intro {
1911
+ margin-bottom: 14px;
1912
+ font-size: 12px;
1913
+ }
1914
+
1915
+ .dialog.settings .settings-section h3 {
1916
+ font-size: 11px;
1917
+ font-weight: 700;
1918
+ letter-spacing: .4px;
1919
+ text-transform: uppercase;
1920
+ color: var(--dim);
1921
+ margin: 0 0 8px;
1922
+ }
1923
+
1924
+ .settings-row {
1925
+ display: flex;
1926
+ gap: 10px;
1927
+ align-items: flex-start;
1928
+ padding: 10px 12px;
1929
+ margin-bottom: 8px;
1930
+ border: 1px solid var(--border);
1931
+ border-radius: 8px;
1932
+ cursor: pointer;
1933
+ background: var(--panel-2);
1934
+ }
1935
+
1936
+ .settings-row:hover {
1937
+ border-color: #454552;
1938
+ }
1939
+
1940
+ .settings-row input {
1941
+ margin-top: 2px;
1942
+ flex: none;
1943
+ }
1944
+
1945
+ .language-row {
1946
+ align-items: center;
1947
+ justify-content: space-between;
1948
+ }
1949
+
1950
+ .language-row .settings-label {
1951
+ margin: 0;
1952
+ }
1953
+
1954
+ .language-row select {
1955
+ min-width: 120px;
1956
+ padding: 5px 8px;
1957
+ color: var(--text);
1958
+ background: var(--panel);
1959
+ border: 1px solid var(--border);
1960
+ border-radius: 4px;
1961
+ }
1962
+
1963
+ .settings-label {
1964
+ display: block;
1965
+ color: #e8e8ec;
1966
+ font-size: 13px;
1967
+ font-weight: 600;
1968
+ margin-bottom: 4px;
1969
+ }
1970
+
1971
+ .settings-hint {
1972
+ display: block;
1973
+ font-size: 12px;
1974
+ color: var(--dim);
1975
+ line-height: 1.35;
1976
+ }
1977
+
1978
+ #btnSettings {
1979
+ display: inline-flex;
1980
+ align-items: center;
1981
+ justify-content: center;
1982
+ width: 34px;
1983
+ padding: 6px 0;
1984
+ }
1985
+
1986
+ #btnSettings .ico {
1987
+ margin: 0;
1988
+ vertical-align: 0;
1989
+ }
1990
+
1991
+ .dialog.help .keys-cols {
1992
+ display: grid;
1993
+ grid-template-columns: 1fr 1fr;
1994
+ gap: 0 28px;
1995
+ margin-bottom: 12px;
1996
+ align-items: start;
1997
+ }
1998
+
1999
+ .dialog.help .keys {
2000
+ width: 100%;
2001
+ border-collapse: collapse;
2002
+ margin-bottom: 0;
2003
+ }
2004
+
2005
+ .dialog.help .keys td {
2006
+ padding: 5px 6px;
2007
+ border-bottom: 1px solid #26262c;
2008
+ font-size: 12px;
2009
+ vertical-align: top;
2010
+ }
2011
+
2012
+ .dialog.help .keys td:first-child {
2013
+ width: 40%;
2014
+ color: var(--dim);
2015
+ white-space: nowrap;
2016
+ }
2017
+
2018
+ @media (max-width: 700px) {
2019
+ .dialog.help .keys-cols {
2020
+ grid-template-columns: 1fr;
2021
+ }
2022
+ }
2023
+
2024
+ kbd {
2025
+ background: var(--panel-2);
2026
+ border: 1px solid var(--border);
2027
+ border-bottom-width: 2px;
2028
+ border-radius: 4px;
2029
+ padding: 1px 6px;
2030
+ font: 11px Consolas, monospace;
2031
+ color: #fff;
2032
+ }
2033
+
2034
+ /* ── Scrollbars ── */
2035
+ ::-webkit-scrollbar {
2036
+ width: 10px;
2037
+ height: 10px;
2038
+ }
2039
+
2040
+ ::-webkit-scrollbar-thumb {
2041
+ background: #35353e;
2042
+ border-radius: 5px;
2043
+ border: 2px solid var(--panel);
2044
+ }
2045
+
2046
+ ::-webkit-scrollbar-track {
2047
+ background: transparent;
2048
+ }
2049
+
2050
+ /* ── Toast ── */
2051
+ #toast {
2052
+ position: fixed;
2053
+ left: 50%;
2054
+ bottom: 26px;
2055
+ transform: translate(-50%, 20px);
2056
+ background: var(--panel-2);
2057
+ border: 1px solid var(--border);
2058
+ color: var(--text);
2059
+ padding: 9px 16px;
2060
+ border-radius: 8px;
2061
+ font-size: 12px;
2062
+ box-shadow: 0 8px 30px #000a;
2063
+ opacity: 0;
2064
+ pointer-events: none;
2065
+ transition: opacity .25s, transform .25s;
2066
+ z-index: 80;
2067
+ max-width: 60vw;
2068
+ }
2069
+
2070
+ #toast.show {
2071
+ opacity: 1;
2072
+ transform: translate(-50%, 0);
2073
+ }
2074
+
2075
+ /* ── Inspector checkboxes ── */
2076
+ .insp-row input[type=checkbox] {
2077
+ width: 15px;
2078
+ height: 15px;
2079
+ accent-color: var(--accent);
2080
+ flex: none;
2081
+ }
2082
+
2083
+ /* ── Drop highlight ── */
2084
+ body.file-drag::after {
2085
+ content: "Drop files to import";
2086
+ position: fixed;
2087
+ inset: 10px;
2088
+ border: 2px dashed var(--accent);
2089
+ border-radius: 14px;
2090
+ background: #7b6cff14;
2091
+ color: #cfc8ff;
2092
+ font-size: 18px;
2093
+ font-weight: 600;
2094
+ display: flex;
2095
+ align-items: center;
2096
+ justify-content: center;
2097
+ z-index: 99;
2098
+ pointer-events: none;
2099
+ }
2100
+
2101
+ /* Font-family previews use real DOM options instead of an OS-native popup. */
2102
+ .font-menu { box-sizing: border-box; }
2103
+ .font-group-label { padding: 7px 10px 4px; font-size: 11px; color: var(--dim); }
2104
+ .font-opt { overflow: hidden; text-overflow: ellipsis; font-size: 18px; line-height: 1.5; }
2105
+ .font-opt.active { outline: 1px solid #7b6cff88; outline-offset: -1px; background: #7b6cff26; }
2106
+
2107
+ /* Prospective drops remain outside the track DOM until the gesture commits. */
2108
+ .timeline-empty { height: 64px; padding: 20px; color: var(--muted); box-sizing: border-box; }
2109
+ .tracks-content { min-height: 100%; padding-bottom: 24px; box-sizing: border-box; }
2110
+ .drop-preview { position: absolute; left: 0; right: 0; pointer-events: none; z-index: 6; box-sizing: border-box; }
2111
+ .drop-preview.new-track { border-top: 1px dashed #6ee7b7; border-bottom: 1px dashed #6ee7b7; background: #6ee7b714; }
2112
+ .drop-ghost { position: absolute; top: 2px; bottom: 2px; border: 1px solid #6ee7b7; background: #6ee7b72b; border-radius: 4px; color: #a7f3d0; font-size: 11px; padding: 0 5px; box-sizing: border-box; overflow: hidden; white-space: nowrap; }
2113
+ .drop-thumb-strip { position: absolute; inset: 0; background: var(--clip-video); }
2114
+ .drop-ghost-label { position: relative; z-index: 1; background: #17171ccc; text-shadow: 0 1px 2px #000; }
2115
+ .drag-origin { opacity: .15; }
2116
+ .drop-preview.moving .drop-ghost { top: 0; bottom: 0; border: 2px solid #eeeaff; background: #423d64; box-shadow: 0 0 0 2px #8b7bff, 0 8px 18px #000b; transform: translateY(-3px); opacity: 1; }
2117
+ .drop-preview.moving .clip-thumb-strip { opacity: 1; }
2118
+ .drop-preview.moving .drop-ghost-label { display: inline-block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; border-radius: 3px; padding: 1px 4px; box-sizing: border-box; color: #fff; font-weight: 600; }
2119
+ .drop-slot { position: absolute; top: 2px; bottom: 2px; border: 1px dashed #a99fff; border-radius: 4px; background: #7b6cff14; box-sizing: border-box; }
2120
+ .drop-insertion { position: absolute; top: 0; bottom: 0; width: 3px; margin-left: -1px; background: #b1a7ff; box-shadow: 0 0 5px #7b6cff88; z-index: 2; }
2121
+ .drop-insertion::before, .drop-insertion::after { content: ""; position: absolute; left: -2px; width: 7px; height: 3px; border-radius: 1px; background: inherit; }
2122
+ .drop-insertion::before { top: 0; }
2123
+ .drop-insertion::after { bottom: 0; }
2124
+ .reorder-preview { transition: transform 240ms cubic-bezier(.25, .1, .25, 1); }
2125
+ .tracks-content[data-gesture="move"], .tracks-content[data-gesture="move"] .clip { cursor: grabbing; }
2126
+ @media (prefers-reduced-motion: reduce) { .reorder-preview { transition: none; } }