@ashraf_mizo/htmlcanvas 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1996 @@
1
+ /* ── HTMLCanvas editor styles ── */
2
+
3
+ *, *::before, *::after {
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ :root {
8
+ --toolbar-h: 48px;
9
+ --sidebar-w: clamp(240px, 18vw, 400px);
10
+ --sidebar-collapsed-w: 0px;
11
+ --bg-workspace: #141414;
12
+ --bg-panel: #1c1c1e;
13
+ --bg-toolbar: #1c1c1e;
14
+ --border-panel: #2a2a2e;
15
+ --text-muted: rgba(255, 255, 255, 0.4);
16
+ --text-primary: rgba(255, 255, 255, 0.88);
17
+ --accent: #E87420;
18
+ --accent-hover: #d06519;
19
+ --accent-blue: #2C4685;
20
+ --accent-purple: #7c3aed;
21
+ }
22
+
23
+ html, body {
24
+ margin: 0;
25
+ padding: 0;
26
+ height: 100%;
27
+ font-family: 'DM Sans', system-ui, sans-serif;
28
+ background: var(--bg-workspace);
29
+ color: var(--text-primary);
30
+ overflow: hidden;
31
+ }
32
+
33
+ /* ── Layout grid ─────────────────────────────────────────────────────────── */
34
+
35
+ .editor-layout {
36
+ display: grid;
37
+ grid-template-rows: var(--toolbar-h) 1fr;
38
+ grid-template-columns: var(--sidebar-w) 1fr var(--sidebar-w);
39
+ width: 100%;
40
+ height: 100vh;
41
+ overflow: hidden;
42
+ }
43
+
44
+ /* Collapsed states */
45
+ .editor-layout.left-collapsed {
46
+ grid-template-columns: var(--sidebar-collapsed-w) 1fr var(--sidebar-w);
47
+ }
48
+ .editor-layout.right-collapsed {
49
+ grid-template-columns: var(--sidebar-w) 1fr var(--sidebar-collapsed-w);
50
+ }
51
+ .editor-layout.left-collapsed.right-collapsed {
52
+ grid-template-columns: var(--sidebar-collapsed-w) 1fr var(--sidebar-collapsed-w);
53
+ }
54
+
55
+ /* ── Toolbar ─────────────────────────────────────────────────────────────── */
56
+
57
+ .toolbar {
58
+ grid-column: 1 / -1;
59
+ grid-row: 1;
60
+ background: var(--bg-toolbar);
61
+ border-bottom: 1px solid var(--border-panel);
62
+ display: flex;
63
+ align-items: center;
64
+ padding: 0 16px;
65
+ gap: 12px;
66
+ user-select: none;
67
+ box-shadow: 0 1px 8px rgba(0, 0, 0, 0.3);
68
+ z-index: 5;
69
+ overflow-x: auto;
70
+ overflow-y: hidden;
71
+ min-width: 0;
72
+ position: relative;
73
+ }
74
+
75
+ /* Extend toolbar background beyond max-width grid on wide viewports */
76
+ .toolbar::after {
77
+ content: '';
78
+ position: absolute;
79
+ top: 0;
80
+ left: 100%;
81
+ width: 100vw;
82
+ height: 100%;
83
+ background: var(--bg-toolbar);
84
+ border-bottom: 1px solid var(--border-panel);
85
+ pointer-events: none;
86
+ }
87
+
88
+
89
+ /* Hide toolbar scrollbar but keep it scrollable */
90
+ .toolbar::-webkit-scrollbar { height: 0; }
91
+ .toolbar { scrollbar-width: none; }
92
+
93
+ .toolbar-wordmark {
94
+ flex-shrink: 0;
95
+ display: flex;
96
+ align-items: center;
97
+ }
98
+
99
+ .toolbar-logo {
100
+ flex-shrink: 0;
101
+ height: 28px;
102
+ width: auto;
103
+ }
104
+
105
+ .wordmark-dot {
106
+ color: var(--accent);
107
+ }
108
+
109
+ .toolbar-separator {
110
+ width: 1px;
111
+ height: 20px;
112
+ background: var(--border-panel);
113
+ flex-shrink: 0;
114
+ }
115
+
116
+ #current-filename {
117
+ font-size: 13px;
118
+ color: var(--text-muted);
119
+ flex: 1;
120
+ min-width: 40px;
121
+ white-space: nowrap;
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ }
125
+
126
+ .toolbar-actions {
127
+ display: flex;
128
+ align-items: center;
129
+ gap: 8px;
130
+ flex-shrink: 0;
131
+ }
132
+
133
+ .btn-toolbar {
134
+ padding: 5px 12px;
135
+ border-radius: 5px;
136
+ font-size: 12px;
137
+ font-weight: 500;
138
+ cursor: pointer;
139
+ border: none;
140
+ transition: background 0.15s, opacity 0.15s;
141
+ }
142
+
143
+ .btn-toolbar.btn-icon {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ width: 30px;
148
+ height: 30px;
149
+ padding: 0;
150
+ background: transparent;
151
+ color: var(--text-muted);
152
+ border: 1px solid var(--border-panel);
153
+ border-radius: 5px;
154
+ }
155
+
156
+ .btn-toolbar.btn-icon:hover {
157
+ background: rgba(255, 255, 255, 0.08);
158
+ color: var(--text-primary);
159
+ }
160
+
161
+ .toolbar-history {
162
+ display: flex;
163
+ gap: 4px;
164
+ flex-shrink: 0;
165
+ }
166
+
167
+ #btn-save {
168
+ background: var(--accent);
169
+ color: #fff;
170
+ }
171
+
172
+ #btn-save:hover {
173
+ background: var(--accent-hover);
174
+ }
175
+
176
+ #btn-save:disabled {
177
+ opacity: 0.4;
178
+ cursor: default;
179
+ }
180
+
181
+ #btn-export {
182
+ background: transparent;
183
+ border: 1px solid var(--border-panel);
184
+ color: var(--text-primary);
185
+ }
186
+
187
+ #btn-export:hover {
188
+ background: rgba(255, 255, 255, 0.06);
189
+ }
190
+
191
+ #btn-export-pdf {
192
+ background: transparent;
193
+ border: 1px solid var(--accent);
194
+ color: var(--accent);
195
+ font-weight: 600;
196
+ font-size: 11px;
197
+ letter-spacing: 0.3px;
198
+ }
199
+ #btn-export-pdf:hover {
200
+ background: rgba(232, 116, 32, 0.12);
201
+ }
202
+ #btn-export-pdf:disabled {
203
+ opacity: 0.5;
204
+ cursor: default;
205
+ }
206
+
207
+ #toolbar-status {
208
+ font-size: 11px;
209
+ color: var(--accent);
210
+ opacity: 0;
211
+ transition: opacity 0.3s;
212
+ pointer-events: none;
213
+ }
214
+
215
+ #toolbar-status.visible {
216
+ opacity: 1;
217
+ }
218
+
219
+ /* ── Zoom controls ──────────────────────────────────────────────────── */
220
+
221
+ .toolbar-zoom {
222
+ display: flex;
223
+ align-items: center;
224
+ gap: 2px;
225
+ flex-shrink: 0;
226
+ }
227
+
228
+ .btn-zoom {
229
+ width: 28px;
230
+ height: 28px;
231
+ border: 1px solid var(--border-panel);
232
+ background: transparent;
233
+ color: var(--text-primary);
234
+ border-radius: 4px;
235
+ font-size: 14px;
236
+ font-weight: 500;
237
+ cursor: pointer;
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ transition: background 0.12s;
242
+ padding: 0;
243
+ line-height: 1;
244
+ }
245
+
246
+ .btn-zoom:hover {
247
+ background: rgba(255, 255, 255, 0.08);
248
+ }
249
+
250
+ .btn-zoom-level {
251
+ height: 28px;
252
+ padding: 0 8px;
253
+ border: 1px solid var(--border-panel);
254
+ background: transparent;
255
+ color: var(--text-muted);
256
+ border-radius: 4px;
257
+ font-size: 11px;
258
+ font-weight: 500;
259
+ cursor: pointer;
260
+ transition: background 0.12s, color 0.12s;
261
+ min-width: 48px;
262
+ text-align: center;
263
+ font-family: 'DM Sans', system-ui, sans-serif;
264
+ }
265
+
266
+ .btn-zoom-level:hover {
267
+ background: rgba(255, 255, 255, 0.06);
268
+ color: var(--text-primary);
269
+ }
270
+
271
+ /* ── Slide count indicator ──────────────────────────────────────────── */
272
+
273
+ .toolbar-slide-count {
274
+ font-size: 11px;
275
+ color: var(--text-muted);
276
+ padding: 4px 10px;
277
+ background: rgba(255, 255, 255, 0.04);
278
+ border: 1px solid var(--border-panel);
279
+ border-radius: 4px;
280
+ white-space: nowrap;
281
+ flex-shrink: 0;
282
+ }
283
+
284
+ /* ── Panels ──────────────────────────────────────────────────────────────── */
285
+
286
+ .panel-layers,
287
+ .panel-properties {
288
+ grid-row: 2;
289
+ background: var(--bg-panel);
290
+ border-right: 1px solid var(--border-panel);
291
+ display: flex;
292
+ flex-direction: column;
293
+ overflow: hidden;
294
+ position: relative;
295
+ min-width: 0; /* prevent grid blowout */
296
+ }
297
+
298
+ .panel-properties {
299
+ grid-row: 2;
300
+ grid-column: 3;
301
+ border-right: none;
302
+ border-left: 1px solid var(--border-panel);
303
+ position: relative;
304
+ }
305
+
306
+ /* Extend right panel background to fill any viewport space beyond the max-width grid */
307
+ .panel-properties::after {
308
+ content: '';
309
+ position: absolute;
310
+ top: 0;
311
+ left: 100%;
312
+ width: 100vw;
313
+ height: 100%;
314
+ background: var(--bg-panel);
315
+ pointer-events: none;
316
+ }
317
+
318
+
319
+ /* Panel inner wrapper — hides content when collapsed */
320
+ .panel-inner {
321
+ display: flex;
322
+ flex-direction: column;
323
+ flex: 1;
324
+ overflow: hidden;
325
+ min-width: 0;
326
+ transition: opacity 0.2s ease;
327
+ }
328
+
329
+ .panel-layers.collapsed .panel-inner,
330
+ .panel-properties.collapsed .panel-inner {
331
+ opacity: 0;
332
+ pointer-events: none;
333
+ overflow: hidden;
334
+ }
335
+
336
+ /* Collapsed panels shrink to 0 via grid, hide border */
337
+ .panel-layers.collapsed {
338
+ border-right: none;
339
+ }
340
+ .panel-properties.collapsed {
341
+ border-left: none;
342
+ }
343
+
344
+ /* ── Panel collapse toggle buttons ─────────────────────────────────── */
345
+ .panel-collapse-btn {
346
+ position: absolute;
347
+ top: 50%;
348
+ transform: translateY(-50%);
349
+ z-index: 10;
350
+ width: 20px;
351
+ height: 48px;
352
+ border: 1px solid var(--border-panel);
353
+ background: var(--bg-panel);
354
+ color: var(--text-muted);
355
+ cursor: pointer;
356
+ display: flex;
357
+ align-items: center;
358
+ justify-content: center;
359
+ padding: 0;
360
+ transition: background 0.15s, color 0.15s, opacity 0.15s;
361
+ opacity: 0;
362
+ }
363
+
364
+ .panel-layers:hover .panel-collapse-btn,
365
+ .panel-properties:hover .panel-collapse-btn,
366
+ .panel-collapse-btn:hover {
367
+ opacity: 1;
368
+ }
369
+
370
+ .panel-collapse-btn:hover {
371
+ background: rgba(255, 255, 255, 0.08);
372
+ color: var(--text-primary);
373
+ }
374
+
375
+ /* Left toggle sits on right edge of left panel */
376
+ .panel-collapse-btn-left {
377
+ right: -20px;
378
+ border-radius: 0 6px 6px 0;
379
+ border-left: none;
380
+ }
381
+
382
+ /* Right toggle sits on left edge of right panel */
383
+ .panel-collapse-btn-right {
384
+ left: -20px;
385
+ border-radius: 6px 0 0 6px;
386
+ border-right: none;
387
+ }
388
+
389
+ /* When collapsed, toggle is always visible and repositioned */
390
+ .panel-layers.collapsed .panel-collapse-btn-left {
391
+ opacity: 1;
392
+ right: -20px;
393
+ }
394
+ .panel-properties.collapsed .panel-collapse-btn-right {
395
+ opacity: 1;
396
+ left: -20px;
397
+ }
398
+
399
+ /* Arrow icon direction: show open icon normally, closed icon when collapsed */
400
+ .collapse-icon-closed { display: none; }
401
+ .collapsed .collapse-icon-open { display: none; }
402
+ .collapsed .collapse-icon-closed { display: inline; }
403
+
404
+ .panel-header {
405
+ padding: 10px 14px;
406
+ font-size: 11px;
407
+ font-weight: 600;
408
+ letter-spacing: 0.06em;
409
+ text-transform: uppercase;
410
+ color: var(--text-muted);
411
+ border-bottom: 1px solid var(--border-panel);
412
+ flex-shrink: 0;
413
+ }
414
+
415
+ .panel-body {
416
+ flex: 1;
417
+ overflow-y: auto;
418
+ padding: 14px;
419
+ display: flex;
420
+ align-items: flex-start;
421
+ justify-content: center;
422
+ }
423
+
424
+ .panel-placeholder {
425
+ font-size: 12px;
426
+ color: var(--text-muted);
427
+ text-align: center;
428
+ padding-top: 20px;
429
+ }
430
+
431
+ /* ── Canvas area ─────────────────────────────────────────────────────────── */
432
+
433
+ .canvas-area {
434
+ grid-column: 2;
435
+ grid-row: 2;
436
+ background: var(--bg-workspace);
437
+ background-image: radial-gradient(circle, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
438
+ background-size: 20px 20px;
439
+ overflow: auto;
440
+ scrollbar-gutter: stable;
441
+ position: relative;
442
+ min-width: 0;
443
+ }
444
+
445
+ /* Custom scrollbar */
446
+ .canvas-area::-webkit-scrollbar {
447
+ width: 8px;
448
+ height: 8px;
449
+ }
450
+ .canvas-area::-webkit-scrollbar-track {
451
+ background: var(--bg-workspace);
452
+ }
453
+ .canvas-area::-webkit-scrollbar-thumb {
454
+ background: var(--border-panel);
455
+ border-radius: 4px;
456
+ }
457
+
458
+ #canvas-empty-state {
459
+ text-align: center;
460
+ pointer-events: none;
461
+ position: absolute;
462
+ top: 50%;
463
+ left: 50%;
464
+ transform: translate(-50%, -50%);
465
+ }
466
+
467
+ #canvas-empty-state .empty-icon {
468
+ font-size: 40px;
469
+ margin-bottom: 12px;
470
+ opacity: 0.15;
471
+ }
472
+
473
+ #canvas-empty-state p {
474
+ margin: 0;
475
+ font-size: 13px;
476
+ color: var(--text-muted);
477
+ }
478
+
479
+ /* ── iframe render container ────────────────────────────────────────── */
480
+
481
+ #iframe-container {
482
+ margin: 24px;
483
+ transform-origin: top left;
484
+ /* Width and height are set dynamically by editor.js based on content */
485
+ }
486
+
487
+ #render-iframe {
488
+ border: none;
489
+ background: #fff;
490
+ display: block;
491
+ /* Width and height are set dynamically by editor.js */
492
+ box-shadow: 0 2px 20px rgba(0, 0, 0, 0.4);
493
+ }
494
+
495
+ /* ── Welcome screen ──────────────────────────────────────────────────────── */
496
+
497
+ #welcome-screen {
498
+ position: fixed;
499
+ inset: 0;
500
+ z-index: 100;
501
+ background: #111;
502
+ display: flex;
503
+ flex-direction: column;
504
+ align-items: center;
505
+ justify-content: center;
506
+ gap: 20px;
507
+ overflow: hidden;
508
+ }
509
+
510
+ /* Gradient glow blobs (matches s2-video-section on ashrafbuilds.com) */
511
+ .welcome-blob {
512
+ position: absolute;
513
+ border-radius: 9999px;
514
+ filter: blur(120px);
515
+ opacity: 0.45;
516
+ pointer-events: none;
517
+ }
518
+
519
+ .welcome-blob-1 {
520
+ width: 50vw; height: 50vh; top: -15%; left: -10%;
521
+ background: radial-gradient(circle, #2C4685 0%, transparent 70%);
522
+ }
523
+
524
+ .welcome-blob-2 {
525
+ width: 60vw; height: 60vh; top: 20%; right: -15%;
526
+ background: radial-gradient(circle, #E87420 0%, transparent 70%);
527
+ }
528
+
529
+ .welcome-blob-3 {
530
+ width: 45vw; height: 45vh; bottom: -10%; left: 25%;
531
+ background: radial-gradient(circle, #8B3A0F 0%, transparent 70%);
532
+ }
533
+
534
+ /* Grain overlay */
535
+ #welcome-screen::before {
536
+ content: '';
537
+ position: absolute;
538
+ inset: 0;
539
+ z-index: 0;
540
+ pointer-events: none;
541
+ opacity: 0.4;
542
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
543
+ background-repeat: repeat;
544
+ background-size: 180px 180px;
545
+ }
546
+
547
+ .welcome-logo {
548
+ position: relative;
549
+ z-index: 1;
550
+ }
551
+
552
+ .welcome-logo-img {
553
+ width: 220px;
554
+ height: auto;
555
+ }
556
+
557
+ .welcome-subtitle,
558
+ #btn-open,
559
+ .recent-files-section {
560
+ position: relative;
561
+ z-index: 1;
562
+ }
563
+
564
+ .welcome-subtitle {
565
+ font-size: 15px;
566
+ color: var(--text-muted);
567
+ margin: -8px 0 0 0;
568
+ }
569
+
570
+ #btn-open {
571
+ padding: 10px 28px;
572
+ background: var(--accent);
573
+ color: #fff;
574
+ border: none;
575
+ border-radius: 8px;
576
+ font-size: 14px;
577
+ font-weight: 600;
578
+ cursor: pointer;
579
+ transition: background 0.15s;
580
+ }
581
+
582
+ #btn-open:hover {
583
+ background: var(--accent-hover);
584
+ }
585
+
586
+ .recent-files-section {
587
+ width: 320px;
588
+ max-width: 90vw;
589
+ }
590
+
591
+ .recent-files-section h3 {
592
+ font-size: 11px;
593
+ font-weight: 600;
594
+ letter-spacing: 0.06em;
595
+ text-transform: uppercase;
596
+ color: var(--text-muted);
597
+ margin: 0 0 10px 0;
598
+ }
599
+
600
+ #recent-files-list {
601
+ list-style: none;
602
+ margin: 0;
603
+ padding: 0;
604
+ display: flex;
605
+ flex-direction: column;
606
+ gap: 4px;
607
+ }
608
+
609
+ #recent-files-list li {
610
+ padding: 8px 12px;
611
+ border-radius: 6px;
612
+ background: transparent;
613
+ border: 1.5px solid rgba(255, 255, 255, 0.7);
614
+ cursor: pointer;
615
+ transition: background 0.12s, border-color 0.12s;
616
+ }
617
+
618
+ #recent-files-list li:hover {
619
+ background: rgba(255, 255, 255, 0.06);
620
+ border-color: #fff;
621
+ }
622
+
623
+ #recent-files-list .recent-filename {
624
+ font-size: 13px;
625
+ color: #fff;
626
+ display: block;
627
+ white-space: nowrap;
628
+ overflow: hidden;
629
+ text-overflow: ellipsis;
630
+ }
631
+
632
+ #recent-files-list .recent-path {
633
+ font-size: 11px;
634
+ color: rgba(255, 255, 255, 0.55);
635
+ display: block;
636
+ white-space: nowrap;
637
+ overflow: hidden;
638
+ text-overflow: ellipsis;
639
+ margin-top: 2px;
640
+ }
641
+
642
+ .recent-files-empty {
643
+ font-size: 12px;
644
+ color: var(--text-muted);
645
+ font-style: italic;
646
+ }
647
+
648
+ /* ── Drop overlay ────────────────────────────────────────────────────────── */
649
+
650
+ #drop-overlay {
651
+ position: fixed;
652
+ inset: 0;
653
+ z-index: 50;
654
+ background: rgba(232, 116, 32, 0.12);
655
+ border: 3px dashed var(--accent);
656
+ display: none;
657
+ align-items: center;
658
+ justify-content: center;
659
+ pointer-events: none;
660
+ }
661
+
662
+ #drop-overlay.active {
663
+ display: flex;
664
+ }
665
+
666
+ #drop-overlay p {
667
+ font-size: 20px;
668
+ font-weight: 600;
669
+ color: var(--accent);
670
+ }
671
+
672
+ /* ── File-changed banner ─────────────────────────────────────────────────── */
673
+
674
+ #file-changed-banner {
675
+ position: fixed;
676
+ bottom: 16px;
677
+ left: 50%;
678
+ transform: translateX(-50%);
679
+ background: #333;
680
+ color: var(--text-primary);
681
+ padding: 10px 20px;
682
+ border-radius: 6px;
683
+ z-index: 200;
684
+ display: none;
685
+ align-items: center;
686
+ gap: 12px;
687
+ font-size: 13px;
688
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
689
+ border: 1px solid var(--border-panel);
690
+ white-space: nowrap;
691
+ }
692
+
693
+ #file-changed-banner.visible {
694
+ display: flex;
695
+ }
696
+
697
+ #file-changed-banner button {
698
+ padding: 4px 10px;
699
+ border-radius: 4px;
700
+ font-size: 12px;
701
+ font-weight: 500;
702
+ cursor: pointer;
703
+ border: 1px solid var(--border-panel);
704
+ background: rgba(255, 255, 255, 0.08);
705
+ color: var(--text-primary);
706
+ transition: background 0.12s;
707
+ }
708
+
709
+ #file-changed-banner button:hover {
710
+ background: rgba(255, 255, 255, 0.14);
711
+ }
712
+
713
+ #file-changed-banner #btn-banner-reload {
714
+ background: var(--accent);
715
+ border-color: var(--accent);
716
+ color: #fff;
717
+ }
718
+
719
+ #file-changed-banner #btn-banner-reload:hover {
720
+ background: var(--accent-hover);
721
+ }
722
+
723
+ /* ── Selection overlays ──────────────────────────────────────────────────── */
724
+
725
+ #hover-overlay {
726
+ position: absolute;
727
+ pointer-events: none;
728
+ border: 1.5px dashed #4a7fd4;
729
+ box-sizing: border-box;
730
+ z-index: 10;
731
+ }
732
+
733
+ #selection-overlay {
734
+ position: absolute;
735
+ pointer-events: none;
736
+ border: 1.5px solid #4a7fd4;
737
+ box-sizing: border-box;
738
+ z-index: 11;
739
+ }
740
+
741
+ .sel-drag-surface {
742
+ position: absolute;
743
+ inset: 0;
744
+ pointer-events: all;
745
+ cursor: move;
746
+ }
747
+
748
+ .sel-handle {
749
+ position: absolute;
750
+ width: 8px;
751
+ height: 8px;
752
+ background: #4a7fd4;
753
+ border: 1px solid #fff;
754
+ box-sizing: border-box;
755
+ pointer-events: all; /* handles ARE clickable for parent escalation */
756
+ cursor: default;
757
+ }
758
+
759
+ /* Handle positions: offset by -50% to center on corner/edge */
760
+ .sel-handle[data-pos="tl"] { transform: translate(-50%, -50%); }
761
+ .sel-handle[data-pos="tm"] { left: 50%; transform: translate(-50%, -50%); }
762
+ .sel-handle[data-pos="tr"] { left: 100%; transform: translate(-50%, -50%); }
763
+ .sel-handle[data-pos="ml"] { top: 50%; transform: translate(-50%, -50%); }
764
+ .sel-handle[data-pos="mr"] { left: 100%; top: 50%; transform: translate(-50%, -50%); }
765
+ .sel-handle[data-pos="bl"] { top: 100%; transform: translate(-50%, -50%); }
766
+ .sel-handle[data-pos="bm"] { left: 50%; top: 100%; transform: translate(-50%, -50%); }
767
+ .sel-handle[data-pos="br"] { left: 100%; top: 100%; transform: translate(-50%, -50%); }
768
+
769
+ .sel-dim-label {
770
+ position: absolute;
771
+ top: calc(100% + 6px);
772
+ left: 50%;
773
+ transform: translateX(-50%);
774
+ font-size: 10px;
775
+ font-family: 'DM Sans', system-ui, sans-serif;
776
+ color: #4a7fd4;
777
+ white-space: nowrap;
778
+ pointer-events: none;
779
+ background: rgba(30, 30, 30, 0.75);
780
+ padding: 1px 5px;
781
+ border-radius: 3px;
782
+ }
783
+
784
+ .sel-rotate-handle {
785
+ position: absolute;
786
+ left: 50%;
787
+ top: -24px;
788
+ width: 12px;
789
+ height: 12px;
790
+ background: #4a7fd4;
791
+ border: 1px solid #fff;
792
+ border-radius: 50%;
793
+ transform: translateX(-50%);
794
+ cursor: grab;
795
+ pointer-events: all;
796
+ }
797
+
798
+ .sel-rotate-handle:active {
799
+ cursor: grabbing;
800
+ }
801
+
802
+ /* ── Marquee selection rect ───────────────────────────────────────────────── */
803
+
804
+ .marquee-rect {
805
+ position: absolute;
806
+ border: 1px dashed #4a90d9;
807
+ background: rgba(74, 144, 217, 0.08);
808
+ pointer-events: none;
809
+ z-index: 1000;
810
+ box-sizing: border-box;
811
+ }
812
+
813
+ /* ── Multi-selection bounding box overlay ─────────────────────────────────── */
814
+
815
+ #multi-selection-overlay {
816
+ position: absolute;
817
+ pointer-events: none;
818
+ border: 1.5px dashed #4a90d9;
819
+ background: rgba(74, 144, 217, 0.05);
820
+ box-sizing: border-box;
821
+ z-index: 12;
822
+ }
823
+
824
+ .multi-drag-surface {
825
+ position: absolute;
826
+ inset: 0;
827
+ pointer-events: all;
828
+ cursor: move;
829
+ }
830
+
831
+ /* ── Layer panel ──────────────────────────────────────────────────────────── */
832
+
833
+ .layer-list {
834
+ list-style: none;
835
+ margin: 0;
836
+ padding: 0;
837
+ }
838
+
839
+ .layer-item {
840
+ padding: 4px 8px;
841
+ font-size: 12px;
842
+ font-family: 'DM Sans', sans-serif;
843
+ color: #ccc;
844
+ cursor: pointer;
845
+ border-radius: 4px;
846
+ white-space: nowrap;
847
+ overflow: hidden;
848
+ text-overflow: ellipsis;
849
+ user-select: none;
850
+ }
851
+
852
+ .layer-item:hover {
853
+ background: rgba(255, 255, 255, 0.06);
854
+ }
855
+
856
+ .layer-item.active {
857
+ background: rgba(44, 70, 133, 0.3);
858
+ color: #fff;
859
+ }
860
+
861
+ /* (Layer tree is now in right panel only) */
862
+
863
+ /* SortableJS drag ghost */
864
+ .layer-item.sortable-ghost {
865
+ opacity: 0.4;
866
+ }
867
+
868
+ .layer-item.sortable-chosen {
869
+ background: rgba(44, 70, 133, 0.2);
870
+ }
871
+
872
+ /* Left panel body (assets/components) */
873
+ .panel-layers .panel-body {
874
+ align-items: flex-start;
875
+ justify-content: flex-start;
876
+ padding: 8px 0;
877
+ }
878
+
879
+ /* Right-side layer panel (inside properties aside) */
880
+ .panel-section-right-layers {
881
+ flex: none !important;
882
+ max-height: 220px;
883
+ overflow-y: auto;
884
+ border-bottom: 1px solid var(--border-panel);
885
+ padding: 4px 0 !important;
886
+ flex-direction: column !important;
887
+ align-items: stretch !important;
888
+ justify-content: flex-start !important;
889
+ }
890
+
891
+ .panel-section-right-layers .layer-list {
892
+ width: 100%;
893
+ }
894
+
895
+ /* Layer groups (slide grouping) */
896
+ .layer-group {
897
+ width: 100%;
898
+ margin-bottom: 2px;
899
+ }
900
+
901
+ .layer-group-label {
902
+ padding: 5px 10px;
903
+ font-size: 10px;
904
+ font-weight: 600;
905
+ color: var(--text-muted);
906
+ text-transform: uppercase;
907
+ letter-spacing: 0.5px;
908
+ cursor: pointer;
909
+ user-select: none;
910
+ }
911
+
912
+ .layer-group-label:hover {
913
+ color: var(--text-primary);
914
+ }
915
+
916
+ /* ── Moveable handle overrides ───────────────────────────────────────────── */
917
+ /* Blue accent (#2680EB) to match editor's selection visual language */
918
+
919
+ .moveable-control-box .moveable-line {
920
+ background: #2680EB !important;
921
+ height: 1px !important;
922
+ }
923
+
924
+ .moveable-control-box .moveable-control {
925
+ background: #fff !important;
926
+ border: 1.5px solid #2680EB !important;
927
+ border-radius: 50% !important;
928
+ width: 8px !important;
929
+ height: 8px !important;
930
+ margin-top: -4px !important;
931
+ margin-left: -4px !important;
932
+ }
933
+
934
+ .moveable-control-box .moveable-rotation-control {
935
+ border-radius: 50% !important;
936
+ background: #fff !important;
937
+ border: 1.5px solid #2680EB !important;
938
+ }
939
+
940
+ /* ── Snap guide lines (Figma-style pink) ─────────────────────────────────── */
941
+
942
+ .moveable-line.moveable-direction {
943
+ background: rgba(255, 0, 153, 0.85) !important;
944
+ height: 1px !important;
945
+ }
946
+
947
+ .moveable-line.moveable-dashed {
948
+ border-color: rgba(255, 0, 153, 0.85) !important;
949
+ }
950
+
951
+ /* ── Properties panel ───────────────────────────────────────────────────────── */
952
+
953
+ /* Override panel-body alignment for properties panel (left-align all controls) */
954
+ .panel-properties .panel-body-properties {
955
+ align-items: flex-start;
956
+ justify-content: flex-start;
957
+ flex-direction: column;
958
+ padding: 0;
959
+ gap: 0;
960
+ }
961
+
962
+ .prop-section {
963
+ width: 100%;
964
+ border-bottom: 1px solid var(--border-panel);
965
+ }
966
+
967
+ .prop-section.prop-disabled {
968
+ opacity: 0.4;
969
+ pointer-events: none;
970
+ }
971
+
972
+ .prop-section-header {
973
+ padding: 7px 12px;
974
+ font-size: 11px;
975
+ font-weight: 600;
976
+ letter-spacing: 0.05em;
977
+ text-transform: uppercase;
978
+ color: var(--text-muted);
979
+ cursor: pointer;
980
+ user-select: none;
981
+ display: flex;
982
+ align-items: center;
983
+ gap: 5px;
984
+ transition: color 0.12s;
985
+ }
986
+
987
+ .prop-section-header:hover {
988
+ color: var(--text-primary);
989
+ }
990
+
991
+ .prop-section-arrow {
992
+ font-size: 9px;
993
+ transition: transform 0.15s;
994
+ flex-shrink: 0;
995
+ }
996
+
997
+ .prop-section.prop-section-collapsed .prop-section-arrow {
998
+ transform: rotate(-90deg);
999
+ }
1000
+
1001
+ .prop-section.prop-section-collapsed .prop-section-body {
1002
+ display: none;
1003
+ }
1004
+
1005
+ .prop-section-body {
1006
+ padding: 4px 10px 8px 10px;
1007
+ display: flex;
1008
+ flex-direction: column;
1009
+ gap: 5px;
1010
+ }
1011
+
1012
+ /* 2x2 grid for X/Y/W/H */
1013
+ .prop-grid-2x2 {
1014
+ display: grid;
1015
+ grid-template-columns: 1fr 1fr;
1016
+ gap: 4px;
1017
+ }
1018
+
1019
+ .prop-row {
1020
+ display: flex;
1021
+ align-items: center;
1022
+ gap: 5px;
1023
+ min-height: 26px;
1024
+ }
1025
+
1026
+ .prop-row-full {
1027
+ width: 100%;
1028
+ }
1029
+
1030
+ .prop-label {
1031
+ font-size: 11px;
1032
+ color: var(--text-muted);
1033
+ min-width: 40px;
1034
+ flex-shrink: 0;
1035
+ }
1036
+
1037
+ .prop-unit {
1038
+ font-size: 11px;
1039
+ color: var(--text-muted);
1040
+ flex-shrink: 0;
1041
+ }
1042
+
1043
+ .prop-input {
1044
+ flex: 1;
1045
+ height: 26px;
1046
+ background: rgba(255, 255, 255, 0.05);
1047
+ border: 1px solid var(--border-panel);
1048
+ border-radius: 4px;
1049
+ color: var(--text-primary);
1050
+ font-size: 11px;
1051
+ font-family: 'DM Sans', system-ui, sans-serif;
1052
+ padding: 0 6px;
1053
+ min-width: 0;
1054
+ transition: border-color 0.12s;
1055
+ }
1056
+
1057
+ .prop-input:focus {
1058
+ outline: none;
1059
+ border-color: var(--accent);
1060
+ }
1061
+
1062
+ .prop-input.prop-locked,
1063
+ .prop-select.prop-locked {
1064
+ opacity: 0.45;
1065
+ cursor: not-allowed;
1066
+ border-style: dashed;
1067
+ }
1068
+
1069
+ .prop-select {
1070
+ flex: 1;
1071
+ height: 26px;
1072
+ background: rgba(255, 255, 255, 0.05);
1073
+ border: 1px solid var(--border-panel);
1074
+ border-radius: 4px;
1075
+ color: var(--text-primary);
1076
+ font-size: 11px;
1077
+ font-family: 'DM Sans', system-ui, sans-serif;
1078
+ padding: 0 4px;
1079
+ cursor: pointer;
1080
+ min-width: 0;
1081
+ appearance: none;
1082
+ -webkit-appearance: none;
1083
+ background-image: url("data:image/svg+xml,%3Csvg width='10' height='6' viewBox='0 0 10 6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%23888' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
1084
+ background-repeat: no-repeat;
1085
+ background-position: right 6px center;
1086
+ padding-right: 22px;
1087
+ }
1088
+
1089
+ .prop-select:focus {
1090
+ outline: none;
1091
+ border-color: var(--accent);
1092
+ }
1093
+
1094
+ .prop-select-full {
1095
+ width: 100%;
1096
+ flex: none;
1097
+ }
1098
+
1099
+ /* ── Custom font picker (searchable dropdown) ──────────────────────────────── */
1100
+
1101
+ .font-picker {
1102
+ width: 100%;
1103
+ position: relative;
1104
+ }
1105
+
1106
+ .font-picker-trigger {
1107
+ width: 100%;
1108
+ height: 26px;
1109
+ background: rgba(255, 255, 255, 0.05);
1110
+ border: 1px solid var(--border-panel);
1111
+ border-radius: 4px;
1112
+ color: var(--text-primary);
1113
+ font-size: 11px;
1114
+ font-family: 'DM Sans', system-ui, sans-serif;
1115
+ padding: 0 22px 0 6px;
1116
+ cursor: pointer;
1117
+ display: flex;
1118
+ align-items: center;
1119
+ text-align: left;
1120
+ position: relative;
1121
+ }
1122
+
1123
+ .font-picker-trigger:focus {
1124
+ outline: none;
1125
+ border-color: var(--accent);
1126
+ }
1127
+
1128
+ .font-picker-trigger:hover {
1129
+ border-color: rgba(255, 255, 255, 0.2);
1130
+ }
1131
+
1132
+ .font-picker-value {
1133
+ overflow: hidden;
1134
+ text-overflow: ellipsis;
1135
+ white-space: nowrap;
1136
+ flex: 1;
1137
+ }
1138
+
1139
+ .font-picker-arrow {
1140
+ position: absolute;
1141
+ right: 6px;
1142
+ top: 50%;
1143
+ transform: translateY(-50%);
1144
+ pointer-events: none;
1145
+ }
1146
+
1147
+ .font-picker.open .font-picker-arrow {
1148
+ transform: translateY(-50%) rotate(180deg);
1149
+ }
1150
+
1151
+ .font-picker-dropdown {
1152
+ position: fixed;
1153
+ width: 220px;
1154
+ max-height: 280px;
1155
+ background: #1e1e22;
1156
+ border: 1px solid var(--border-panel);
1157
+ border-radius: 6px;
1158
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
1159
+ z-index: 10000;
1160
+ display: flex;
1161
+ flex-direction: column;
1162
+ overflow: hidden;
1163
+ }
1164
+
1165
+ .font-picker-search {
1166
+ width: 100%;
1167
+ height: 30px;
1168
+ background: rgba(255, 255, 255, 0.06);
1169
+ border: none;
1170
+ border-bottom: 1px solid var(--border-panel);
1171
+ color: var(--text-primary);
1172
+ font-size: 11px;
1173
+ font-family: 'DM Sans', system-ui, sans-serif;
1174
+ padding: 0 8px;
1175
+ outline: none;
1176
+ }
1177
+
1178
+ .font-picker-search::placeholder {
1179
+ color: var(--text-muted);
1180
+ }
1181
+
1182
+ .font-picker-list {
1183
+ flex: 1;
1184
+ overflow-y: auto;
1185
+ padding: 4px 0;
1186
+ }
1187
+
1188
+ .font-picker-option {
1189
+ padding: 5px 10px;
1190
+ font-size: 11px;
1191
+ color: var(--text-primary);
1192
+ cursor: pointer;
1193
+ white-space: nowrap;
1194
+ overflow: hidden;
1195
+ text-overflow: ellipsis;
1196
+ }
1197
+
1198
+ .font-picker-option:hover,
1199
+ .font-picker-option.highlighted {
1200
+ background: rgba(232, 116, 32, 0.2);
1201
+ }
1202
+
1203
+ .font-picker-option.active {
1204
+ background: rgba(232, 116, 32, 0.35);
1205
+ font-weight: 600;
1206
+ }
1207
+
1208
+ .font-picker-separator {
1209
+ height: 1px;
1210
+ background: var(--border-panel);
1211
+ margin: 4px 0;
1212
+ }
1213
+
1214
+ .font-picker.prop-locked .font-picker-trigger {
1215
+ opacity: 0.45;
1216
+ cursor: not-allowed;
1217
+ border-style: dashed;
1218
+ }
1219
+
1220
+ .prop-color-swatch {
1221
+ width: 26px;
1222
+ height: 26px;
1223
+ border: 1px solid var(--border-panel);
1224
+ border-radius: 4px;
1225
+ padding: 2px;
1226
+ background: transparent;
1227
+ cursor: pointer;
1228
+ flex-shrink: 0;
1229
+ }
1230
+
1231
+ .prop-color-swatch::-webkit-color-swatch-wrapper {
1232
+ padding: 0;
1233
+ border-radius: 2px;
1234
+ }
1235
+
1236
+ .prop-color-swatch::-webkit-color-swatch {
1237
+ border: none;
1238
+ border-radius: 2px;
1239
+ }
1240
+
1241
+ .prop-hex-input {
1242
+ width: 72px;
1243
+ flex: none;
1244
+ }
1245
+
1246
+ .prop-var-lock {
1247
+ font-size: 10px;
1248
+ color: var(--accent);
1249
+ font-weight: 500;
1250
+ background: rgba(232, 116, 32, 0.1);
1251
+ border: 1px solid rgba(232, 116, 32, 0.3);
1252
+ padding: 1px 5px;
1253
+ border-radius: 3px;
1254
+ white-space: nowrap;
1255
+ flex-shrink: 0;
1256
+ }
1257
+
1258
+ /* ── Snap toggle button ──────────────────────────────────────────────────── */
1259
+
1260
+ #btn-snap {
1261
+ background: transparent;
1262
+ border: 1px solid var(--border-panel);
1263
+ color: var(--text-muted);
1264
+ transition: background 0.12s, color 0.12s, border-color 0.12s;
1265
+ }
1266
+
1267
+ #btn-snap:hover {
1268
+ background: rgba(255, 255, 255, 0.06);
1269
+ color: var(--text-primary);
1270
+ }
1271
+
1272
+ #btn-snap.active {
1273
+ background: rgba(232, 116, 32, 0.12);
1274
+ border-color: var(--accent);
1275
+ color: var(--accent);
1276
+ }
1277
+
1278
+ /* ── Shape picker dropdown ─────────────────────────────────────────────────── */
1279
+
1280
+ .shape-picker-wrapper {
1281
+ position: relative;
1282
+ }
1283
+
1284
+ #btn-shapes {
1285
+ display: flex;
1286
+ align-items: center;
1287
+ gap: 2px;
1288
+ width: auto;
1289
+ padding: 0 6px;
1290
+ }
1291
+
1292
+ .btn-shapes-caret {
1293
+ flex-shrink: 0;
1294
+ opacity: 0.5;
1295
+ margin-left: -1px;
1296
+ }
1297
+
1298
+ .shape-picker-dropdown {
1299
+ position: absolute;
1300
+ top: calc(100% + 6px);
1301
+ left: 0;
1302
+ width: 260px;
1303
+ max-height: 380px;
1304
+ overflow-y: auto;
1305
+ background: #1e1e22;
1306
+ border: 1px solid var(--border-panel);
1307
+ border-radius: 8px;
1308
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
1309
+ z-index: 10000;
1310
+ padding: 6px;
1311
+ }
1312
+
1313
+ .shape-picker-dropdown::-webkit-scrollbar {
1314
+ width: 5px;
1315
+ }
1316
+
1317
+ .shape-picker-dropdown::-webkit-scrollbar-thumb {
1318
+ background: rgba(255, 255, 255, 0.12);
1319
+ border-radius: 3px;
1320
+ }
1321
+
1322
+ .shape-picker-cat {
1323
+ font-size: 10px;
1324
+ font-weight: 600;
1325
+ text-transform: uppercase;
1326
+ letter-spacing: 0.05em;
1327
+ color: var(--text-muted);
1328
+ padding: 6px 6px 4px 6px;
1329
+ }
1330
+
1331
+ .shape-picker-grid {
1332
+ display: grid;
1333
+ grid-template-columns: repeat(6, 1fr);
1334
+ gap: 2px;
1335
+ padding: 0 2px 6px 2px;
1336
+ }
1337
+
1338
+ .shape-picker-item {
1339
+ width: 36px;
1340
+ height: 36px;
1341
+ display: flex;
1342
+ align-items: center;
1343
+ justify-content: center;
1344
+ background: transparent;
1345
+ border: 1px solid transparent;
1346
+ border-radius: 5px;
1347
+ color: var(--text-muted);
1348
+ cursor: pointer;
1349
+ padding: 0;
1350
+ transition: background 0.1s, color 0.1s, border-color 0.1s;
1351
+ }
1352
+
1353
+ .shape-picker-item:hover {
1354
+ background: rgba(232, 116, 32, 0.12);
1355
+ border-color: rgba(232, 116, 32, 0.3);
1356
+ color: var(--accent);
1357
+ }
1358
+
1359
+ .shape-picker-item svg {
1360
+ pointer-events: none;
1361
+ }
1362
+
1363
+ /* ── Asset browser & component library (05-04) ── */
1364
+ .toolbar-shapes { display: flex; gap: 2px; flex-shrink: 0; }
1365
+ .panel-header-collapsible { cursor: pointer; user-select: none; display: flex; align-items: center; gap: 6px; }
1366
+ .panel-header-collapsible::before { content: '▾'; font-size: 10px; }
1367
+ .panel-header-collapsible.collapsed::before { transform: rotate(-90deg); }
1368
+ .panel-section-assets, .panel-section-components { flex: none; overflow-y: auto; max-height: 180px; border-bottom: 1px solid var(--border-panel); }
1369
+ .asset-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; padding: 8px; }
1370
+ .asset-thumb { width: 60px; height: 60px; object-fit: cover; border-radius: 4px; cursor: grab; border: 1px solid transparent; background: rgba(255,255,255,0.06); }
1371
+ .asset-thumb:hover { border-color: var(--accent); }
1372
+ .component-list { display: flex; flex-direction: column; padding: 6px; gap: 3px; }
1373
+ .component-item { padding: 6px 10px; font-size: 11px; color: var(--text-primary); background: rgba(255,255,255,0.04); border: 1px solid var(--border-panel); border-radius: 4px; cursor: grab; }
1374
+ .context-menu { position: fixed; z-index: 10000; background: #1e1e22; border: 1px solid var(--border-panel); border-radius: 6px; padding: 4px; }
1375
+ .context-menu-item { padding: 7px 12px; font-size: 12px; color: var(--text-primary); border-radius: 4px; cursor: pointer; }
1376
+ .context-menu-item:hover { background: rgba(232,116,32,0.15); color: var(--accent); }
1377
+
1378
+ /* ── Properties panel action buttons ── */
1379
+ .prop-section-actions { border-bottom: 1px solid var(--border-panel); padding: 8px 10px; }
1380
+ .prop-actions-row { display: flex; gap: 6px; }
1381
+ .prop-action-btn {
1382
+ display: inline-flex; align-items: center; gap: 5px;
1383
+ padding: 5px 10px; font-size: 11px; font-family: inherit;
1384
+ color: var(--text-primary); background: rgba(255,255,255,0.06);
1385
+ border: 1px solid var(--border-panel); border-radius: 4px;
1386
+ cursor: pointer; transition: background 0.12s, border-color 0.12s;
1387
+ }
1388
+ .prop-action-btn:hover { background: rgba(232,116,32,0.12); border-color: var(--accent); color: var(--accent); }
1389
+ .prop-action-btn svg { flex-shrink: 0; }
1390
+
1391
+ /* ── Shape mask picker ── */
1392
+ .prop-mask-wrapper { position: relative; }
1393
+
1394
+ .mask-picker {
1395
+ position: absolute;
1396
+ top: calc(100% + 6px);
1397
+ left: 0;
1398
+ width: 220px;
1399
+ background: #1e1e22;
1400
+ border: 1px solid var(--border-panel);
1401
+ border-radius: 8px;
1402
+ box-shadow: 0 8px 32px rgba(0,0,0,0.5);
1403
+ z-index: 10001;
1404
+ padding: 8px;
1405
+ }
1406
+
1407
+ .mask-picker-grid {
1408
+ display: grid;
1409
+ grid-template-columns: repeat(6, 1fr);
1410
+ gap: 3px;
1411
+ margin-bottom: 6px;
1412
+ }
1413
+
1414
+ .mask-picker-item {
1415
+ width: 32px;
1416
+ height: 32px;
1417
+ display: flex;
1418
+ align-items: center;
1419
+ justify-content: center;
1420
+ background: rgba(255,255,255,0.05);
1421
+ border: 1px solid transparent;
1422
+ border-radius: 4px;
1423
+ cursor: pointer;
1424
+ padding: 0;
1425
+ transition: background 0.12s, border-color 0.12s;
1426
+ }
1427
+
1428
+ .mask-picker-item:hover,
1429
+ .mask-picker-item.active {
1430
+ background: rgba(232,116,32,0.15);
1431
+ border-color: var(--accent);
1432
+ }
1433
+
1434
+ .mask-picker-item svg { pointer-events: none; }
1435
+
1436
+ .mask-picker-remove {
1437
+ width: 100%;
1438
+ padding: 5px;
1439
+ font-size: 11px;
1440
+ font-family: inherit;
1441
+ color: var(--text-muted);
1442
+ background: rgba(255,255,255,0.04);
1443
+ border: 1px solid var(--border-panel);
1444
+ border-radius: 4px;
1445
+ cursor: pointer;
1446
+ transition: color 0.12s, border-color 0.12s;
1447
+ }
1448
+
1449
+ .mask-picker-remove:hover { color: var(--text-primary); border-color: var(--text-muted); }
1450
+
1451
+ /* ── Text-edit cursor hint on drag surface ── */
1452
+ .sel-drag-surface { cursor: move; }
1453
+ .sel-drag-surface.text-cursor { cursor: text; }
1454
+
1455
+ /* ── Alignment toolbar ── */
1456
+ .toolbar-align {
1457
+ display: flex;
1458
+ gap: 2px;
1459
+ flex-shrink: 0;
1460
+ }
1461
+
1462
+ /* ── Toggle button group (text-align, text-decoration, etc.) ── */
1463
+ .prop-btn-group {
1464
+ display: flex;
1465
+ gap: 2px;
1466
+ flex: 1;
1467
+ }
1468
+
1469
+ .prop-btn-toggle {
1470
+ width: 28px;
1471
+ height: 26px;
1472
+ display: flex;
1473
+ align-items: center;
1474
+ justify-content: center;
1475
+ background: rgba(255, 255, 255, 0.05);
1476
+ border: 1px solid var(--border-panel);
1477
+ border-radius: 4px;
1478
+ color: var(--text-muted);
1479
+ cursor: pointer;
1480
+ transition: background 0.12s, color 0.12s, border-color 0.12s;
1481
+ padding: 0;
1482
+ font-family: inherit;
1483
+ }
1484
+
1485
+ .prop-btn-toggle:hover {
1486
+ background: rgba(255, 255, 255, 0.1);
1487
+ color: var(--text-primary);
1488
+ }
1489
+
1490
+ .prop-btn-toggle.active {
1491
+ background: rgba(232, 116, 32, 0.15);
1492
+ border-color: var(--accent);
1493
+ color: var(--accent);
1494
+ }
1495
+
1496
+ /* ── Fill / Border chip toggles ── */
1497
+ .prop-chip-group {
1498
+ display: flex;
1499
+ gap: 4px;
1500
+ }
1501
+
1502
+ .prop-chip {
1503
+ flex: 1;
1504
+ height: 26px;
1505
+ display: flex;
1506
+ align-items: center;
1507
+ justify-content: center;
1508
+ background: rgba(255, 255, 255, 0.05);
1509
+ border: 1px solid var(--border-panel);
1510
+ border-radius: 4px;
1511
+ color: var(--text-muted);
1512
+ cursor: pointer;
1513
+ font-size: 11px;
1514
+ font-family: inherit;
1515
+ font-weight: 500;
1516
+ transition: background 0.12s, color 0.12s, border-color 0.12s;
1517
+ }
1518
+
1519
+ .prop-chip:hover {
1520
+ background: rgba(255, 255, 255, 0.1);
1521
+ color: var(--text-primary);
1522
+ }
1523
+
1524
+ .prop-chip.active {
1525
+ background: rgba(232, 116, 32, 0.15);
1526
+ border-color: var(--accent);
1527
+ color: var(--accent);
1528
+ }
1529
+
1530
+ /* ── Opacity range slider ── */
1531
+ .prop-range {
1532
+ flex: 1;
1533
+ height: 4px;
1534
+ -webkit-appearance: none;
1535
+ appearance: none;
1536
+ background: rgba(255, 255, 255, 0.12);
1537
+ border-radius: 2px;
1538
+ outline: none;
1539
+ cursor: pointer;
1540
+ }
1541
+
1542
+ .prop-range::-webkit-slider-thumb {
1543
+ -webkit-appearance: none;
1544
+ width: 14px;
1545
+ height: 14px;
1546
+ border-radius: 50%;
1547
+ background: var(--accent);
1548
+ border: 2px solid #fff;
1549
+ cursor: pointer;
1550
+ }
1551
+
1552
+ .prop-range::-moz-range-thumb {
1553
+ width: 14px;
1554
+ height: 14px;
1555
+ border-radius: 50%;
1556
+ background: var(--accent);
1557
+ border: 2px solid #fff;
1558
+ cursor: pointer;
1559
+ }
1560
+
1561
+ .prop-input-sm {
1562
+ width: 48px;
1563
+ flex: none;
1564
+ }
1565
+
1566
+ /* ── Small action button variant ── */
1567
+ .prop-action-btn-sm {
1568
+ font-size: 10px;
1569
+ padding: 3px 8px;
1570
+ }
1571
+
1572
+ /* ── Aspect ratio lock button ── */
1573
+ .prop-row-linked {
1574
+ position: relative;
1575
+ }
1576
+
1577
+ .prop-link-btn {
1578
+ width: 22px;
1579
+ height: 22px;
1580
+ display: flex;
1581
+ align-items: center;
1582
+ justify-content: center;
1583
+ background: transparent;
1584
+ border: 1px solid var(--border-panel);
1585
+ border-radius: 3px;
1586
+ color: var(--text-muted);
1587
+ cursor: pointer;
1588
+ padding: 0;
1589
+ flex-shrink: 0;
1590
+ transition: background 0.12s, color 0.12s, border-color 0.12s;
1591
+ }
1592
+
1593
+ .prop-link-btn:hover {
1594
+ background: rgba(255, 255, 255, 0.08);
1595
+ color: var(--text-primary);
1596
+ }
1597
+
1598
+ .prop-link-btn.active {
1599
+ background: rgba(232, 116, 32, 0.15);
1600
+ border-color: var(--accent);
1601
+ color: var(--accent);
1602
+ }
1603
+
1604
+ /* ── Layer item lock/hide toggles ── */
1605
+ .layer-item {
1606
+ display: flex;
1607
+ align-items: center;
1608
+ gap: 4px;
1609
+ }
1610
+
1611
+ .layer-item-label {
1612
+ flex: 1;
1613
+ overflow: hidden;
1614
+ text-overflow: ellipsis;
1615
+ white-space: nowrap;
1616
+ }
1617
+
1618
+ .layer-toggle {
1619
+ width: 18px;
1620
+ height: 18px;
1621
+ display: flex;
1622
+ align-items: center;
1623
+ justify-content: center;
1624
+ background: transparent;
1625
+ border: none;
1626
+ color: var(--text-muted);
1627
+ cursor: pointer;
1628
+ padding: 0;
1629
+ border-radius: 3px;
1630
+ opacity: 0;
1631
+ transition: opacity 0.12s, color 0.12s;
1632
+ flex-shrink: 0;
1633
+ }
1634
+
1635
+ .layer-item:hover .layer-toggle,
1636
+ .layer-toggle.active {
1637
+ opacity: 1;
1638
+ }
1639
+
1640
+ .layer-toggle:hover {
1641
+ color: var(--text-primary);
1642
+ background: rgba(255, 255, 255, 0.08);
1643
+ }
1644
+
1645
+ .layer-toggle.active {
1646
+ color: var(--accent);
1647
+ }
1648
+
1649
+ /* ── Recent color swatches ── */
1650
+ .prop-recent-colors {
1651
+ display: flex;
1652
+ gap: 3px;
1653
+ flex-wrap: wrap;
1654
+ margin-top: 4px;
1655
+ }
1656
+
1657
+ .prop-recent-swatch {
1658
+ width: 18px;
1659
+ height: 18px;
1660
+ border-radius: 3px;
1661
+ border: 1px solid rgba(255, 255, 255, 0.15);
1662
+ cursor: pointer;
1663
+ padding: 0;
1664
+ transition: border-color 0.12s;
1665
+ }
1666
+
1667
+ .prop-recent-swatch:hover {
1668
+ border-color: var(--accent);
1669
+ }
1670
+
1671
+ /* ── Rulers and Guides ─────────────────────────────────────────────────────── */
1672
+
1673
+ /* Rulers use a wrapper that sits on top of the canvas and doesn't scroll */
1674
+ .canvas-rulers-wrapper {
1675
+ position: absolute;
1676
+ top: 0;
1677
+ left: 0;
1678
+ pointer-events: none;
1679
+ z-index: 15;
1680
+ overflow: hidden;
1681
+ /* width/height and top/left are set dynamically by JS to track the scroll viewport */
1682
+ }
1683
+
1684
+ .canvas-ruler {
1685
+ position: absolute;
1686
+ background: #1c1c1e;
1687
+ pointer-events: all;
1688
+ overflow: hidden;
1689
+ }
1690
+
1691
+ .canvas-ruler canvas {
1692
+ display: block;
1693
+ }
1694
+
1695
+ .canvas-ruler-h {
1696
+ top: 0;
1697
+ left: 20px;
1698
+ right: 0;
1699
+ height: 20px;
1700
+ cursor: s-resize;
1701
+ border-bottom: 1px solid #2a2a2e;
1702
+ }
1703
+
1704
+ .canvas-ruler-v {
1705
+ top: 20px;
1706
+ left: 0;
1707
+ bottom: 0;
1708
+ width: 20px;
1709
+ cursor: e-resize;
1710
+ border-right: 1px solid #2a2a2e;
1711
+ }
1712
+
1713
+ .canvas-ruler-corner {
1714
+ position: absolute;
1715
+ top: 0;
1716
+ left: 0;
1717
+ width: 20px;
1718
+ height: 20px;
1719
+ background: #1c1c1e;
1720
+ border-right: 1px solid #2a2a2e;
1721
+ border-bottom: 1px solid #2a2a2e;
1722
+ z-index: 16;
1723
+ pointer-events: all;
1724
+ }
1725
+
1726
+ .canvas-guides-container {
1727
+ position: absolute;
1728
+ top: 0;
1729
+ left: 0;
1730
+ width: 1px;
1731
+ height: 1px;
1732
+ overflow: visible;
1733
+ pointer-events: none;
1734
+ z-index: 9;
1735
+ }
1736
+
1737
+ .canvas-guide {
1738
+ pointer-events: all !important;
1739
+ }
1740
+
1741
+ .canvas-guide-h {
1742
+ height: 0;
1743
+ border-top: 1px dashed rgba(0, 160, 255, 0.45);
1744
+ background: none;
1745
+ }
1746
+
1747
+ .canvas-guide-v {
1748
+ width: 0;
1749
+ border-left: 1px dashed rgba(0, 160, 255, 0.45);
1750
+ background: none;
1751
+ }
1752
+
1753
+ /* ── Slide panel (PowerPoint-style thumbnails) ────────────────────────────── */
1754
+
1755
+ .slide-panel {
1756
+ flex: 1;
1757
+ overflow-y: auto;
1758
+ overflow-x: hidden;
1759
+ padding: 12px 6px 12px 4px;
1760
+ display: flex;
1761
+ flex-direction: column;
1762
+ gap: 6px;
1763
+ }
1764
+
1765
+ /* Scrollbar for slide panel */
1766
+ .slide-panel::-webkit-scrollbar {
1767
+ width: 6px;
1768
+ }
1769
+ .slide-panel::-webkit-scrollbar-track {
1770
+ background: transparent;
1771
+ }
1772
+ .slide-panel::-webkit-scrollbar-thumb {
1773
+ background: rgba(255, 255, 255, 0.1);
1774
+ border-radius: 3px;
1775
+ }
1776
+
1777
+ .slide-thumb {
1778
+ display: flex;
1779
+ align-items: flex-start;
1780
+ gap: 6px;
1781
+ padding: 4px;
1782
+ cursor: pointer;
1783
+ border-radius: 6px;
1784
+ transition: background 0.12s;
1785
+ flex-shrink: 0;
1786
+ }
1787
+
1788
+ .slide-thumb:hover {
1789
+ background: rgba(255, 255, 255, 0.04);
1790
+ }
1791
+
1792
+ .slide-thumb-num {
1793
+ font-size: 10px;
1794
+ color: var(--text-muted);
1795
+ width: 16px;
1796
+ text-align: right;
1797
+ flex-shrink: 0;
1798
+ padding-top: 4px;
1799
+ font-weight: 500;
1800
+ font-variant-numeric: tabular-nums;
1801
+ }
1802
+
1803
+ .slide-thumb-preview {
1804
+ flex: 1;
1805
+ overflow: hidden;
1806
+ border-radius: 3px;
1807
+ border: 2px solid rgba(255, 255, 255, 0.08);
1808
+ position: relative;
1809
+ background: #fff;
1810
+ transition: border-color 0.15s, box-shadow 0.15s;
1811
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
1812
+ }
1813
+
1814
+ .slide-thumb.active .slide-thumb-preview {
1815
+ border-color: var(--accent);
1816
+ box-shadow: 0 0 0 1px var(--accent), 0 2px 8px rgba(232, 116, 32, 0.25);
1817
+ }
1818
+
1819
+ .slide-thumb:hover:not(.active) .slide-thumb-preview {
1820
+ border-color: rgba(255, 255, 255, 0.2);
1821
+ }
1822
+
1823
+ .slide-thumb-iframe {
1824
+ border: none;
1825
+ pointer-events: none;
1826
+ transform-origin: top left;
1827
+ position: absolute;
1828
+ top: 0;
1829
+ left: 0;
1830
+ display: block;
1831
+ }
1832
+
1833
+ /* ── Crop overlay ──────────────────────────────────────────────────────────── */
1834
+
1835
+ .crop-overlay {
1836
+ position: absolute;
1837
+ z-index: 20;
1838
+ pointer-events: none;
1839
+ }
1840
+
1841
+ .crop-dim-area {
1842
+ position: absolute;
1843
+ inset: 0;
1844
+ background: rgba(0, 0, 0, 0.5);
1845
+ pointer-events: none;
1846
+ }
1847
+
1848
+ /* Edge handles */
1849
+ .crop-handle {
1850
+ position: absolute;
1851
+ pointer-events: all;
1852
+ z-index: 21;
1853
+ }
1854
+
1855
+ .crop-handle-t, .crop-handle-b {
1856
+ height: 6px;
1857
+ margin-top: -3px;
1858
+ cursor: ns-resize;
1859
+ }
1860
+
1861
+ .crop-handle-l, .crop-handle-r {
1862
+ width: 6px;
1863
+ margin-left: -3px;
1864
+ cursor: ew-resize;
1865
+ }
1866
+
1867
+ /* Corner handles */
1868
+ .crop-handle-tl, .crop-handle-tr, .crop-handle-bl, .crop-handle-br {
1869
+ width: 12px;
1870
+ height: 12px;
1871
+ background: #fff;
1872
+ border: 2px solid var(--accent);
1873
+ border-radius: 2px;
1874
+ margin-left: -6px;
1875
+ margin-top: -6px;
1876
+ z-index: 22;
1877
+ }
1878
+
1879
+ .crop-handle-tl { cursor: nwse-resize; }
1880
+ .crop-handle-tr { cursor: nesw-resize; }
1881
+ .crop-handle-bl { cursor: nesw-resize; }
1882
+ .crop-handle-br { cursor: nwse-resize; }
1883
+
1884
+ /* Crop toolbar */
1885
+ .crop-toolbar {
1886
+ position: absolute;
1887
+ display: flex;
1888
+ gap: 6px;
1889
+ pointer-events: all;
1890
+ z-index: 23;
1891
+ padding-top: 8px;
1892
+ }
1893
+
1894
+ .crop-btn {
1895
+ padding: 5px 12px;
1896
+ font-size: 11px;
1897
+ font-weight: 600;
1898
+ font-family: 'DM Sans', system-ui, sans-serif;
1899
+ border-radius: 4px;
1900
+ cursor: pointer;
1901
+ border: none;
1902
+ transition: background 0.12s;
1903
+ }
1904
+
1905
+ .crop-btn-apply {
1906
+ background: var(--accent);
1907
+ color: #fff;
1908
+ }
1909
+
1910
+ .crop-btn-apply:hover {
1911
+ background: var(--accent-hover);
1912
+ }
1913
+
1914
+ .crop-btn-cancel, .crop-btn-reset {
1915
+ background: rgba(255, 255, 255, 0.1);
1916
+ color: var(--text-primary);
1917
+ border: 1px solid var(--border-panel);
1918
+ }
1919
+
1920
+ .crop-btn-cancel:hover, .crop-btn-reset:hover {
1921
+ background: rgba(255, 255, 255, 0.18);
1922
+ }
1923
+
1924
+ /* ── Z-order controls (layer ordering) ─────────────────────────────────── */
1925
+
1926
+ .prop-zorder-row {
1927
+ display: flex;
1928
+ gap: 4px;
1929
+ flex-wrap: wrap;
1930
+ }
1931
+
1932
+ .prop-zorder-btn {
1933
+ flex: 1;
1934
+ min-width: 0;
1935
+ padding: 4px 2px;
1936
+ border: 1px solid var(--border-panel);
1937
+ background: transparent;
1938
+ color: var(--text-muted);
1939
+ border-radius: 4px;
1940
+ font-size: 10px;
1941
+ font-weight: 500;
1942
+ cursor: pointer;
1943
+ display: flex;
1944
+ align-items: center;
1945
+ justify-content: center;
1946
+ gap: 3px;
1947
+ transition: background 0.12s, color 0.12s;
1948
+ white-space: nowrap;
1949
+ }
1950
+
1951
+ .prop-zorder-btn:hover {
1952
+ background: rgba(255, 255, 255, 0.08);
1953
+ color: var(--text-primary);
1954
+ }
1955
+
1956
+ .prop-zorder-btn svg {
1957
+ flex-shrink: 0;
1958
+ }
1959
+
1960
+ /* ── Responsive: small viewports ──────────────────────────────────────── */
1961
+
1962
+ @media (max-width: 1100px) {
1963
+ :root {
1964
+ --sidebar-w: 180px;
1965
+ }
1966
+ .panel-section-right-layers {
1967
+ max-height: 160px;
1968
+ }
1969
+ }
1970
+
1971
+ @media (max-width: 900px) {
1972
+ :root {
1973
+ --sidebar-w: 160px;
1974
+ --toolbar-h: 40px;
1975
+ }
1976
+ .panel-inner {
1977
+ zoom: 0.88;
1978
+ }
1979
+ .panel-section-right-layers {
1980
+ max-height: 120px;
1981
+ }
1982
+ .toolbar {
1983
+ padding: 0 8px;
1984
+ gap: 4px;
1985
+ }
1986
+ .toolbar-wordmark { font-size: 12px; }
1987
+ .toolbar-separator { display: none; }
1988
+ .toolbar-wordmark span { display: none; }
1989
+ #current-filename { min-width: 20px; flex: 0 1 auto; }
1990
+ .btn-toolbar { padding: 4px 6px; font-size: 11px; }
1991
+ .btn-toolbar.btn-icon { width: 26px; height: 26px; }
1992
+ #btn-export { display: none; }
1993
+ .btn-zoom { width: 24px; height: 24px; font-size: 12px; }
1994
+ .btn-zoom-level { height: 24px; font-size: 10px; min-width: 40px; }
1995
+ #iframe-container { margin: 20px auto; }
1996
+ }