@dickpy/dsh-imagegen 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,970 @@
1
+ /**
2
+ * dsh-imagegen studio styles. Scoped by the plugin's own data attributes so
3
+ * nothing leaks into the rest of the GUI; colors ride the dsh --dsw-* tokens
4
+ * and interactive controls reuse the system primitives (Button / Pill), so
5
+ * the studio follows the active theme (light/dark and skins) by construction.
6
+ * The center-column hide rules are attribute-scoped and must stay in this
7
+ * stylesheet (it is imported by mount.tsx, so the styles load with the
8
+ * plugin).
9
+ */
10
+
11
+ /* --- center-column takeover (global rules, attribute-scoped) ----------------- */
12
+
13
+ [data-pane='conversation'] {
14
+ position: relative;
15
+ }
16
+
17
+ /* The panel container rides inside the conversation grid item as an extra
18
+ trailing child; hidden unless the panel is active. */
19
+ [data-dsh-imagegen-view] {
20
+ position: absolute;
21
+ inset: 0;
22
+ display: none;
23
+ z-index: 60;
24
+ background: var(--dsw-alias-bg-base);
25
+ }
26
+
27
+ /* The center column is single-occupant; the :not() guards keep the sibling
28
+ panels (task board / ssh) from fighting over visibility if both activation
29
+ attributes ever coexist. */
30
+ html[data-dsh-imagegen-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [data-dsh-imagegen-view] {
31
+ display: block;
32
+ }
33
+
34
+ /* While the panel is active, the conversation content underneath is hidden
35
+ (it stays mounted and stateful). */
36
+ html[data-dsh-imagegen-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [data-pane='conversation'] > :not([data-dsh-imagegen-view]),
37
+ html[data-dsh-imagegen-active]:not([data-dsh-taskboard-active]):not([data-dsh-ssh-active]) [class*='centerCol'] > :not([data-dsh-imagegen-view]) {
38
+ display: none !important;
39
+ }
40
+
41
+ /* --- sidebar entry row ------------------------------------------------------- */
42
+
43
+ .entry {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 8px;
47
+ width: 100%;
48
+ height: 32px;
49
+ padding: 0 12px;
50
+ background: transparent;
51
+ border: none;
52
+ border-radius: 8px;
53
+ color: var(--dsw-alias-label-secondary);
54
+ cursor: pointer;
55
+ font-size: 13px;
56
+ white-space: nowrap;
57
+ }
58
+
59
+ .entry:hover {
60
+ background: var(--dsw-specific-sidebar-nav-item-hover);
61
+ color: var(--dsw-alias-label-primary);
62
+ }
63
+
64
+ .entry[data-active] {
65
+ background: var(--dsw-specific-sidebar-nav-item-active);
66
+ color: var(--dsw-alias-label-primary);
67
+ font-weight: 600;
68
+ }
69
+
70
+ .entryIcon {
71
+ display: inline-flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ flex: none;
75
+ }
76
+
77
+ .entryLabel {
78
+ overflow: hidden;
79
+ text-overflow: ellipsis;
80
+ }
81
+
82
+ /* Collapsed rail: icon-only, centered, matching the shell's 56px rail. */
83
+ [data-dsh-frame][data-sidebar-collapsed] .entry {
84
+ justify-content: center;
85
+ padding: 0;
86
+ width: 100%;
87
+ }
88
+
89
+ [data-dsh-frame][data-sidebar-collapsed] .entryLabel {
90
+ display: none;
91
+ }
92
+
93
+ /* --- panel frame -------------------------------------------------------------- */
94
+
95
+ .view {
96
+ overflow: hidden;
97
+ }
98
+
99
+ /* The shell does not ship a global `box-sizing: border-box` reset, so scope
100
+ one to the panel subtree: without it, `height: 100%` + padding grows past
101
+ the container and clips the footer off the bottom of the screen. */
102
+ .panel,
103
+ .panel *,
104
+ .panel *::before,
105
+ .panel *::after {
106
+ box-sizing: border-box;
107
+ }
108
+
109
+ .panel {
110
+ display: flex;
111
+ flex-direction: column;
112
+ height: 100%;
113
+ min-width: 0;
114
+ min-height: 0;
115
+ overflow: hidden;
116
+ padding: 14px 16px 16px;
117
+ gap: 10px;
118
+ background: var(--dsw-alias-bg-base);
119
+ color: var(--dsw-alias-label-primary);
120
+ font-family: var(--dsw-font-family);
121
+ }
122
+
123
+ .panelHeader {
124
+ display: flex;
125
+ align-items: baseline;
126
+ gap: 10px;
127
+ flex: none;
128
+ }
129
+
130
+ .panelTitle {
131
+ margin: 0;
132
+ font-size: 16px;
133
+ font-weight: 700;
134
+ color: var(--dsw-alias-label-primary);
135
+ white-space: nowrap;
136
+ }
137
+
138
+ .panelSubtitle {
139
+ font-size: 12px;
140
+ color: var(--dsw-alias-label-tertiary);
141
+ white-space: nowrap;
142
+ overflow: hidden;
143
+ text-overflow: ellipsis;
144
+ }
145
+
146
+ /* --- banners ------------------------------------------------------------------ */
147
+
148
+ .banner {
149
+ flex: none;
150
+ padding: 7px 12px;
151
+ font-size: 12px;
152
+ line-height: 1.5;
153
+ border-radius: 10px;
154
+ border: 1px solid var(--dsw-alias-border-l2);
155
+ color: var(--dsw-alias-label-secondary);
156
+ overflow-wrap: anywhere;
157
+ }
158
+
159
+ .banner[data-kind='ok'] {
160
+ color: var(--dsw-alias-state-success-primary);
161
+ border-color: var(--dsw-alias-state-success-primary);
162
+ }
163
+
164
+ .banner[data-kind='warn'] {
165
+ color: var(--dsw-alias-state-warn-primary);
166
+ border-color: var(--dsw-alias-state-warn-primary);
167
+ }
168
+
169
+ /* --- studio split: left config sidebar (narrow) + right canvas (wide) --------- */
170
+
171
+ .studio {
172
+ display: flex;
173
+ gap: 14px;
174
+ flex: 1;
175
+ min-height: 0;
176
+ min-width: 0;
177
+ }
178
+
179
+ .config {
180
+ display: flex;
181
+ flex-direction: column;
182
+ gap: 12px;
183
+ flex: none;
184
+ width: 300px;
185
+ min-width: 260px;
186
+ max-width: 340px;
187
+ height: 100%;
188
+ min-height: 0;
189
+ overflow: hidden;
190
+ }
191
+
192
+ /* The cards scroll in their own scrollport; the footer stays a fixed sibling
193
+ below, so nothing ever hides underneath it (text and edit modes alike). */
194
+ .configScroll {
195
+ display: flex;
196
+ flex-direction: column;
197
+ gap: 12px;
198
+ flex: 1;
199
+ min-height: 0;
200
+ overflow-y: auto;
201
+ padding-right: 2px;
202
+ scrollbar-width: thin;
203
+ scrollbar-color: var(--dsw-alias-border-l2) transparent;
204
+ }
205
+
206
+ .configScroll::-webkit-scrollbar {
207
+ width: 8px;
208
+ }
209
+
210
+ .configScroll::-webkit-scrollbar-thumb {
211
+ background: var(--dsw-alias-border-l2);
212
+ border-radius: 999px;
213
+ }
214
+
215
+ .canvas {
216
+ position: relative;
217
+ flex: 1;
218
+ min-width: 0;
219
+ min-height: 0;
220
+ display: flex;
221
+ flex-direction: column;
222
+ border: 1px solid var(--dsw-alias-border-l1);
223
+ border-radius: 12px;
224
+ background: var(--dsw-alias-bg-layer-1);
225
+ overflow: hidden;
226
+ }
227
+
228
+ /* --- history column (far right) ------------------------------------------------ */
229
+
230
+ .history {
231
+ display: flex;
232
+ flex-direction: column;
233
+ flex: none;
234
+ width: 240px;
235
+ min-width: 200px;
236
+ max-width: 280px;
237
+ min-height: 0;
238
+ border: 1px solid var(--dsw-alias-border-l1);
239
+ border-radius: 12px;
240
+ background: var(--dsw-alias-bg-layer-1);
241
+ overflow: hidden;
242
+ }
243
+
244
+ .historyHeader {
245
+ display: flex;
246
+ align-items: center;
247
+ justify-content: space-between;
248
+ gap: 8px;
249
+ padding: 10px 12px;
250
+ border-bottom: 1px solid var(--dsw-alias-border-l1);
251
+ flex: none;
252
+ }
253
+
254
+ .historyTitle {
255
+ font-size: 13px;
256
+ font-weight: 600;
257
+ color: var(--dsw-alias-label-primary);
258
+ }
259
+
260
+ .historyClear {
261
+ padding: 2px 8px;
262
+ font: inherit;
263
+ font-size: 11.5px;
264
+ color: var(--dsw-alias-label-tertiary);
265
+ background: transparent;
266
+ border: 1px solid var(--dsw-alias-border-l2);
267
+ border-radius: 999px;
268
+ cursor: pointer;
269
+ }
270
+
271
+ .historyClear:hover {
272
+ color: var(--dsw-alias-label-error);
273
+ border-color: var(--dsw-alias-label-error);
274
+ }
275
+
276
+ .historyList {
277
+ flex: 1;
278
+ min-height: 0;
279
+ overflow-y: auto;
280
+ display: flex;
281
+ flex-direction: column;
282
+ gap: 8px;
283
+ padding: 10px;
284
+ scrollbar-width: thin;
285
+ scrollbar-color: var(--dsw-alias-border-l2) transparent;
286
+ }
287
+
288
+ .historyList::-webkit-scrollbar {
289
+ width: 8px;
290
+ }
291
+
292
+ .historyList::-webkit-scrollbar-thumb {
293
+ background: var(--dsw-alias-border-l2);
294
+ border-radius: 999px;
295
+ }
296
+
297
+ .historyEmpty {
298
+ flex: 1;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ padding: 20px;
303
+ font-size: 12px;
304
+ line-height: 1.6;
305
+ text-align: center;
306
+ color: var(--dsw-alias-label-tertiary);
307
+ }
308
+
309
+ .historyItem {
310
+ display: flex;
311
+ flex-direction: column;
312
+ gap: 6px;
313
+ padding: 8px;
314
+ border: 1px solid var(--dsw-alias-border-l1);
315
+ border-radius: 10px;
316
+ background: var(--dsw-alias-bg-layer-2);
317
+ flex: none;
318
+ }
319
+
320
+ .historyItem:hover {
321
+ border-color: var(--dsw-alias-border-l2);
322
+ }
323
+
324
+ .historyItem[data-active] {
325
+ border-color: var(--dsw-alias-brand-primary);
326
+ }
327
+
328
+ .historyMain {
329
+ display: flex;
330
+ gap: 8px;
331
+ align-items: flex-start;
332
+ padding: 0;
333
+ background: transparent;
334
+ border: none;
335
+ font: inherit;
336
+ color: inherit;
337
+ text-align: left;
338
+ cursor: pointer;
339
+ min-width: 0;
340
+ }
341
+
342
+ .historyThumb {
343
+ width: 52px;
344
+ height: 52px;
345
+ border-radius: 8px;
346
+ object-fit: cover;
347
+ background: var(--dsw-alias-bg-base);
348
+ flex: none;
349
+ }
350
+
351
+ .historyThumbPlaceholder {
352
+ width: 52px;
353
+ height: 52px;
354
+ border-radius: 8px;
355
+ background: var(--dsw-alias-bg-layer-3);
356
+ flex: none;
357
+ }
358
+
359
+ .historyInfo {
360
+ flex: 1;
361
+ min-width: 0;
362
+ display: flex;
363
+ flex-direction: column;
364
+ gap: 4px;
365
+ }
366
+
367
+ .historyPrompt {
368
+ font-size: 12px;
369
+ line-height: 1.4;
370
+ color: var(--dsw-alias-label-primary);
371
+ display: -webkit-box;
372
+ -webkit-line-clamp: 2;
373
+ -webkit-box-orient: vertical;
374
+ overflow: hidden;
375
+ }
376
+
377
+ .historyMeta {
378
+ font-size: 11px;
379
+ color: var(--dsw-alias-label-tertiary);
380
+ white-space: nowrap;
381
+ overflow: hidden;
382
+ text-overflow: ellipsis;
383
+ }
384
+
385
+ .historyActions {
386
+ display: flex;
387
+ gap: 6px;
388
+ justify-content: flex-end;
389
+ }
390
+
391
+ .historyAction {
392
+ padding: 2px 8px;
393
+ font: inherit;
394
+ font-size: 11.5px;
395
+ color: var(--dsw-alias-label-secondary);
396
+ background: transparent;
397
+ border: 1px solid var(--dsw-alias-border-l2);
398
+ border-radius: 999px;
399
+ cursor: pointer;
400
+ }
401
+
402
+ .historyAction:hover {
403
+ color: var(--dsw-alias-label-primary);
404
+ border-color: var(--dsw-alias-label-dimmed);
405
+ }
406
+
407
+ .historyAction[data-danger]:hover {
408
+ color: var(--dsw-alias-label-error);
409
+ border-color: var(--dsw-alias-label-error);
410
+ }
411
+
412
+ /* --- cards (system-aligned rounded group chrome) ------------------------------ */
413
+
414
+ .card {
415
+ display: flex;
416
+ flex-direction: column;
417
+ gap: 10px;
418
+ padding: 12px;
419
+ background: var(--dsw-alias-bg-layer-2);
420
+ border: 1px solid var(--dsw-alias-border-l1);
421
+ border-radius: 12px;
422
+ flex: none;
423
+ }
424
+
425
+ /* --- mode tabs (system Pill switcher) ------------------------------------------ */
426
+
427
+ .modeRow {
428
+ display: flex;
429
+ gap: 8px;
430
+ align-items: center;
431
+ }
432
+
433
+ .modePill {
434
+ flex: 1;
435
+ justify-content: center;
436
+ height: 28px;
437
+ font-size: 13px;
438
+ }
439
+
440
+ /* --- reference image upload (edit mode) ---------------------------------------- */
441
+
442
+ .uploadBox {
443
+ display: flex;
444
+ flex-direction: column;
445
+ align-items: center;
446
+ justify-content: center;
447
+ gap: 6px;
448
+ min-height: 128px;
449
+ padding: 16px;
450
+ color: var(--dsw-alias-label-secondary);
451
+ background: transparent;
452
+ border: 1.5px dashed var(--dsw-alias-border-l2);
453
+ border-radius: 12px;
454
+ cursor: pointer;
455
+ font: inherit;
456
+ font-size: 12.5px;
457
+ text-align: center;
458
+ }
459
+
460
+ .uploadBox:hover {
461
+ color: var(--dsw-alias-label-primary);
462
+ border-color: var(--dsw-alias-label-dimmed);
463
+ background: var(--dsw-alias-interactive-bg-hover);
464
+ }
465
+
466
+ .uploadBox:focus-visible {
467
+ outline: 2px solid var(--dsw-alias-brand-primary);
468
+ outline-offset: 1px;
469
+ }
470
+
471
+ .uploadIcon {
472
+ display: inline-flex;
473
+ color: var(--dsw-alias-label-tertiary);
474
+ }
475
+
476
+ .uploadHint {
477
+ font-size: 11px;
478
+ color: var(--dsw-alias-label-tertiary);
479
+ }
480
+
481
+ .reference {
482
+ display: flex;
483
+ flex-direction: column;
484
+ gap: 8px;
485
+ }
486
+
487
+ .referenceImage {
488
+ width: 100%;
489
+ max-height: 176px;
490
+ object-fit: contain;
491
+ border-radius: 10px;
492
+ background: var(--dsw-alias-bg-base);
493
+ border: 1px solid var(--dsw-alias-border-l1);
494
+ }
495
+
496
+ .referenceActions {
497
+ display: flex;
498
+ gap: 8px;
499
+ }
500
+
501
+ .hiddenFile {
502
+ display: none;
503
+ }
504
+
505
+ /* --- prompt -------------------------------------------------------------------- */
506
+
507
+ .prompt {
508
+ width: 100%;
509
+ min-height: 120px;
510
+ padding: 10px 12px;
511
+ font-size: 13px;
512
+ line-height: 1.6;
513
+ color: var(--dsw-alias-label-primary);
514
+ background: var(--dsw-alias-bg-layer-3);
515
+ border: 1px solid var(--dsw-alias-border-l2);
516
+ border-radius: 10px;
517
+ outline: none;
518
+ resize: vertical;
519
+ font-family: inherit;
520
+ box-sizing: border-box;
521
+ }
522
+
523
+ .prompt:focus-visible {
524
+ border-color: var(--dsw-alias-brand-primary);
525
+ }
526
+
527
+ .prompt::placeholder {
528
+ color: var(--dsw-alias-label-tertiary);
529
+ }
530
+
531
+ .promptFooter {
532
+ display: flex;
533
+ justify-content: flex-end;
534
+ margin-top: -6px;
535
+ }
536
+
537
+ .promptCount {
538
+ font-size: 11px;
539
+ color: var(--dsw-alias-label-tertiary);
540
+ font-variant-numeric: tabular-nums;
541
+ }
542
+
543
+ /* --- parameter groups ----------------------------------------------------------- */
544
+
545
+ .paramGroup {
546
+ display: flex;
547
+ flex-direction: column;
548
+ gap: 8px;
549
+ }
550
+
551
+ .paramLabel {
552
+ font-size: 12px;
553
+ font-weight: 600;
554
+ color: var(--dsw-alias-label-secondary);
555
+ }
556
+
557
+ .optionRow {
558
+ display: flex;
559
+ gap: 6px;
560
+ flex-wrap: wrap;
561
+ }
562
+
563
+ .optionGrid {
564
+ display: grid;
565
+ grid-template-columns: repeat(3, 1fr);
566
+ gap: 6px;
567
+ }
568
+
569
+ .optionPill {
570
+ justify-content: center;
571
+ }
572
+
573
+ .paramHint {
574
+ font-size: 11px;
575
+ line-height: 1.45;
576
+ color: var(--dsw-alias-label-tertiary);
577
+ }
578
+
579
+ /* --- footer: model dropdown + generate button (fixed under the scroll) -------- */
580
+
581
+ .footer {
582
+ display: flex;
583
+ flex-direction: column;
584
+ align-items: stretch;
585
+ gap: 8px;
586
+ flex: none;
587
+ padding: 10px 2px 0 0;
588
+ border-top: 1px solid var(--dsw-alias-border-l1);
589
+ }
590
+
591
+ .modelWrap {
592
+ display: flex;
593
+ flex-direction: column;
594
+ gap: 5px;
595
+ min-width: 0;
596
+ }
597
+
598
+ .modelLabel {
599
+ font-size: 12px;
600
+ font-weight: 600;
601
+ color: var(--dsw-alias-label-secondary);
602
+ }
603
+
604
+ .modelSelect {
605
+ width: 100%;
606
+ height: 36px;
607
+ padding: 0 12px;
608
+ font-size: 13px;
609
+ color: var(--dsw-alias-label-primary);
610
+ background: var(--dsw-alias-bg-layer-2);
611
+ border: 1px solid var(--dsw-alias-border-l2);
612
+ border-radius: 18px;
613
+ outline: none;
614
+ font-family: inherit;
615
+ cursor: pointer;
616
+ }
617
+
618
+ .modelSelect:focus-visible {
619
+ border-color: var(--dsw-alias-brand-primary);
620
+ }
621
+
622
+ .modelSelect:disabled {
623
+ opacity: 0.55;
624
+ }
625
+
626
+ .generateButton {
627
+ width: 100%;
628
+ }
629
+
630
+ .generateInner {
631
+ display: inline-flex;
632
+ align-items: center;
633
+ gap: 7px;
634
+ }
635
+
636
+ /* --- canvas states --------------------------------------------------------------- */
637
+
638
+ .canvasState {
639
+ flex: 1;
640
+ display: flex;
641
+ flex-direction: column;
642
+ align-items: center;
643
+ justify-content: center;
644
+ gap: 8px;
645
+ padding: 24px;
646
+ text-align: center;
647
+ color: var(--dsw-alias-label-tertiary);
648
+ }
649
+
650
+ .canvasStateTitle {
651
+ font-size: 14px;
652
+ font-weight: 600;
653
+ color: var(--dsw-alias-label-secondary);
654
+ }
655
+
656
+ .canvasStateHint {
657
+ font-size: 12px;
658
+ max-width: 380px;
659
+ line-height: 1.6;
660
+ }
661
+
662
+ .canvasEmptyIcon {
663
+ display: inline-flex;
664
+ margin-bottom: 4px;
665
+ color: var(--dsw-alias-label-tertiary);
666
+ }
667
+
668
+ .canvasError {
669
+ margin: 14px;
670
+ padding: 10px 14px;
671
+ font-size: 12.5px;
672
+ line-height: 1.6;
673
+ color: var(--dsw-alias-label-error);
674
+ background: var(--dsw-alias-bg-layer-2);
675
+ border: 1px solid var(--dsw-alias-label-error);
676
+ border-radius: 10px;
677
+ overflow-wrap: anywhere;
678
+ flex: none;
679
+ }
680
+
681
+ .canvasBody {
682
+ flex: 1;
683
+ min-height: 0;
684
+ display: flex;
685
+ flex-direction: column;
686
+ gap: 10px;
687
+ overflow-y: auto;
688
+ padding: 14px;
689
+ scrollbar-width: thin;
690
+ scrollbar-color: var(--dsw-alias-border-l2) transparent;
691
+ }
692
+
693
+ .canvasBody::-webkit-scrollbar {
694
+ width: 8px;
695
+ }
696
+
697
+ .canvasBody::-webkit-scrollbar-thumb {
698
+ background: var(--dsw-alias-border-l2);
699
+ border-radius: 999px;
700
+ }
701
+
702
+ .canvasMeta {
703
+ flex: none;
704
+ display: flex;
705
+ align-items: center;
706
+ gap: 8px;
707
+ font-size: 12px;
708
+ color: var(--dsw-alias-label-tertiary);
709
+ }
710
+
711
+ .canvasHistoryTag {
712
+ padding: 1px 8px;
713
+ font-size: 11px;
714
+ color: var(--dsw-alias-label-secondary);
715
+ background: var(--dsw-alias-bg-layer-2);
716
+ border: 1px solid var(--dsw-alias-border-l2);
717
+ border-radius: 999px;
718
+ white-space: nowrap;
719
+ }
720
+
721
+ /* --- result grid ----------------------------------------------------------------- */
722
+
723
+ .grid {
724
+ display: grid;
725
+ grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
726
+ gap: 14px;
727
+ align-content: start;
728
+ }
729
+
730
+ .imageCard {
731
+ position: relative;
732
+ display: flex;
733
+ flex-direction: column;
734
+ margin: 0;
735
+ border: 1px solid var(--dsw-alias-border-l1);
736
+ border-radius: 12px;
737
+ overflow: hidden;
738
+ background: var(--dsw-alias-bg-layer-2);
739
+ cursor: zoom-in;
740
+ }
741
+
742
+ .imageCard:focus-visible {
743
+ outline: 2px solid var(--dsw-alias-brand-primary);
744
+ outline-offset: 1px;
745
+ }
746
+
747
+ .image {
748
+ display: block;
749
+ width: 100%;
750
+ aspect-ratio: 1 / 1;
751
+ object-fit: cover;
752
+ background: var(--dsw-alias-bg-base);
753
+ }
754
+
755
+ .imageCaption {
756
+ padding: 7px 10px;
757
+ font-size: 11px;
758
+ line-height: 1.5;
759
+ color: var(--dsw-alias-label-tertiary);
760
+ white-space: nowrap;
761
+ overflow: hidden;
762
+ text-overflow: ellipsis;
763
+ border-top: 1px solid var(--dsw-alias-border-l1);
764
+ }
765
+
766
+ .download {
767
+ position: absolute;
768
+ top: 8px;
769
+ right: 8px;
770
+ padding: 2px 10px;
771
+ font-size: 12px;
772
+ line-height: 20px;
773
+ font-weight: 500;
774
+ color: var(--dsw-alias-label-primary);
775
+ background: var(--dsw-alias-bg-mask-1);
776
+ border: 1px solid var(--dsw-alias-border-l2);
777
+ border-radius: 999px;
778
+ text-decoration: none;
779
+ opacity: 0;
780
+ transition: opacity 0.12s;
781
+ backdrop-filter: blur(4px);
782
+ }
783
+
784
+ .imageCard:hover .download {
785
+ opacity: 1;
786
+ }
787
+
788
+ .download:hover {
789
+ background: var(--dsw-alias-bg-base);
790
+ }
791
+
792
+ /* Hover hint for the click-to-zoom behavior. */
793
+ .zoomHint {
794
+ position: absolute;
795
+ left: 8px;
796
+ bottom: 8px;
797
+ display: inline-flex;
798
+ align-items: center;
799
+ gap: 5px;
800
+ padding: 2px 10px;
801
+ font-size: 12px;
802
+ line-height: 20px;
803
+ font-weight: 500;
804
+ color: var(--dsw-alias-label-primary);
805
+ background: var(--dsw-alias-bg-mask-1);
806
+ border: 1px solid var(--dsw-alias-border-l2);
807
+ border-radius: 999px;
808
+ opacity: 0;
809
+ transition: opacity 0.12s;
810
+ backdrop-filter: blur(4px);
811
+ pointer-events: none;
812
+ }
813
+
814
+ .imageCard:hover .zoomHint {
815
+ opacity: 1;
816
+ }
817
+
818
+ /* --- spinner --------------------------------------------------------------------- */
819
+
820
+ .spinner,
821
+ .bigSpinner {
822
+ display: inline-block;
823
+ flex: none;
824
+ border-radius: 50%;
825
+ border: 2px solid currentColor;
826
+ border-top-color: transparent;
827
+ animation: dshImageGenSpin 800ms linear infinite;
828
+ }
829
+
830
+ .spinner {
831
+ width: 11px;
832
+ height: 11px;
833
+ }
834
+
835
+ .bigSpinner {
836
+ width: 30px;
837
+ height: 30px;
838
+ border-width: 3px;
839
+ color: var(--dsw-alias-state-business-primary);
840
+ margin-bottom: 6px;
841
+ }
842
+
843
+ /* --- full-screen image preview (lightbox) -------------------------------------- */
844
+
845
+ .lightbox {
846
+ position: fixed;
847
+ inset: 0;
848
+ z-index: 1000;
849
+ display: flex;
850
+ align-items: center;
851
+ justify-content: center;
852
+ padding: 24px;
853
+ background: rgba(0, 0, 0, 0.72);
854
+ backdrop-filter: blur(6px);
855
+ }
856
+
857
+ .lightboxClose {
858
+ position: absolute;
859
+ top: 16px;
860
+ right: 16px;
861
+ display: inline-flex;
862
+ align-items: center;
863
+ justify-content: center;
864
+ width: 38px;
865
+ height: 38px;
866
+ color: #fff;
867
+ background: rgba(255, 255, 255, 0.14);
868
+ border: 1px solid rgba(255, 255, 255, 0.28);
869
+ border-radius: 50%;
870
+ cursor: pointer;
871
+ }
872
+
873
+ .lightboxClose:hover {
874
+ background: rgba(255, 255, 255, 0.26);
875
+ }
876
+
877
+ .lightboxNav {
878
+ position: absolute;
879
+ top: 50%;
880
+ transform: translateY(-50%);
881
+ display: inline-flex;
882
+ align-items: center;
883
+ justify-content: center;
884
+ width: 42px;
885
+ height: 42px;
886
+ color: #fff;
887
+ background: rgba(255, 255, 255, 0.14);
888
+ border: 1px solid rgba(255, 255, 255, 0.28);
889
+ border-radius: 50%;
890
+ cursor: pointer;
891
+ }
892
+
893
+ .lightboxNav:hover {
894
+ background: rgba(255, 255, 255, 0.26);
895
+ }
896
+
897
+ .lightboxNav[data-dir='prev'] {
898
+ left: 16px;
899
+ }
900
+
901
+ .lightboxNav[data-dir='next'] {
902
+ right: 16px;
903
+ }
904
+
905
+ .lightboxFigure {
906
+ display: flex;
907
+ flex-direction: column;
908
+ gap: 10px;
909
+ margin: 0;
910
+ max-width: min(1100px, calc(100vw - 160px));
911
+ max-height: calc(100vh - 48px);
912
+ }
913
+
914
+ .lightboxImage {
915
+ max-width: 100%;
916
+ max-height: calc(100vh - 160px);
917
+ object-fit: contain;
918
+ border-radius: 10px;
919
+ box-shadow: 0 24px 80px rgba(0, 0, 0, 0.5);
920
+ background: rgba(255, 255, 255, 0.04);
921
+ }
922
+
923
+ .lightboxCaption {
924
+ font-size: 12px;
925
+ line-height: 1.6;
926
+ color: rgba(255, 255, 255, 0.9);
927
+ display: -webkit-box;
928
+ -webkit-line-clamp: 3;
929
+ -webkit-box-orient: vertical;
930
+ overflow: hidden;
931
+ }
932
+
933
+ .lightboxMeta {
934
+ display: flex;
935
+ align-items: center;
936
+ justify-content: space-between;
937
+ gap: 12px;
938
+ }
939
+
940
+ .lightboxIndex {
941
+ font-size: 12px;
942
+ color: rgba(255, 255, 255, 0.8);
943
+ font-variant-numeric: tabular-nums;
944
+ }
945
+
946
+ .lightboxDownload {
947
+ padding: 4px 14px;
948
+ font-size: 12.5px;
949
+ font-weight: 500;
950
+ color: #fff;
951
+ background: rgba(255, 255, 255, 0.14);
952
+ border: 1px solid rgba(255, 255, 255, 0.28);
953
+ border-radius: 999px;
954
+ text-decoration: none;
955
+ }
956
+
957
+ .lightboxDownload:hover {
958
+ background: rgba(255, 255, 255, 0.26);
959
+ }
960
+
961
+ @keyframes dshImageGenSpin {
962
+ to { transform: rotate(360deg); }
963
+ }
964
+
965
+ @media (prefers-reduced-motion: reduce) {
966
+ .download, .spinner, .bigSpinner {
967
+ transition: none;
968
+ animation-duration: 1.5s;
969
+ }
970
+ }