qdadm 0.13.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 (82) hide show
  1. package/CHANGELOG.md +270 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/package.json +48 -0
  5. package/src/assets/logo.svg +6 -0
  6. package/src/components/BoolCell.vue +28 -0
  7. package/src/components/dialogs/BulkStatusDialog.vue +43 -0
  8. package/src/components/dialogs/MultiStepDialog.vue +321 -0
  9. package/src/components/dialogs/SimpleDialog.vue +108 -0
  10. package/src/components/dialogs/UnsavedChangesDialog.vue +87 -0
  11. package/src/components/display/CardsGrid.vue +155 -0
  12. package/src/components/display/CopyableId.vue +92 -0
  13. package/src/components/display/EmptyState.vue +114 -0
  14. package/src/components/display/IntensityBar.vue +171 -0
  15. package/src/components/display/RichCardsGrid.vue +220 -0
  16. package/src/components/editors/JsonEditorFoldable.vue +467 -0
  17. package/src/components/editors/JsonStructuredField.vue +218 -0
  18. package/src/components/editors/JsonViewer.vue +91 -0
  19. package/src/components/editors/KeyValueEditor.vue +314 -0
  20. package/src/components/editors/LanguageEditor.vue +245 -0
  21. package/src/components/editors/ScopeEditor.vue +341 -0
  22. package/src/components/editors/VanillaJsonEditor.vue +185 -0
  23. package/src/components/forms/FormActions.vue +104 -0
  24. package/src/components/forms/FormField.vue +64 -0
  25. package/src/components/forms/FormTab.vue +217 -0
  26. package/src/components/forms/FormTabs.vue +108 -0
  27. package/src/components/index.js +44 -0
  28. package/src/components/layout/AppLayout.vue +430 -0
  29. package/src/components/layout/Breadcrumb.vue +106 -0
  30. package/src/components/layout/PageHeader.vue +75 -0
  31. package/src/components/layout/PageLayout.vue +93 -0
  32. package/src/components/lists/ActionButtons.vue +41 -0
  33. package/src/components/lists/ActionColumn.vue +37 -0
  34. package/src/components/lists/FilterBar.vue +53 -0
  35. package/src/components/lists/ListPage.vue +319 -0
  36. package/src/composables/index.js +19 -0
  37. package/src/composables/useApp.js +43 -0
  38. package/src/composables/useAuth.js +49 -0
  39. package/src/composables/useBareForm.js +143 -0
  40. package/src/composables/useBreadcrumb.js +221 -0
  41. package/src/composables/useDirtyState.js +103 -0
  42. package/src/composables/useEntityTitle.js +121 -0
  43. package/src/composables/useForm.js +254 -0
  44. package/src/composables/useGuardStore.js +37 -0
  45. package/src/composables/useJsonSyntax.js +101 -0
  46. package/src/composables/useListPageBuilder.js +1176 -0
  47. package/src/composables/useNavigation.js +89 -0
  48. package/src/composables/usePageBuilder.js +334 -0
  49. package/src/composables/useStatus.js +146 -0
  50. package/src/composables/useSubEditor.js +165 -0
  51. package/src/composables/useTabSync.js +110 -0
  52. package/src/composables/useUnsavedChangesGuard.js +122 -0
  53. package/src/entity/EntityManager.js +540 -0
  54. package/src/entity/index.js +11 -0
  55. package/src/entity/storage/ApiStorage.js +146 -0
  56. package/src/entity/storage/LocalStorage.js +220 -0
  57. package/src/entity/storage/MemoryStorage.js +201 -0
  58. package/src/entity/storage/index.js +10 -0
  59. package/src/index.js +29 -0
  60. package/src/kernel/Kernel.js +234 -0
  61. package/src/kernel/index.js +7 -0
  62. package/src/module/index.js +16 -0
  63. package/src/module/moduleRegistry.js +222 -0
  64. package/src/orchestrator/Orchestrator.js +141 -0
  65. package/src/orchestrator/index.js +8 -0
  66. package/src/orchestrator/useOrchestrator.js +61 -0
  67. package/src/plugin.js +142 -0
  68. package/src/styles/_alerts.css +48 -0
  69. package/src/styles/_code.css +33 -0
  70. package/src/styles/_dialogs.css +17 -0
  71. package/src/styles/_markdown.css +82 -0
  72. package/src/styles/_show-pages.css +84 -0
  73. package/src/styles/index.css +16 -0
  74. package/src/styles/main.css +845 -0
  75. package/src/styles/theme/components.css +286 -0
  76. package/src/styles/theme/index.css +10 -0
  77. package/src/styles/theme/tokens.css +125 -0
  78. package/src/styles/theme/utilities.css +172 -0
  79. package/src/utils/debugInjector.js +261 -0
  80. package/src/utils/formatters.js +165 -0
  81. package/src/utils/index.js +35 -0
  82. package/src/utils/transformers.js +105 -0
@@ -0,0 +1,845 @@
1
+ /* Framework Design System */
2
+ @import './theme/index.css';
3
+
4
+ /* Modular CSS imports */
5
+ @import './_alerts.css';
6
+ @import './_code.css';
7
+ @import './_dialogs.css';
8
+ @import './_markdown.css';
9
+ @import './_show-pages.css';
10
+
11
+ /* Base styles */
12
+ * {
13
+ margin: 0;
14
+ padding: 0;
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ html, body, #app {
19
+ height: 100%;
20
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
21
+ }
22
+
23
+ /* Layout - AppLayout styles are now scoped in AppLayout.vue */
24
+ /* Only keep truly global layout utilities here */
25
+
26
+ .page-content {
27
+ flex: 1;
28
+ padding: 1.5rem;
29
+ overflow-y: auto;
30
+ }
31
+
32
+ /* Cards */
33
+ .stats-grid {
34
+ display: grid;
35
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
36
+ gap: 1.5rem;
37
+ margin-bottom: 2rem;
38
+ }
39
+
40
+ .stat-card {
41
+ background: var(--p-surface-0);
42
+ border-radius: 0.5rem;
43
+ padding: 1.5rem;
44
+ border: 1px solid var(--p-surface-200);
45
+ }
46
+
47
+ .stat-card-title {
48
+ font-size: 0.875rem;
49
+ color: var(--p-surface-500);
50
+ margin-bottom: 0.5rem;
51
+ }
52
+
53
+ .stat-card-value {
54
+ font-size: 2rem;
55
+ font-weight: 600;
56
+ color: var(--p-surface-900);
57
+ }
58
+
59
+ .stat-card-subtitle {
60
+ font-size: 0.75rem;
61
+ color: var(--p-surface-400);
62
+ margin-top: 0.25rem;
63
+ }
64
+
65
+ /* Page headers */
66
+ .page-header {
67
+ margin-bottom: 1.5rem;
68
+ }
69
+
70
+ .page-title {
71
+ font-size: 1.5rem;
72
+ font-weight: 600;
73
+ color: var(--p-surface-900);
74
+ }
75
+
76
+ .header-actions {
77
+ display: flex;
78
+ gap: 0.75rem;
79
+ align-items: center;
80
+ }
81
+
82
+ /* Forms */
83
+ .form-grid {
84
+ display: grid;
85
+ grid-template-columns: repeat(2, 1fr);
86
+ gap: 1.5rem;
87
+ padding: 1rem 0;
88
+ }
89
+
90
+ .form-field {
91
+ display: flex;
92
+ flex-direction: column;
93
+ gap: 0.5rem;
94
+ }
95
+
96
+ /* Spacing between form sections (not within grids - gap handles that) */
97
+ .form-row + .form-field,
98
+ .form-field + .form-row {
99
+ margin-top: 1.25rem;
100
+ }
101
+
102
+ .form-field label {
103
+ font-weight: 500;
104
+ color: var(--p-surface-700);
105
+ }
106
+
107
+ .form-field small {
108
+ color: var(--p-surface-500);
109
+ font-size: 0.85rem;
110
+ }
111
+
112
+ /* Form rows - grid layouts */
113
+ .form-row {
114
+ display: grid;
115
+ grid-template-columns: repeat(2, 1fr);
116
+ gap: 1.5rem;
117
+ align-items: end;
118
+ }
119
+
120
+ .form-row-3 {
121
+ display: grid;
122
+ grid-template-columns: repeat(3, 1fr);
123
+ gap: 1rem;
124
+ align-items: end;
125
+ }
126
+
127
+ .form-row.metadata {
128
+ display: grid;
129
+ grid-template-columns: repeat(4, 1fr);
130
+ gap: 1rem;
131
+ padding: 1rem;
132
+ background: var(--p-surface-50);
133
+ border-radius: 0.5rem;
134
+ align-items: end;
135
+ }
136
+
137
+ .form-row.checkboxes {
138
+ display: flex;
139
+ gap: 3rem;
140
+ }
141
+
142
+ /* Meta items in forms */
143
+ .meta-item {
144
+ display: flex;
145
+ flex-direction: column;
146
+ gap: 0.25rem;
147
+ }
148
+
149
+ .meta-item label {
150
+ font-size: 0.85rem;
151
+ color: var(--p-surface-500);
152
+ }
153
+
154
+ .meta-item span {
155
+ font-weight: 500;
156
+ }
157
+
158
+ /* Toggle/checkbox fields */
159
+ .toggle-field {
160
+ flex-direction: row;
161
+ align-items: center;
162
+ gap: 1rem;
163
+ }
164
+
165
+ .toggle-field label {
166
+ min-width: 120px;
167
+ }
168
+
169
+ /* Field with inline button (url, lock, envelope) */
170
+ .url-field,
171
+ .lock-field,
172
+ .envelope-field {
173
+ display: flex;
174
+ gap: 0.5rem;
175
+ align-items: center;
176
+ }
177
+
178
+ .url-field input,
179
+ .lock-field input,
180
+ .envelope-field input {
181
+ flex: 1;
182
+ }
183
+
184
+ /* Field hint */
185
+ .field-hint,
186
+ .form-hint {
187
+ font-size: 0.75rem;
188
+ color: var(--p-surface-500);
189
+ }
190
+
191
+ /* Info grid for readonly data */
192
+ .info-grid {
193
+ display: grid;
194
+ grid-template-columns: repeat(2, 1fr);
195
+ gap: 1rem;
196
+ }
197
+
198
+ .info-grid > div {
199
+ display: flex;
200
+ flex-direction: column;
201
+ gap: 0.25rem;
202
+ }
203
+
204
+ .info-grid label {
205
+ font-size: 0.85rem;
206
+ color: var(--p-surface-500);
207
+ }
208
+
209
+ /* Info item */
210
+ .info-item {
211
+ display: flex;
212
+ flex-direction: column;
213
+ gap: 0.25rem;
214
+ }
215
+
216
+ .info-item label {
217
+ font-size: 0.75rem;
218
+ font-weight: 600;
219
+ color: var(--p-surface-500);
220
+ text-transform: uppercase;
221
+ }
222
+
223
+ .info-value {
224
+ font-size: 0.9rem;
225
+ }
226
+
227
+ /* Timestamps grid */
228
+ .timestamps-grid {
229
+ display: grid;
230
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
231
+ gap: 1rem;
232
+ }
233
+
234
+ .timestamps-grid--separator {
235
+ padding-top: 1rem;
236
+ border-top: 1px solid var(--p-surface-200);
237
+ }
238
+
239
+ .timestamp {
240
+ display: flex;
241
+ flex-direction: column;
242
+ gap: 0.25rem;
243
+ }
244
+
245
+ .timestamp label {
246
+ font-size: 0.75rem;
247
+ color: var(--text-color-secondary);
248
+ text-transform: uppercase;
249
+ }
250
+
251
+ /* Loading/busy states */
252
+ .loading-state {
253
+ display: flex;
254
+ justify-content: center;
255
+ align-items: center;
256
+ padding: 3rem;
257
+ }
258
+
259
+ .loading-state--inline {
260
+ padding: 1rem;
261
+ gap: 0.75rem;
262
+ color: var(--p-text-muted-color);
263
+ }
264
+
265
+ /* Empty state (no content) */
266
+ .empty-state {
267
+ padding: 2rem;
268
+ text-align: center;
269
+ color: var(--p-text-muted-color);
270
+ }
271
+
272
+ /* Error message display */
273
+ .error-message {
274
+ background: var(--p-red-50);
275
+ border: 1px solid var(--p-red-200);
276
+ border-radius: 0.375rem;
277
+ padding: 0.75rem 1rem;
278
+ color: var(--p-red-700);
279
+ font-family: var(--p-font-family-mono, monospace);
280
+ font-size: 0.85rem;
281
+ white-space: pre-wrap;
282
+ word-break: break-word;
283
+ }
284
+
285
+ /* Error content in cards/panels */
286
+ .error-content {
287
+ background: var(--p-red-50);
288
+ color: var(--p-red-700);
289
+ padding: 1rem;
290
+ border-radius: 0.5rem;
291
+ overflow-x: auto;
292
+ margin: 0;
293
+ font-size: 0.85rem;
294
+ white-space: pre-wrap;
295
+ }
296
+
297
+ :root[data-theme='dark'] .error-message,
298
+ :root[data-theme='dark'] .error-content {
299
+ background: rgba(239, 68, 68, 0.1);
300
+ color: var(--p-red-400);
301
+ border-color: var(--p-red-900);
302
+ }
303
+
304
+ /* Login page styles are now scoped in Login.vue */
305
+ /* User info styles are now scoped in AppLayout.vue */
306
+
307
+ /* Table actions */
308
+ .table-actions {
309
+ display: flex;
310
+ gap: 0.25rem;
311
+ justify-content: flex-start;
312
+ }
313
+
314
+ /* ===========================================
315
+ List Page Common Styles
316
+ =========================================== */
317
+
318
+ /* Text utilities */
319
+ .text-muted {
320
+ color: var(--p-surface-400);
321
+ }
322
+
323
+ /* Status/Type tags container */
324
+ .status-tags,
325
+ .type-tags {
326
+ display: flex;
327
+ gap: 0.25rem;
328
+ flex-wrap: wrap;
329
+ }
330
+
331
+ /* External link style (domains, urls) */
332
+ .external-link {
333
+ display: flex;
334
+ align-items: center;
335
+ gap: 0.5rem;
336
+ color: var(--p-primary-500);
337
+ text-decoration: none;
338
+ }
339
+
340
+ .external-link:hover {
341
+ text-decoration: underline;
342
+ }
343
+
344
+ .external-link i {
345
+ font-size: 0.75rem;
346
+ opacity: 0.6;
347
+ }
348
+
349
+ /* Domain cell (for domain lists) */
350
+ .domain-cell {
351
+ display: flex;
352
+ align-items: center;
353
+ }
354
+
355
+ .domain-link {
356
+ display: flex;
357
+ align-items: center;
358
+ gap: 0.5rem;
359
+ color: var(--p-primary-500);
360
+ text-decoration: none;
361
+ }
362
+
363
+ .domain-link:hover {
364
+ text-decoration: underline;
365
+ }
366
+
367
+ .domain-link i {
368
+ font-size: 0.75rem;
369
+ opacity: 0.6;
370
+ }
371
+
372
+ /* Domain tags in event list */
373
+ .domain-tags {
374
+ display: flex;
375
+ gap: 0.25rem;
376
+ }
377
+
378
+ /* Clickable table cell text */
379
+ .clickable-cell {
380
+ cursor: pointer;
381
+ color: var(--p-primary-color);
382
+ }
383
+
384
+ .clickable-cell:hover {
385
+ text-decoration: underline;
386
+ }
387
+
388
+ /* Entity links (for references to jobs, batches, stories, etc.) */
389
+ .entity-link {
390
+ display: flex;
391
+ align-items: center;
392
+ gap: 0.5rem;
393
+ text-decoration: none;
394
+ color: var(--p-primary-color);
395
+ }
396
+
397
+ .entity-link:hover {
398
+ text-decoration: underline;
399
+ }
400
+
401
+ .entity-type {
402
+ font-weight: 500;
403
+ }
404
+
405
+ .entity-id {
406
+ font-size: 0.75rem;
407
+ background: var(--p-surface-100);
408
+ padding: 0.15rem 0.35rem;
409
+ border-radius: 3px;
410
+ }
411
+
412
+ /* Interests/tags display (limited with +N) */
413
+ .tags-preview {
414
+ display: flex;
415
+ gap: 0.25rem;
416
+ flex-wrap: wrap;
417
+ }
418
+
419
+ .tags-preview .p-tag {
420
+ font-size: 0.75rem;
421
+ }
422
+
423
+ /* Filter bar */
424
+ .filter-bar {
425
+ display: flex;
426
+ justify-content: space-between;
427
+ align-items: center;
428
+ gap: 1rem;
429
+ margin-bottom: 1rem;
430
+ }
431
+
432
+ /* Highlight active filters with orange border */
433
+ .p-select.filter-active,
434
+ .p-inputtext.filter-active {
435
+ border-color: #f97316 !important;
436
+ box-shadow: 0 0 0 1px #f97316 !important;
437
+ }
438
+
439
+ /* Modified form fields - orange border */
440
+ /* Applied via FormField wrapper component */
441
+ .form-field.field-dirty .p-inputtext,
442
+ .form-field.field-dirty .p-select,
443
+ .form-field.field-dirty .p-textarea,
444
+ .form-field.field-dirty .p-password input,
445
+ .form-field.field-dirty .p-multiselect,
446
+ .form-field.field-dirty .p-calendar input,
447
+ .form-field.field-dirty .p-inputnumber input,
448
+ .form-field.field-dirty .p-dropdown {
449
+ border-color: #f97316 !important;
450
+ box-shadow: 0 0 0 1px #f97316 !important;
451
+ }
452
+
453
+ /* Note: Checkbox and toggle switch dirty styling removed
454
+ because it highlights ALL items in a group when any changes.
455
+ The "unsaved changes" banner is sufficient feedback. */
456
+
457
+ .filter-bar-left {
458
+ display: flex;
459
+ align-items: center;
460
+ gap: 0.75rem;
461
+ }
462
+
463
+ .filter-bar-right {
464
+ display: flex;
465
+ align-items: center;
466
+ gap: 0.75rem;
467
+ }
468
+
469
+ /* Checkbox field layout */
470
+ .checkbox-field {
471
+ display: flex;
472
+ align-items: center;
473
+ gap: 0.5rem;
474
+ }
475
+
476
+ .checkbox-field label {
477
+ margin: 0;
478
+ cursor: pointer;
479
+ }
480
+
481
+ /* Utility class for full width */
482
+ .w-full {
483
+ width: 100% !important;
484
+ }
485
+
486
+ /* Force PrimeVue inputs to be full width */
487
+ .form-field .p-inputtext,
488
+ .form-field .p-textarea,
489
+ .form-field .p-select,
490
+ .form-field .p-multiselect,
491
+ .form-field .p-inputwrapper,
492
+ .form-field input,
493
+ .form-field textarea {
494
+ width: 100% !important;
495
+ box-sizing: border-box;
496
+ }
497
+
498
+ /* Fix textarea height */
499
+ .form-field .p-textarea,
500
+ .form-field textarea {
501
+ min-height: 100px;
502
+ resize: vertical;
503
+ }
504
+
505
+ /* Dirty state indicator for forms */
506
+ .form-dirty-indicator {
507
+ display: flex;
508
+ align-items: center;
509
+ gap: 0.5rem;
510
+ padding: 0.5rem 1rem;
511
+ background: color-mix(in srgb, var(--p-orange-100) 50%, transparent);
512
+ border: 1px solid var(--p-orange-300);
513
+ border-radius: 0.375rem;
514
+ color: var(--p-orange-700);
515
+ font-size: 0.875rem;
516
+ margin-bottom: 1rem;
517
+ }
518
+
519
+ .form-dirty-indicator i {
520
+ color: var(--p-orange-500);
521
+ }
522
+
523
+ /* PrimeVue Tabs - add padding to tab panels */
524
+ .p-tabpanels {
525
+ padding-top: 1rem;
526
+ }
527
+
528
+ /* First form element in tab panel needs top margin */
529
+ .p-tabpanel > .form-field:first-child,
530
+ .p-tabpanel > .form-row:first-child,
531
+ .p-tabpanel > .form-grid:first-child {
532
+ margin-top: 0.5rem;
533
+ }
534
+
535
+ /* ===========================================
536
+ Utility Classes
537
+ =========================================== */
538
+
539
+ /* Spinners */
540
+ .spinner-lg {
541
+ font-size: 2rem;
542
+ }
543
+
544
+ .spinner-md {
545
+ font-size: 1.5rem;
546
+ }
547
+
548
+ /* Cards */
549
+ .card {
550
+ background: var(--p-surface-0);
551
+ border-radius: 0.5rem;
552
+ padding: 1.5rem;
553
+ border: 1px solid var(--p-surface-200);
554
+ }
555
+
556
+ .form-card {
557
+ background: var(--p-surface-0);
558
+ padding: 2rem;
559
+ border-radius: 0.5rem;
560
+ }
561
+
562
+ .info-card {
563
+ background: var(--p-surface-50);
564
+ padding: 1rem;
565
+ border-radius: 0.5rem;
566
+ }
567
+
568
+ /* Card title patterns */
569
+ .card-title {
570
+ display: flex;
571
+ align-items: center;
572
+ justify-content: space-between;
573
+ }
574
+
575
+ .card h3,
576
+ .card-heading {
577
+ margin: 0 0 1rem;
578
+ font-size: 1rem;
579
+ font-weight: 600;
580
+ color: var(--p-surface-700);
581
+ }
582
+
583
+ .warning-card {
584
+ background: var(--p-yellow-50);
585
+ padding: 1rem;
586
+ border-radius: 0.5rem;
587
+ border: 1px solid var(--p-yellow-200);
588
+ }
589
+
590
+ .warning-card i {
591
+ color: var(--p-yellow-600);
592
+ }
593
+
594
+ .warning-card span {
595
+ margin-left: 0.5rem;
596
+ color: var(--p-yellow-700);
597
+ }
598
+
599
+ /* Grid utilities */
600
+ .span-full {
601
+ grid-column: 1 / -1;
602
+ }
603
+
604
+ /* Text utilities */
605
+ .text-muted {
606
+ color: var(--p-surface-500);
607
+ }
608
+
609
+ .text-uppercase {
610
+ text-transform: uppercase;
611
+ }
612
+
613
+ .text-center {
614
+ text-align: center;
615
+ }
616
+
617
+ .monospace {
618
+ font-family: monospace;
619
+ }
620
+
621
+ .break-all {
622
+ word-break: break-all;
623
+ }
624
+
625
+ /* Spacing */
626
+ .mb-0 { margin-bottom: 0; }
627
+ .mb-1 { margin-bottom: 0.5rem; }
628
+ .mb-2 { margin-bottom: 1rem; }
629
+ .mb-3 { margin-bottom: 1.5rem; }
630
+ .mt-0 { margin-top: 0; }
631
+ .mt-1 { margin-top: 0.5rem; }
632
+ .mt-2 { margin-top: 1rem; }
633
+ .p-2 { padding: 1rem; }
634
+ .p-3 { padding: 1.5rem; }
635
+ .pt-2 { padding-top: 1rem; }
636
+ .gap-1 { gap: 0.5rem; }
637
+ .gap-2 { gap: 1rem; }
638
+ .gap-3 { gap: 1.5rem; }
639
+
640
+ /* Flexbox utilities */
641
+ .flex { display: flex; }
642
+ .flex-col { flex-direction: column; }
643
+ .flex-wrap { flex-wrap: wrap; }
644
+ .items-center { align-items: center; }
645
+ .items-start { align-items: flex-start; }
646
+ .items-end { align-items: flex-end; }
647
+ .justify-center { justify-content: center; }
648
+ .justify-between { justify-content: space-between; }
649
+ .flex-1 { flex: 1; }
650
+
651
+ /* Grid utilities */
652
+ .grid { display: grid; }
653
+ .grid-cols-2 { grid-template-columns: repeat(2, 1fr); }
654
+ .grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
655
+
656
+ /* Display info blocks (for show pages) */
657
+ .info-block {
658
+ background: var(--p-surface-50);
659
+ padding: 1.5rem;
660
+ border-radius: 0.5rem;
661
+ }
662
+
663
+ .info-block-title {
664
+ margin: 0 0 1rem 0;
665
+ font-size: 1rem;
666
+ color: var(--p-surface-600);
667
+ }
668
+
669
+ .info-block-title i {
670
+ margin-right: 0.5rem;
671
+ }
672
+
673
+ .info-label {
674
+ font-weight: 500;
675
+ color: var(--p-surface-500);
676
+ display: block;
677
+ margin-bottom: 0.25rem;
678
+ }
679
+
680
+ .info-label-sm {
681
+ font-size: 0.75rem;
682
+ font-weight: 600;
683
+ color: var(--p-surface-500);
684
+ text-transform: uppercase;
685
+ display: block;
686
+ margin-bottom: 0.25rem;
687
+ }
688
+
689
+ .value-lg {
690
+ font-size: 1.5rem;
691
+ font-weight: 600;
692
+ }
693
+
694
+ /* Accent blocks */
695
+ .accent-block {
696
+ background: var(--p-surface-50);
697
+ border-left: 3px solid var(--p-primary-500);
698
+ padding: 1rem;
699
+ border-radius: 0.25rem;
700
+ }
701
+
702
+ /* Code/key display */
703
+ .code-block {
704
+ word-break: break-all;
705
+ font-family: monospace;
706
+ background: var(--p-surface-100);
707
+ padding: 1rem;
708
+ border-radius: 0.25rem;
709
+ }
710
+
711
+ /* Empty state styling */
712
+ .empty-state-icon {
713
+ font-size: 3rem;
714
+ color: var(--p-text-muted-color);
715
+ }
716
+
717
+ /* ===========================================
718
+ Section Headers
719
+ =========================================== */
720
+
721
+ .section-header {
722
+ display: flex;
723
+ align-items: center;
724
+ gap: 0.5rem;
725
+ margin-bottom: 1rem;
726
+ }
727
+
728
+ .section-header h3 {
729
+ margin: 0;
730
+ font-size: 1rem;
731
+ font-weight: 600;
732
+ }
733
+
734
+ .section-header i {
735
+ color: var(--p-primary-500);
736
+ }
737
+
738
+ .section-description {
739
+ color: var(--p-surface-500);
740
+ font-size: 0.875rem;
741
+ margin-bottom: 1rem;
742
+ }
743
+
744
+ .section-title {
745
+ margin: 0 0 1rem 0;
746
+ font-size: 1rem;
747
+ font-weight: 600;
748
+ color: var(--p-surface-700);
749
+ }
750
+
751
+ .section-title--separator {
752
+ border-top: 1px solid var(--p-surface-200);
753
+ padding-top: 1.5rem;
754
+ }
755
+
756
+ .section-title i {
757
+ margin-right: 0.5rem;
758
+ }
759
+
760
+ /* ===========================================
761
+ Config Pages Pattern
762
+ =========================================== */
763
+
764
+ .config-intro {
765
+ display: flex;
766
+ align-items: flex-start;
767
+ gap: 0.75rem;
768
+ padding: 1rem;
769
+ background: var(--p-surface-50);
770
+ border-radius: 0.5rem;
771
+ margin-bottom: 1.5rem;
772
+ }
773
+
774
+ .config-intro i {
775
+ font-size: 1.25rem;
776
+ color: var(--p-primary-500);
777
+ margin-top: 0.125rem;
778
+ }
779
+
780
+ .config-field {
781
+ margin-bottom: 1.5rem;
782
+ }
783
+
784
+ /* ===========================================
785
+ Image Gallery Pattern
786
+ =========================================== */
787
+
788
+ .image-gallery {
789
+ display: grid;
790
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
791
+ gap: 1rem;
792
+ }
793
+
794
+ .image-card {
795
+ position: relative;
796
+ border-radius: 0.5rem;
797
+ overflow: hidden;
798
+ border: 1px solid var(--p-surface-200);
799
+ }
800
+
801
+ .image-card img {
802
+ width: 100%;
803
+ aspect-ratio: 16/9;
804
+ object-fit: cover;
805
+ }
806
+
807
+ .image-card--clickable {
808
+ cursor: pointer;
809
+ transition: border-color 0.2s, box-shadow 0.2s;
810
+ }
811
+
812
+ .image-card--clickable:hover {
813
+ border-color: var(--p-primary-300);
814
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
815
+ }
816
+
817
+ .image-caption {
818
+ padding: 0.5rem;
819
+ background: var(--p-surface-50);
820
+ font-size: 0.75rem;
821
+ color: var(--p-surface-600);
822
+ }
823
+
824
+ /* ===========================================
825
+ Info Row Pattern (for key-value pairs)
826
+ =========================================== */
827
+
828
+ .info-row {
829
+ display: flex;
830
+ justify-content: space-between;
831
+ align-items: center;
832
+ padding: 0.5rem 0;
833
+ border-bottom: 1px solid var(--p-surface-100);
834
+ }
835
+
836
+ .info-row:last-child {
837
+ border-bottom: none;
838
+ }
839
+
840
+ /* Responsive - Sidebar mobile styles are now in AppLayout.vue */
841
+ @media (max-width: 768px) {
842
+ .form-grid {
843
+ grid-template-columns: 1fr;
844
+ }
845
+ }