@withwiz/gallery 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.ko.md +484 -0
  2. package/README.md +484 -0
  3. package/dist/chunk-B3MQL6ZR.mjs +79 -0
  4. package/dist/chunk-B3MQL6ZR.mjs.map +1 -0
  5. package/dist/chunk-BC3TPJQY.mjs +122 -0
  6. package/dist/chunk-BC3TPJQY.mjs.map +1 -0
  7. package/dist/chunk-BTLELFKC.mjs +11 -0
  8. package/dist/chunk-BTLELFKC.mjs.map +1 -0
  9. package/dist/chunk-GDUGKVDQ.mjs +50 -0
  10. package/dist/chunk-GDUGKVDQ.mjs.map +1 -0
  11. package/dist/chunk-GFOWZGJX.js +50 -0
  12. package/dist/chunk-GFOWZGJX.js.map +1 -0
  13. package/dist/chunk-ILSZPLME.js +47 -0
  14. package/dist/chunk-ILSZPLME.js.map +1 -0
  15. package/dist/chunk-M7CCTDUG.js +122 -0
  16. package/dist/chunk-M7CCTDUG.js.map +1 -0
  17. package/dist/chunk-WVRTM6E7.js +19 -0
  18. package/dist/chunk-WVRTM6E7.js.map +1 -0
  19. package/dist/chunk-XLPMNJJV.js +11 -0
  20. package/dist/chunk-XLPMNJJV.js.map +1 -0
  21. package/dist/chunk-XSPWM4DD.js +79 -0
  22. package/dist/chunk-XSPWM4DD.js.map +1 -0
  23. package/dist/chunk-YUMB3GBN.mjs +47 -0
  24. package/dist/chunk-YUMB3GBN.mjs.map +1 -0
  25. package/dist/chunk-ZEZCUJJD.mjs +19 -0
  26. package/dist/chunk-ZEZCUJJD.mjs.map +1 -0
  27. package/dist/components/gallery.css +1074 -0
  28. package/dist/components/index.d.mts +156 -0
  29. package/dist/components/index.d.ts +156 -0
  30. package/dist/components/index.js +1215 -0
  31. package/dist/components/index.js.map +1 -0
  32. package/dist/components/index.mjs +1215 -0
  33. package/dist/components/index.mjs.map +1 -0
  34. package/dist/errors-B9gzUsX-.d.ts +39 -0
  35. package/dist/errors-DYrlDCzP.d.mts +39 -0
  36. package/dist/gallery.css +1074 -0
  37. package/dist/hooks/index.d.mts +65 -0
  38. package/dist/hooks/index.d.ts +65 -0
  39. package/dist/hooks/index.js +14 -0
  40. package/dist/hooks/index.js.map +1 -0
  41. package/dist/hooks/index.mjs +14 -0
  42. package/dist/hooks/index.mjs.map +1 -0
  43. package/dist/index.d.mts +17 -0
  44. package/dist/index.d.ts +17 -0
  45. package/dist/index.js +37 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/index.mjs +37 -0
  48. package/dist/index.mjs.map +1 -0
  49. package/dist/presets/ballet.d.mts +64 -0
  50. package/dist/presets/ballet.d.ts +64 -0
  51. package/dist/presets/ballet.js +162 -0
  52. package/dist/presets/ballet.js.map +1 -0
  53. package/dist/presets/ballet.mjs +162 -0
  54. package/dist/presets/ballet.mjs.map +1 -0
  55. package/dist/server/index.d.mts +157 -0
  56. package/dist/server/index.d.ts +157 -0
  57. package/dist/server/index.js +619 -0
  58. package/dist/server/index.js.map +1 -0
  59. package/dist/server/index.mjs +619 -0
  60. package/dist/server/index.mjs.map +1 -0
  61. package/dist/types/index.d.mts +137 -0
  62. package/dist/types/index.d.ts +137 -0
  63. package/dist/types/index.js +1 -0
  64. package/dist/types/index.js.map +1 -0
  65. package/dist/types/index.mjs +1 -0
  66. package/dist/types/index.mjs.map +1 -0
  67. package/dist/useGalleryLightbox-BYzPyBYB.d.mts +22 -0
  68. package/dist/useGalleryLightbox-BYzPyBYB.d.ts +22 -0
  69. package/dist/validators/index.d.mts +68 -0
  70. package/dist/validators/index.d.ts +68 -0
  71. package/dist/validators/index.js +7 -0
  72. package/dist/validators/index.js.map +1 -0
  73. package/dist/validators/index.mjs +7 -0
  74. package/dist/validators/index.mjs.map +1 -0
  75. package/package.json +85 -0
  76. package/prisma/gallery.schema.prisma +62 -0
  77. package/prisma/migrations/2026-05-24-enum-to-table.sql +65 -0
@@ -0,0 +1,1074 @@
1
+ /* ═══════════════════════════════════════════════════════════════
2
+ * @withwiz/gallery — primitive UI styles
3
+ * ────────────────────────────────────────────────────────────────
4
+ * - CSS variables: --gallery-accent / --gallery-bg / --gallery-fg / --gallery-border
5
+ * (RGB triplet, host 가 :root 에서 override)
6
+ * - 클래스 prefix: `gallery-` (충돌 회피)
7
+ * - Tailwind 와 호환 — 컴포넌트는 Tailwind 클래스도 함께 사용 가능
8
+ * ═══════════════════════════════════════════════════════════════ */
9
+
10
+ :where(
11
+ .gallery-toggle,
12
+ .gallery-dropzone,
13
+ .gallery-dropzone-wrap,
14
+ .gallery-manager,
15
+ .gallery-edit-form,
16
+ .gallery-home-preview,
17
+ .gallery-category-admin,
18
+ .gallery-public-mosaic-section,
19
+ .gallery-public-mosaic,
20
+ .gallery-lightbox
21
+ ) {
22
+ --gallery-accent: 212 175 55;
23
+ --gallery-bg: 10 10 10;
24
+ --gallery-fg: 254 254 254;
25
+ --gallery-border: 30 30 30;
26
+ }
27
+
28
+ /* ─── Toggle Switch ─── */
29
+
30
+ .gallery-toggle {
31
+ display: inline-flex;
32
+ align-items: center;
33
+ gap: 8px;
34
+ user-select: none;
35
+ }
36
+
37
+ .gallery-toggle__track {
38
+ position: relative;
39
+ display: inline-block;
40
+ flex-shrink: 0;
41
+ width: 36px;
42
+ height: 20px;
43
+ padding: 0;
44
+ border: 0;
45
+ border-radius: 999px;
46
+ background: rgb(var(--gallery-border));
47
+ cursor: pointer;
48
+ transition: background 0.2s ease;
49
+ }
50
+
51
+ .gallery-toggle__track:focus-visible {
52
+ outline: 2px solid rgb(var(--gallery-accent));
53
+ outline-offset: 2px;
54
+ }
55
+
56
+ .gallery-toggle__thumb {
57
+ position: absolute;
58
+ top: 2px;
59
+ left: 2px;
60
+ width: 16px;
61
+ height: 16px;
62
+ border-radius: 50%;
63
+ background: rgb(var(--gallery-fg));
64
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
65
+ transition: left 0.2s ease, transform 0.2s ease;
66
+ }
67
+
68
+ .gallery-toggle__track.gallery-toggle--checked {
69
+ background: rgb(var(--gallery-accent));
70
+ }
71
+
72
+ .gallery-toggle__track.gallery-toggle--checked .gallery-toggle__thumb {
73
+ left: 18px;
74
+ }
75
+
76
+ .gallery-toggle__track.gallery-toggle--disabled {
77
+ cursor: not-allowed;
78
+ opacity: 0.5;
79
+ }
80
+
81
+ .gallery-toggle__label {
82
+ font-size: 13px;
83
+ color: rgb(var(--gallery-fg));
84
+ }
85
+
86
+ /* size modifiers */
87
+
88
+ .gallery-toggle--sm .gallery-toggle__track {
89
+ width: 28px;
90
+ height: 16px;
91
+ }
92
+
93
+ .gallery-toggle--sm .gallery-toggle__thumb {
94
+ width: 12px;
95
+ height: 12px;
96
+ }
97
+
98
+ .gallery-toggle--sm .gallery-toggle__track.gallery-toggle--checked .gallery-toggle__thumb {
99
+ left: 14px;
100
+ }
101
+
102
+ .gallery-toggle--lg .gallery-toggle__track {
103
+ width: 48px;
104
+ height: 26px;
105
+ }
106
+
107
+ .gallery-toggle--lg .gallery-toggle__thumb {
108
+ width: 22px;
109
+ height: 22px;
110
+ }
111
+
112
+ .gallery-toggle--lg .gallery-toggle__track.gallery-toggle--checked .gallery-toggle__thumb {
113
+ left: 24px;
114
+ }
115
+
116
+ /* ─── Image Drop Zone ─── */
117
+
118
+ .gallery-dropzone-wrap {
119
+ position: relative;
120
+ display: block;
121
+ }
122
+
123
+ .gallery-dropzone {
124
+ position: relative;
125
+ display: flex;
126
+ align-items: center;
127
+ justify-content: center;
128
+ width: 100%;
129
+ min-height: 160px;
130
+ border: 2px dashed rgb(var(--gallery-border));
131
+ border-radius: 8px;
132
+ background: rgb(var(--gallery-bg) / 0.4);
133
+ color: rgb(var(--gallery-fg));
134
+ cursor: pointer;
135
+ overflow: hidden;
136
+ transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
137
+ }
138
+
139
+ .gallery-dropzone:focus-visible {
140
+ outline: 2px solid rgb(var(--gallery-accent));
141
+ outline-offset: 2px;
142
+ }
143
+
144
+ .gallery-dropzone--dragging {
145
+ border-color: rgb(var(--gallery-accent));
146
+ background: rgb(var(--gallery-accent) / 0.08);
147
+ box-shadow: inset 0 0 0 2px rgb(var(--gallery-accent) / 0.2);
148
+ }
149
+
150
+ .gallery-dropzone--disabled {
151
+ cursor: not-allowed;
152
+ opacity: 0.5;
153
+ pointer-events: none;
154
+ }
155
+
156
+ .gallery-dropzone--has-preview {
157
+ min-height: auto;
158
+ padding: 0;
159
+ background: rgb(var(--gallery-bg));
160
+ }
161
+
162
+ .gallery-dropzone__preview {
163
+ display: block;
164
+ width: 100%;
165
+ height: auto;
166
+ max-height: 320px;
167
+ object-fit: contain;
168
+ }
169
+
170
+ .gallery-dropzone__prompt {
171
+ display: flex;
172
+ align-items: center;
173
+ justify-content: center;
174
+ padding: 16px;
175
+ font-size: 13px;
176
+ color: rgb(var(--gallery-fg) / 0.7);
177
+ text-align: center;
178
+ pointer-events: none;
179
+ }
180
+
181
+ .gallery-dropzone__prompt--overlay {
182
+ position: absolute;
183
+ inset: 0;
184
+ background: rgb(var(--gallery-bg) / 0.6);
185
+ color: rgb(var(--gallery-fg));
186
+ opacity: 0;
187
+ transition: opacity 0.15s ease;
188
+ }
189
+
190
+ .gallery-dropzone--dragging .gallery-dropzone__prompt--overlay {
191
+ opacity: 1;
192
+ }
193
+
194
+ .gallery-dropzone__rejected {
195
+ margin: 8px 0 0;
196
+ padding: 8px 12px;
197
+ list-style: none;
198
+ font-size: 12px;
199
+ color: rgb(220 80 80);
200
+ background: rgb(220 80 80 / 0.08);
201
+ border: 1px solid rgb(220 80 80 / 0.3);
202
+ border-radius: 6px;
203
+ }
204
+
205
+ .gallery-dropzone__rejected-title {
206
+ font-weight: 600;
207
+ margin-bottom: 4px;
208
+ }
209
+
210
+ .gallery-dropzone__rejected-item {
211
+ line-height: 1.5;
212
+ }
213
+
214
+ /* ─── Manager Layout (3-pane) ─── */
215
+
216
+ .gallery-manager {
217
+ display: grid;
218
+ gap: 16px;
219
+ color: rgb(var(--gallery-fg));
220
+ background: rgb(var(--gallery-bg));
221
+ min-height: 100vh;
222
+ padding: 12px;
223
+ grid-template-columns: 1fr;
224
+ }
225
+
226
+ @media (min-width: 1024px) {
227
+ .gallery-manager--with-preview {
228
+ grid-template-columns: minmax(280px, 360px) minmax(420px, 1fr) minmax(280px, 420px);
229
+ grid-template-areas: "list form preview";
230
+ }
231
+ .gallery-manager--no-preview {
232
+ grid-template-columns: minmax(280px, 360px) minmax(420px, 1fr);
233
+ grid-template-areas: "list form";
234
+ }
235
+ .gallery-manager__list { grid-area: list; }
236
+ .gallery-manager__form { grid-area: form; }
237
+ .gallery-manager__preview { grid-area: preview; }
238
+ }
239
+
240
+ .gallery-manager__list,
241
+ .gallery-manager__form,
242
+ .gallery-manager__preview {
243
+ border: 1px solid rgb(var(--gallery-border));
244
+ border-radius: 8px;
245
+ background: rgb(var(--gallery-bg));
246
+ padding: 12px;
247
+ overflow: auto;
248
+ max-height: calc(100vh - 24px);
249
+ }
250
+
251
+ .gallery-manager__toolbar {
252
+ display: flex;
253
+ justify-content: space-between;
254
+ align-items: center;
255
+ padding-bottom: 8px;
256
+ border-bottom: 1px solid rgb(var(--gallery-border));
257
+ margin-bottom: 8px;
258
+ }
259
+
260
+ .gallery-manager__toolbar-row {
261
+ display: flex;
262
+ align-items: center;
263
+ justify-content: space-between;
264
+ gap: 8px;
265
+ width: 100%;
266
+ }
267
+
268
+ .gallery-manager__title {
269
+ font-size: 16px;
270
+ font-weight: 600;
271
+ margin: 0;
272
+ }
273
+
274
+ .gallery-manager__new-btn {
275
+ background: rgb(var(--gallery-accent));
276
+ color: rgb(var(--gallery-bg));
277
+ border: 0;
278
+ border-radius: 4px;
279
+ padding: 6px 12px;
280
+ font-weight: 600;
281
+ cursor: pointer;
282
+ }
283
+
284
+ .gallery-manager__filter {
285
+ margin-bottom: 8px;
286
+ }
287
+
288
+ .gallery-manager__filter-controls {
289
+ display: flex;
290
+ align-items: center;
291
+ gap: 8px;
292
+ }
293
+
294
+ .gallery-manager__search {
295
+ flex: 1;
296
+ padding: 6px 8px;
297
+ border: 1px solid rgb(var(--gallery-border));
298
+ border-radius: 4px;
299
+ background: rgb(var(--gallery-bg));
300
+ color: rgb(var(--gallery-fg));
301
+ font-size: 13px;
302
+ }
303
+
304
+ .gallery-manager__count {
305
+ font-size: 12px;
306
+ color: rgb(var(--gallery-fg) / 0.7);
307
+ }
308
+
309
+ .gallery-manager__list-body {
310
+ margin-top: 4px;
311
+ }
312
+
313
+ .gallery-manager__list-ul {
314
+ list-style: none;
315
+ margin: 0;
316
+ padding: 0;
317
+ display: flex;
318
+ flex-direction: column;
319
+ gap: 6px;
320
+ }
321
+
322
+ .gallery-manager__empty {
323
+ display: flex;
324
+ align-items: center;
325
+ justify-content: center;
326
+ height: 100%;
327
+ min-height: 240px;
328
+ color: rgb(var(--gallery-fg) / 0.5);
329
+ font-size: 13px;
330
+ }
331
+
332
+ /* ─── List Item ─── */
333
+
334
+ .gallery-list-item {
335
+ display: flex;
336
+ gap: 10px;
337
+ align-items: center;
338
+ padding: 6px;
339
+ border: 1px solid transparent;
340
+ border-radius: 6px;
341
+ cursor: pointer;
342
+ background: rgb(var(--gallery-bg));
343
+ transition: background 0.15s ease, border-color 0.15s ease;
344
+ }
345
+
346
+ .gallery-list-item:hover {
347
+ background: rgb(var(--gallery-fg) / 0.04);
348
+ }
349
+
350
+ .gallery-list-item--active {
351
+ border-color: rgb(var(--gallery-accent));
352
+ background: rgb(var(--gallery-accent) / 0.06);
353
+ }
354
+
355
+ .gallery-list-item__thumb {
356
+ width: 60px;
357
+ height: 40px;
358
+ object-fit: cover;
359
+ border-radius: 4px;
360
+ flex-shrink: 0;
361
+ }
362
+
363
+ .gallery-list-item__body {
364
+ flex: 1;
365
+ min-width: 0;
366
+ }
367
+
368
+ .gallery-list-item__caption {
369
+ font-size: 13px;
370
+ white-space: nowrap;
371
+ overflow: hidden;
372
+ text-overflow: ellipsis;
373
+ }
374
+
375
+ .gallery-list-item__meta {
376
+ font-size: 11px;
377
+ color: rgb(var(--gallery-fg) / 0.6);
378
+ }
379
+
380
+ /* ─── Edit Form ─── */
381
+
382
+ .gallery-edit-form {
383
+ display: flex;
384
+ flex-direction: column;
385
+ gap: 16px;
386
+ color: rgb(var(--gallery-fg));
387
+ }
388
+
389
+ .gallery-edit-form__header {
390
+ display: flex;
391
+ align-items: center;
392
+ justify-content: space-between;
393
+ gap: 12px;
394
+ flex-wrap: wrap;
395
+ border-bottom: 1px solid rgb(var(--gallery-border));
396
+ padding-bottom: 10px;
397
+ }
398
+
399
+ .gallery-edit-form__title {
400
+ font-size: 16px;
401
+ font-weight: 600;
402
+ margin: 0;
403
+ }
404
+
405
+ .gallery-edit-form__actions {
406
+ display: flex;
407
+ gap: 8px;
408
+ align-items: center;
409
+ flex-wrap: wrap;
410
+ }
411
+
412
+ .gallery-edit-form__btn {
413
+ background: transparent;
414
+ color: rgb(var(--gallery-fg));
415
+ border: 1px solid rgb(var(--gallery-border));
416
+ border-radius: 4px;
417
+ padding: 6px 12px;
418
+ font-size: 13px;
419
+ cursor: pointer;
420
+ }
421
+
422
+ .gallery-edit-form__btn:hover { background: rgb(var(--gallery-fg) / 0.06); }
423
+
424
+ .gallery-edit-form__btn--primary {
425
+ background: rgb(var(--gallery-accent));
426
+ color: rgb(var(--gallery-bg));
427
+ border-color: rgb(var(--gallery-accent));
428
+ font-weight: 600;
429
+ }
430
+
431
+ .gallery-edit-form__btn--danger {
432
+ color: rgb(220 80 80);
433
+ border-color: rgb(220 80 80 / 0.5);
434
+ }
435
+
436
+ .gallery-edit-form__section {
437
+ display: flex;
438
+ flex-direction: column;
439
+ gap: 6px;
440
+ }
441
+
442
+ .gallery-edit-form__section-title {
443
+ font-size: 12px;
444
+ font-weight: 600;
445
+ color: rgb(var(--gallery-fg) / 0.8);
446
+ text-transform: uppercase;
447
+ letter-spacing: 0.04em;
448
+ }
449
+
450
+ .gallery-edit-form__row {
451
+ display: grid;
452
+ grid-template-columns: 1fr 1fr;
453
+ gap: 12px;
454
+ }
455
+
456
+ .gallery-edit-form__input {
457
+ width: 100%;
458
+ padding: 8px 10px;
459
+ border: 1px solid rgb(var(--gallery-border));
460
+ border-radius: 4px;
461
+ background: rgb(var(--gallery-bg));
462
+ color: rgb(var(--gallery-fg));
463
+ font-size: 13px;
464
+ }
465
+
466
+ .gallery-edit-form__input:focus-visible {
467
+ outline: 2px solid rgb(var(--gallery-accent));
468
+ outline-offset: 1px;
469
+ }
470
+
471
+ .gallery-edit-form__hint {
472
+ font-size: 11px;
473
+ color: rgb(var(--gallery-fg) / 0.6);
474
+ }
475
+
476
+ .gallery-edit-form__note {
477
+ font-size: 11px;
478
+ color: rgb(220 80 80);
479
+ }
480
+
481
+ .gallery-edit-form__error {
482
+ font-size: 12px;
483
+ color: rgb(220 80 80);
484
+ background: rgb(220 80 80 / 0.08);
485
+ padding: 6px 8px;
486
+ border-radius: 4px;
487
+ }
488
+
489
+ .gallery-edit-form__multi-grid {
490
+ display: grid;
491
+ grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
492
+ gap: 6px;
493
+ margin-top: 8px;
494
+ }
495
+
496
+ .gallery-edit-form__multi-tile {
497
+ position: relative;
498
+ aspect-ratio: 1;
499
+ border-radius: 4px;
500
+ overflow: hidden;
501
+ border: 1px solid rgb(var(--gallery-border));
502
+ }
503
+
504
+ .gallery-edit-form__multi-img {
505
+ width: 100%;
506
+ height: 100%;
507
+ object-fit: cover;
508
+ display: block;
509
+ }
510
+
511
+ .gallery-edit-form__multi-remove {
512
+ position: absolute;
513
+ top: 4px;
514
+ right: 4px;
515
+ width: 18px;
516
+ height: 18px;
517
+ border-radius: 50%;
518
+ background: rgba(0, 0, 0, 0.7);
519
+ color: #fff;
520
+ border: 0;
521
+ cursor: pointer;
522
+ font-size: 11px;
523
+ line-height: 1;
524
+ display: flex;
525
+ align-items: center;
526
+ justify-content: center;
527
+ }
528
+
529
+ /* ─── Home Preview (mosaic) ─── */
530
+
531
+ .gallery-home-preview {
532
+ display: flex;
533
+ flex-direction: column;
534
+ gap: 10px;
535
+ }
536
+
537
+ .gallery-home-preview__header {
538
+ display: flex;
539
+ justify-content: space-between;
540
+ align-items: baseline;
541
+ }
542
+
543
+ .gallery-home-preview__title {
544
+ font-size: 14px;
545
+ font-weight: 600;
546
+ margin: 0;
547
+ }
548
+
549
+ .gallery-home-preview__count {
550
+ font-size: 12px;
551
+ color: rgb(var(--gallery-fg) / 0.7);
552
+ }
553
+
554
+ .gallery-home-preview__hint {
555
+ font-size: 11px;
556
+ color: rgb(var(--gallery-fg) / 0.6);
557
+ }
558
+
559
+ .gallery-home-preview__empty {
560
+ padding: 20px;
561
+ text-align: center;
562
+ color: rgb(var(--gallery-fg) / 0.5);
563
+ border: 1px dashed rgb(var(--gallery-border));
564
+ border-radius: 6px;
565
+ font-size: 13px;
566
+ }
567
+
568
+ .gallery-home-preview__mosaic {
569
+ display: grid;
570
+ gap: 4px;
571
+ width: 100%;
572
+ aspect-ratio: 16 / 10;
573
+ grid-template-columns: repeat(4, 1fr);
574
+ grid-template-rows: repeat(3, 1fr);
575
+ }
576
+
577
+ .gallery-home-preview__mosaic[data-count="1"] {
578
+ grid-template-columns: 1fr;
579
+ grid-template-rows: 1fr;
580
+ }
581
+
582
+ .gallery-home-preview__mosaic[data-count="4"] {
583
+ grid-template-columns: 1fr 1fr;
584
+ grid-template-rows: 1fr 1fr;
585
+ }
586
+
587
+ .gallery-home-preview__mosaic[data-count="7"] > .gallery-home-preview__tile:nth-child(1) {
588
+ grid-column: span 2;
589
+ grid-row: span 2;
590
+ }
591
+
592
+ .gallery-home-preview__tile {
593
+ position: relative;
594
+ overflow: hidden;
595
+ border-radius: 4px;
596
+ border: 1px solid rgb(var(--gallery-border));
597
+ background: rgb(var(--gallery-bg));
598
+ cursor: grab;
599
+ }
600
+
601
+ .gallery-home-preview__tile--empty {
602
+ display: flex;
603
+ align-items: center;
604
+ justify-content: center;
605
+ color: rgb(var(--gallery-fg) / 0.3);
606
+ cursor: default;
607
+ }
608
+
609
+ .gallery-home-preview__tile--drag-over {
610
+ outline: 2px solid rgb(var(--gallery-accent));
611
+ outline-offset: -2px;
612
+ }
613
+
614
+ .gallery-home-preview__tile--dragging {
615
+ opacity: 0.4;
616
+ }
617
+
618
+ .gallery-home-preview__img {
619
+ width: 100%;
620
+ height: 100%;
621
+ object-fit: cover;
622
+ display: block;
623
+ }
624
+
625
+ .gallery-home-preview__star {
626
+ position: absolute;
627
+ top: 4px;
628
+ right: 4px;
629
+ width: 24px;
630
+ height: 24px;
631
+ border: 0;
632
+ border-radius: 50%;
633
+ background: rgba(0, 0, 0, 0.55);
634
+ color: rgb(var(--gallery-fg) / 0.6);
635
+ cursor: pointer;
636
+ font-size: 14px;
637
+ line-height: 1;
638
+ display: flex;
639
+ align-items: center;
640
+ justify-content: center;
641
+ }
642
+
643
+ .gallery-home-preview__star--active {
644
+ color: rgb(var(--gallery-accent));
645
+ }
646
+
647
+ .gallery-home-preview__order {
648
+ position: absolute;
649
+ bottom: 4px;
650
+ left: 4px;
651
+ background: rgba(0, 0, 0, 0.55);
652
+ color: #fff;
653
+ font-size: 10px;
654
+ padding: 1px 5px;
655
+ border-radius: 3px;
656
+ }
657
+
658
+ .gallery-home-preview__caption {
659
+ position: absolute;
660
+ bottom: 4px;
661
+ right: 4px;
662
+ background: rgba(0, 0, 0, 0.55);
663
+ color: #fff;
664
+ font-size: 10px;
665
+ padding: 1px 5px;
666
+ border-radius: 3px;
667
+ max-width: 60%;
668
+ white-space: nowrap;
669
+ overflow: hidden;
670
+ text-overflow: ellipsis;
671
+ }
672
+
673
+ /* ─── Category Admin ─── */
674
+
675
+ .gallery-category-admin {
676
+ display: flex;
677
+ flex-direction: column;
678
+ gap: 16px;
679
+ color: rgb(var(--gallery-fg));
680
+ background: rgb(var(--gallery-bg));
681
+ padding: 16px;
682
+ border: 1px solid rgb(var(--gallery-border));
683
+ border-radius: 8px;
684
+ }
685
+
686
+ .gallery-category-admin__header {
687
+ display: flex;
688
+ align-items: center;
689
+ justify-content: space-between;
690
+ }
691
+
692
+ .gallery-category-admin__title {
693
+ font-size: 16px;
694
+ font-weight: 600;
695
+ margin: 0;
696
+ }
697
+
698
+ .gallery-category-admin__new {
699
+ background: rgb(var(--gallery-accent));
700
+ color: rgb(var(--gallery-bg));
701
+ border: 0;
702
+ border-radius: 4px;
703
+ padding: 6px 12px;
704
+ font-weight: 600;
705
+ cursor: pointer;
706
+ }
707
+
708
+ .gallery-category-admin__error {
709
+ background: rgb(220 80 80 / 0.08);
710
+ color: rgb(220 80 80);
711
+ padding: 8px 12px;
712
+ border: 1px solid rgb(220 80 80 / 0.3);
713
+ border-radius: 4px;
714
+ font-size: 12px;
715
+ }
716
+
717
+ .gallery-category-admin__list {
718
+ list-style: none;
719
+ margin: 0;
720
+ padding: 0;
721
+ display: flex;
722
+ flex-direction: column;
723
+ gap: 6px;
724
+ }
725
+
726
+ .gallery-category-admin__item {
727
+ display: flex;
728
+ align-items: stretch;
729
+ border: 1px solid rgb(var(--gallery-border));
730
+ border-radius: 4px;
731
+ overflow: hidden;
732
+ }
733
+
734
+ .gallery-category-admin__item-row {
735
+ flex: 1;
736
+ display: grid;
737
+ grid-template-columns: 120px 1fr 60px 40px;
738
+ gap: 8px;
739
+ align-items: center;
740
+ padding: 6px 10px;
741
+ background: transparent;
742
+ border: 0;
743
+ color: rgb(var(--gallery-fg));
744
+ text-align: left;
745
+ cursor: pointer;
746
+ font-size: 13px;
747
+ }
748
+
749
+ .gallery-category-admin__item-row:hover { background: rgb(var(--gallery-fg) / 0.05); }
750
+
751
+ .gallery-category-admin__slug {
752
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
753
+ font-size: 12px;
754
+ }
755
+
756
+ .gallery-category-admin__delete {
757
+ width: 36px;
758
+ background: transparent;
759
+ color: rgb(220 80 80);
760
+ border: 0;
761
+ border-left: 1px solid rgb(var(--gallery-border));
762
+ cursor: pointer;
763
+ font-size: 16px;
764
+ }
765
+
766
+ .gallery-category-admin__delete:hover { background: rgb(220 80 80 / 0.08); }
767
+
768
+ .gallery-category-admin__form {
769
+ display: flex;
770
+ flex-direction: column;
771
+ gap: 8px;
772
+ border-top: 1px solid rgb(var(--gallery-border));
773
+ padding-top: 12px;
774
+ }
775
+
776
+ .gallery-category-admin__form-title {
777
+ font-size: 13px;
778
+ font-weight: 600;
779
+ }
780
+
781
+ .gallery-category-admin__field {
782
+ display: flex;
783
+ flex-direction: column;
784
+ gap: 4px;
785
+ }
786
+
787
+ .gallery-category-admin__field--row {
788
+ flex-direction: row;
789
+ align-items: center;
790
+ gap: 12px;
791
+ }
792
+
793
+ .gallery-category-admin__field-label {
794
+ font-size: 11px;
795
+ color: rgb(var(--gallery-fg) / 0.7);
796
+ text-transform: uppercase;
797
+ letter-spacing: 0.04em;
798
+ }
799
+
800
+ .gallery-category-admin__input {
801
+ padding: 6px 8px;
802
+ border: 1px solid rgb(var(--gallery-border));
803
+ border-radius: 4px;
804
+ background: rgb(var(--gallery-bg));
805
+ color: rgb(var(--gallery-fg));
806
+ font-size: 13px;
807
+ }
808
+
809
+ .gallery-category-admin__form-actions {
810
+ display: flex;
811
+ justify-content: flex-end;
812
+ gap: 8px;
813
+ margin-top: 4px;
814
+ }
815
+
816
+ .gallery-category-admin__save {
817
+ background: rgb(var(--gallery-accent));
818
+ color: rgb(var(--gallery-bg));
819
+ border: 0;
820
+ border-radius: 4px;
821
+ padding: 6px 14px;
822
+ font-weight: 600;
823
+ cursor: pointer;
824
+ }
825
+
826
+ .gallery-category-admin__save:disabled { opacity: 0.5; cursor: not-allowed; }
827
+
828
+ .gallery-category-admin__cancel {
829
+ background: transparent;
830
+ border: 1px solid rgb(var(--gallery-border));
831
+ color: rgb(var(--gallery-fg));
832
+ border-radius: 4px;
833
+ padding: 6px 12px;
834
+ cursor: pointer;
835
+ }
836
+
837
+ /* ═══════════════════════════════════════════════════════════════
838
+ * Public — Mosaic (presets/ballet:PublicGalleryMosaic)
839
+ * ─────────────────────────────────────────────────────────────── */
840
+
841
+ .gallery-public-mosaic-section {
842
+ padding: clamp(4rem, 8vh, 8rem) 0 0;
843
+ background: rgb(var(--gallery-bg));
844
+ color: rgb(var(--gallery-fg));
845
+ opacity: 0;
846
+ transform: translateY(20px);
847
+ transition: opacity 0.6s ease, transform 0.6s ease;
848
+ }
849
+
850
+ .gallery-public-mosaic-section--visible {
851
+ opacity: 1;
852
+ transform: translateY(0);
853
+ }
854
+
855
+ .gallery-public-mosaic__head {
856
+ max-width: 1200px;
857
+ margin: 0 auto 60px;
858
+ padding: 0 40px;
859
+ }
860
+
861
+ .gallery-public-mosaic__label {
862
+ font-size: 12px;
863
+ letter-spacing: 4px;
864
+ text-transform: uppercase;
865
+ color: rgb(var(--gallery-accent));
866
+ margin-bottom: 12px;
867
+ }
868
+
869
+ .gallery-public-mosaic__title {
870
+ font-size: clamp(28px, 4vw, 48px);
871
+ font-weight: 900;
872
+ letter-spacing: -1px;
873
+ margin: 0;
874
+ }
875
+
876
+ .gallery-public-mosaic {
877
+ display: grid;
878
+ grid-template-columns: repeat(12, 1fr);
879
+ gap: 4px;
880
+ grid-auto-rows: 250px;
881
+ }
882
+
883
+ .gallery-public-mosaic__item {
884
+ position: relative;
885
+ overflow: hidden;
886
+ cursor: pointer;
887
+ background: rgb(var(--gallery-border));
888
+ }
889
+
890
+ .gallery-public-mosaic__item:focus-visible {
891
+ outline: 2px solid rgb(var(--gallery-accent));
892
+ outline-offset: -2px;
893
+ }
894
+
895
+ .gallery-public-mosaic__img {
896
+ width: 100%;
897
+ height: 100%;
898
+ object-fit: cover;
899
+ transition: transform 1.2s cubic-bezier(0.25, 0, 0.25, 1);
900
+ }
901
+
902
+ .gallery-public-mosaic__item:hover .gallery-public-mosaic__img {
903
+ transform: scale(1.1);
904
+ }
905
+
906
+ .gallery-public-mosaic__hover {
907
+ position: absolute;
908
+ inset: 0;
909
+ background: rgba(0, 0, 0, 0.2);
910
+ backdrop-filter: blur(4px);
911
+ display: flex;
912
+ align-items: center;
913
+ justify-content: center;
914
+ opacity: 0;
915
+ transition: opacity 0.5s ease;
916
+ pointer-events: none;
917
+ }
918
+
919
+ .gallery-public-mosaic__item:hover .gallery-public-mosaic__hover {
920
+ opacity: 1;
921
+ }
922
+
923
+ .gallery-public-mosaic__icon {
924
+ width: 50px;
925
+ height: 50px;
926
+ border: 1px solid #fff;
927
+ border-radius: 50%;
928
+ display: flex;
929
+ align-items: center;
930
+ justify-content: center;
931
+ color: #fff;
932
+ font-size: 1.2rem;
933
+ background: rgba(0, 0, 0, 0.3);
934
+ transition: transform 0.3s ease;
935
+ }
936
+
937
+ .gallery-public-mosaic__item:hover .gallery-public-mosaic__icon {
938
+ transform: scale(1.1);
939
+ }
940
+
941
+ /* Adaptive layouts (data-count 1~7) */
942
+
943
+ .gallery-public-mosaic[data-count="1"] .gallery-public-mosaic__item { grid-column: 1 / -1; }
944
+
945
+ .gallery-public-mosaic[data-count="2"] .gallery-public-mosaic__item:nth-child(1) { grid-column: 1 / 7; }
946
+ .gallery-public-mosaic[data-count="2"] .gallery-public-mosaic__item:nth-child(2) { grid-column: 7 / 13; }
947
+
948
+ .gallery-public-mosaic[data-count="3"] .gallery-public-mosaic__item:nth-child(1) { grid-column: 1 / 7; grid-row: span 2; }
949
+ .gallery-public-mosaic[data-count="3"] .gallery-public-mosaic__item:nth-child(2) { grid-column: 7 / 13; }
950
+ .gallery-public-mosaic[data-count="3"] .gallery-public-mosaic__item:nth-child(3) { grid-column: 7 / 13; }
951
+
952
+ .gallery-public-mosaic[data-count="4"] .gallery-public-mosaic__item:nth-child(1) { grid-column: 1 / 7; }
953
+ .gallery-public-mosaic[data-count="4"] .gallery-public-mosaic__item:nth-child(2) { grid-column: 7 / 13; }
954
+ .gallery-public-mosaic[data-count="4"] .gallery-public-mosaic__item:nth-child(3) { grid-column: 1 / 7; }
955
+ .gallery-public-mosaic[data-count="4"] .gallery-public-mosaic__item:nth-child(4) { grid-column: 7 / 13; }
956
+
957
+ .gallery-public-mosaic[data-count="5"] .gallery-public-mosaic__item:nth-child(1) { grid-column: 1 / 6; grid-row: span 2; }
958
+ .gallery-public-mosaic[data-count="5"] .gallery-public-mosaic__item:nth-child(2) { grid-column: 6 / 9; }
959
+ .gallery-public-mosaic[data-count="5"] .gallery-public-mosaic__item:nth-child(3) { grid-column: 9 / 13; }
960
+ .gallery-public-mosaic[data-count="5"] .gallery-public-mosaic__item:nth-child(4) { grid-column: 6 / 9; }
961
+ .gallery-public-mosaic[data-count="5"] .gallery-public-mosaic__item:nth-child(5) { grid-column: 9 / 13; }
962
+
963
+ .gallery-public-mosaic[data-count="6"] { grid-template-columns: repeat(16, 1fr); grid-template-rows: 3fr 2fr; }
964
+ .gallery-public-mosaic[data-count="6"] .gallery-public-mosaic__item:nth-child(1) { grid-column: 1/10; }
965
+ .gallery-public-mosaic[data-count="6"] .gallery-public-mosaic__item:nth-child(2) { grid-column: 10/13; }
966
+ .gallery-public-mosaic[data-count="6"] .gallery-public-mosaic__item:nth-child(3) { grid-column: 13/17; }
967
+ .gallery-public-mosaic[data-count="6"] .gallery-public-mosaic__item:nth-child(4) { grid-column: 1/5; }
968
+ .gallery-public-mosaic[data-count="6"] .gallery-public-mosaic__item:nth-child(5) { grid-column: 5/10; }
969
+ .gallery-public-mosaic[data-count="6"] .gallery-public-mosaic__item:nth-child(6) { grid-column: 10/17; }
970
+
971
+ .gallery-public-mosaic[data-count="7"] { grid-template-columns: repeat(16, 1fr); }
972
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(1) { grid-column: 1/10; grid-row: span 2; }
973
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(2) { grid-column: 10/13; }
974
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(3) { grid-column: 13/17; grid-row: span 2; }
975
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(4) { grid-column: 1/5; }
976
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(5) { grid-column: 5/10; }
977
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(6) { grid-column: 10/13; grid-row: 2 / span 2; }
978
+ .gallery-public-mosaic[data-count="7"] .gallery-public-mosaic__item:nth-child(7) { grid-column: 13/17; }
979
+
980
+ /* ═══════════════════════════════════════════════════════════════
981
+ * Public — Lightbox (presets/ballet:PublicGalleryMosaic)
982
+ * ─────────────────────────────────────────────────────────────── */
983
+
984
+ .gallery-lightbox {
985
+ position: fixed;
986
+ inset: 0;
987
+ z-index: 9999;
988
+ background: rgba(0, 0, 0, 0.92);
989
+ display: flex;
990
+ align-items: center;
991
+ justify-content: center;
992
+ animation: gallery-lightbox-fadein 0.3s ease;
993
+ }
994
+
995
+ @keyframes gallery-lightbox-fadein {
996
+ from { opacity: 0; }
997
+ to { opacity: 1; }
998
+ }
999
+
1000
+ .gallery-lightbox__content {
1001
+ width: 90vw;
1002
+ height: 85vh;
1003
+ display: flex;
1004
+ align-items: center;
1005
+ justify-content: center;
1006
+ }
1007
+
1008
+ .gallery-lightbox__img {
1009
+ max-width: 100%;
1010
+ max-height: 100%;
1011
+ object-fit: contain;
1012
+ border-radius: 4px;
1013
+ }
1014
+
1015
+ .gallery-lightbox__close {
1016
+ position: absolute;
1017
+ top: 20px;
1018
+ right: 24px;
1019
+ background: none;
1020
+ border: none;
1021
+ color: #fff;
1022
+ font-size: 36px;
1023
+ cursor: pointer;
1024
+ width: 48px;
1025
+ height: 48px;
1026
+ display: flex;
1027
+ align-items: center;
1028
+ justify-content: center;
1029
+ opacity: 0.7;
1030
+ transition: opacity 0.2s ease;
1031
+ z-index: 1;
1032
+ }
1033
+
1034
+ .gallery-lightbox__close:hover {
1035
+ opacity: 1;
1036
+ }
1037
+
1038
+ .gallery-lightbox__nav {
1039
+ position: absolute;
1040
+ top: 50%;
1041
+ transform: translateY(-50%);
1042
+ background: rgba(255, 255, 255, 0.1);
1043
+ border: 1px solid rgba(255, 255, 255, 0.2);
1044
+ color: #fff;
1045
+ font-size: 32px;
1046
+ width: 48px;
1047
+ height: 48px;
1048
+ border-radius: 50%;
1049
+ cursor: pointer;
1050
+ display: flex;
1051
+ align-items: center;
1052
+ justify-content: center;
1053
+ opacity: 0.7;
1054
+ transition: opacity 0.2s ease, background 0.2s ease;
1055
+ z-index: 1;
1056
+ }
1057
+
1058
+ .gallery-lightbox__nav:hover {
1059
+ opacity: 1;
1060
+ background: rgba(255, 255, 255, 0.2);
1061
+ }
1062
+
1063
+ .gallery-lightbox__prev { left: 20px; }
1064
+ .gallery-lightbox__next { right: 20px; }
1065
+
1066
+ .gallery-lightbox__counter {
1067
+ position: absolute;
1068
+ bottom: 24px;
1069
+ left: 50%;
1070
+ transform: translateX(-50%);
1071
+ color: rgba(255, 255, 255, 0.7);
1072
+ font-size: 14px;
1073
+ letter-spacing: 2px;
1074
+ }