@keenmate/pure-admin-core 2.3.1 → 2.3.3

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 (70) hide show
  1. package/README.md +30 -9
  2. package/dist/css/main.css +205 -190
  3. package/package.json +1 -1
  4. package/snippets/buttons.html +375 -365
  5. package/snippets/command-palette.html +15 -13
  6. package/src/scss/_base-css-variables.scss +10 -0
  7. package/src/scss/_core.scss +121 -121
  8. package/src/scss/core-components/_alerts.scss +227 -227
  9. package/src/scss/core-components/_badges.scss +16 -16
  10. package/src/scss/core-components/_base.scss +125 -125
  11. package/src/scss/core-components/_buttons.scss +31 -16
  12. package/src/scss/core-components/_callouts.scss +152 -152
  13. package/src/scss/core-components/_cards.scss +488 -488
  14. package/src/scss/core-components/_checkbox-lists.scss +289 -289
  15. package/src/scss/core-components/_code.scss +141 -141
  16. package/src/scss/core-components/_command-palette.scss +518 -509
  17. package/src/scss/core-components/_comparison.scss +172 -172
  18. package/src/scss/core-components/_data-display.scss +9 -9
  19. package/src/scss/core-components/_data-viz.scss +9 -9
  20. package/src/scss/core-components/_detail-panel.scss +1 -1
  21. package/src/scss/core-components/_file-selector.scss +780 -780
  22. package/src/scss/core-components/_filter-card.scss +58 -58
  23. package/src/scss/core-components/_forms.scss +16 -16
  24. package/src/scss/core-components/_grid.scss +293 -293
  25. package/src/scss/core-components/_layout.scss +15 -15
  26. package/src/scss/core-components/_lists.scss +211 -211
  27. package/src/scss/core-components/_loaders.scss +277 -277
  28. package/src/scss/core-components/_logic-tree.scss +280 -280
  29. package/src/scss/core-components/_modals.scss +203 -203
  30. package/src/scss/core-components/_notifications.scss +320 -320
  31. package/src/scss/core-components/_pagers.scss +141 -141
  32. package/src/scss/core-components/_popconfirm.scss +170 -170
  33. package/src/scss/core-components/_profile.scss +405 -405
  34. package/src/scss/core-components/_scrollbars.scss +40 -40
  35. package/src/scss/core-components/_settings-panel.scss +141 -141
  36. package/src/scss/core-components/_statistics.scss +200 -201
  37. package/src/scss/core-components/_tables.scss +900 -900
  38. package/src/scss/core-components/_tabs.scss +504 -504
  39. package/src/scss/core-components/_timeline.scss +589 -589
  40. package/src/scss/core-components/_toasts.scss +425 -425
  41. package/src/scss/core-components/_tooltips.scss +605 -605
  42. package/src/scss/core-components/_utilities.scss +1 -1
  43. package/src/scss/core-components/_web-components-theme.scss +21 -21
  44. package/src/scss/core-components/badges/_badge-base.scss +121 -121
  45. package/src/scss/core-components/badges/_badge-group.scss +25 -25
  46. package/src/scss/core-components/badges/_composite-badge-variants.scss +396 -396
  47. package/src/scss/core-components/badges/_composite-badge.scss +70 -70
  48. package/src/scss/core-components/badges/_index.scss +10 -10
  49. package/src/scss/core-components/badges/_labels.scss +155 -155
  50. package/src/scss/core-components/forms/_checkboxes-radios.scss +205 -205
  51. package/src/scss/core-components/forms/_form-inputs.scss +3 -3
  52. package/src/scss/core-components/forms/_form-layout.scss +66 -66
  53. package/src/scss/core-components/forms/_form-states.scss +115 -115
  54. package/src/scss/core-components/forms/_index.scss +12 -12
  55. package/src/scss/core-components/forms/_input-groups.scss +154 -154
  56. package/src/scss/core-components/forms/_input-wrapper.scss +89 -89
  57. package/src/scss/core-components/forms/_query-editor.scss +313 -313
  58. package/src/scss/core-components/layout/_index.scss +11 -11
  59. package/src/scss/core-components/layout/_layout-container.scss +168 -168
  60. package/src/scss/core-components/layout/_layout-responsive.scss +99 -99
  61. package/src/scss/core-components/layout/_navbar-elements.scss +250 -250
  62. package/src/scss/core-components/layout/_navbar.scss +83 -83
  63. package/src/scss/core-components/layout/_sidebar-states.scss +237 -237
  64. package/src/scss/core-components/layout/_sidebar.scss +234 -234
  65. package/src/scss/main.scss +7 -7
  66. package/src/scss/utilities.scss +740 -740
  67. package/src/scss/variables/_base.scss +228 -228
  68. package/src/scss/variables/_components.scss +748 -748
  69. package/src/scss/variables/_layout.scss +65 -65
  70. package/src/scss/variables/_typography.scss +37 -37
@@ -1,488 +1,488 @@
1
- /* ========================================
2
- Card Components
3
- Cards with headers, bodies, footers, variants, and card sections
4
- ======================================== */
5
- @use '../variables' as *;
6
-
7
- // Cards
8
- .pa-card {
9
- background: var(--pa-card-bg);
10
- border: $card-border-width solid var(--pa-border-color);
11
- border-radius: $card-border-radius;
12
- margin-bottom: $spacing-base;
13
- box-shadow: $shadow-sm;
14
- transition: box-shadow $transition-fast $easing-snappy;
15
- display: flex;
16
- flex-direction: column;
17
- overflow: hidden;
18
-
19
- &:hover {
20
- box-shadow: $shadow-lg;
21
- }
22
-
23
- &__header {
24
- padding: $card-header-padding-v $card-header-padding-h;
25
- min-height: $card-header-min-height;
26
- border-top-left-radius: $card-border-radius;
27
- border-top-right-radius: $card-border-radius;
28
- border-bottom: $border-width-base solid var(--pa-border-color);
29
- background: var(--pa-card-header-bg);
30
- display: flex;
31
- justify-content: space-between;
32
- align-items: center;
33
- gap: $spacing-base; // Gap between header elements (title, description, actions)
34
- min-width: 0; // Enable text truncation
35
-
36
- // Reset margins/paddings/borders for all native elements
37
- // (border-bottom reset prevents .pa-section h3 rule from bleeding in)
38
- h1,
39
- h2,
40
- h3,
41
- h4,
42
- h5,
43
- h6,
44
- p,
45
- ul,
46
- ol,
47
- dl,
48
- blockquote,
49
- pre,
50
- figure,
51
- fieldset {
52
- margin: 0;
53
- padding: 0;
54
- border-bottom: none;
55
- }
56
-
57
- // Specific heading styles
58
- h1,
59
- h2,
60
- h3,
61
- h4,
62
- h5,
63
- h6 {
64
- color: var(--pa-text-color-1);
65
- font-size: $font-size-base;
66
- }
67
-
68
- // Direct heading children - truncate when card is narrow
69
- > h1,
70
- > h2,
71
- > h3,
72
- > h4,
73
- > h5,
74
- > h6 {
75
- min-width: 0;
76
- overflow: hidden;
77
- text-overflow: ellipsis;
78
- white-space: nowrap;
79
- }
80
-
81
- // Description paragraphs - flexible middle, truncate with ellipsis
82
- > p {
83
- flex: 1;
84
- min-width: 0;
85
- overflow: hidden;
86
- text-overflow: ellipsis;
87
- white-space: nowrap;
88
- color: var(--pa-text-color-2);
89
- font-size: $font-size-sm;
90
- }
91
-
92
- // Actions container - fixed, doesn't shrink
93
- .pa-card__actions,
94
- .pa-btn-group {
95
- flex-shrink: 0;
96
- }
97
-
98
- // Buttons in card headers - negative margin to prevent header height growth
99
- .pa-btn {
100
- margin-top: -0.25rem;
101
- margin-bottom: -0.25rem;
102
- flex-shrink: 0;
103
- }
104
-
105
- // Underline modifier - accent border under heading inside card header
106
- &--underlined {
107
- h1, h2, h3, h4, h5, h6 {
108
- border-bottom: $border-width-medium solid var(--pa-accent);
109
- padding-bottom: $spacing-sm;
110
- }
111
-
112
- // Semantic color variants
113
- &.pa-card__header--underline-success h1,
114
- &.pa-card__header--underline-success h2,
115
- &.pa-card__header--underline-success h3,
116
- &.pa-card__header--underline-success h4,
117
- &.pa-card__header--underline-success h5,
118
- &.pa-card__header--underline-success h6 {
119
- border-bottom-color: var(--pa-success-bg);
120
- }
121
-
122
- &.pa-card__header--underline-warning h1,
123
- &.pa-card__header--underline-warning h2,
124
- &.pa-card__header--underline-warning h3,
125
- &.pa-card__header--underline-warning h4,
126
- &.pa-card__header--underline-warning h5,
127
- &.pa-card__header--underline-warning h6 {
128
- border-bottom-color: var(--pa-warning-bg);
129
- }
130
-
131
- &.pa-card__header--underline-danger h1,
132
- &.pa-card__header--underline-danger h2,
133
- &.pa-card__header--underline-danger h3,
134
- &.pa-card__header--underline-danger h4,
135
- &.pa-card__header--underline-danger h5,
136
- &.pa-card__header--underline-danger h6 {
137
- border-bottom-color: var(--pa-danger-bg);
138
- }
139
-
140
- &.pa-card__header--underline-info h1,
141
- &.pa-card__header--underline-info h2,
142
- &.pa-card__header--underline-info h3,
143
- &.pa-card__header--underline-info h4,
144
- &.pa-card__header--underline-info h5,
145
- &.pa-card__header--underline-info h6 {
146
- border-bottom-color: var(--pa-info-bg);
147
- }
148
-
149
- // Theme color slots (1-9)
150
- @for $i from 1 through 9 {
151
- &.pa-card__header--underline-color-#{$i} h1,
152
- &.pa-card__header--underline-color-#{$i} h2,
153
- &.pa-card__header--underline-color-#{$i} h3,
154
- &.pa-card__header--underline-color-#{$i} h4,
155
- &.pa-card__header--underline-color-#{$i} h5,
156
- &.pa-card__header--underline-color-#{$i} h6 {
157
- border-bottom-color: var(--pa-color-#{$i});
158
- }
159
- }
160
- }
161
-
162
- // Wrap modifier - allow heading and description to wrap instead of truncating
163
- &--wrap {
164
- flex-wrap: wrap;
165
-
166
- > h1, > h2, > h3, > h4, > h5, > h6 {
167
- white-space: normal;
168
- overflow: visible;
169
- text-overflow: clip;
170
- }
171
-
172
- > p {
173
- white-space: normal;
174
- flex-basis: 100%;
175
- order: 1;
176
- margin-top: $spacing-xs;
177
- }
178
- }
179
- }
180
-
181
- &__title {
182
- display: flex;
183
- align-items: center;
184
- gap: $spacing-sm;
185
- min-width: 0; // Enable text truncation
186
- flex: 1;
187
-
188
- &-icon {
189
- flex-shrink: 0;
190
- font-size: $font-size-base;
191
- line-height: 1;
192
- }
193
-
194
- &-text {
195
- overflow: hidden;
196
- text-overflow: ellipsis;
197
- white-space: nowrap;
198
- margin: 0;
199
- color: var(--pa-text-color-1);
200
- font-size: $font-size-base;
201
- font-weight: $font-weight-semibold;
202
- line-height: 1;
203
- }
204
- }
205
-
206
- &__body {
207
- padding: $card-body-padding-v $card-body-padding-h;
208
- flex: 1;
209
-
210
- // Remove top margin from first child to avoid double spacing with padding
211
- > :first-child {
212
- margin-top: 0;
213
- }
214
-
215
- &--no-padding {
216
- padding: 0;
217
- }
218
- }
219
-
220
- &__footer {
221
- padding: $card-footer-padding-v $card-footer-padding-h;
222
- border-top: $border-width-base solid var(--pa-border-color);
223
- border-bottom-left-radius: $border-radius-lg;
224
- border-bottom-right-radius: $border-radius-lg;
225
- background: var(--pa-card-footer-bg);
226
- display: flex;
227
- justify-content: space-between;
228
- align-items: center;
229
- }
230
-
231
- &__actions {
232
- display: flex;
233
- gap: $spacing-sm;
234
- align-items: center;
235
- }
236
-
237
- &__meta {
238
- color: var(--pa-text-color-2);
239
- font-size: $font-size-sm;
240
- }
241
-
242
- // Card variants
243
- &--primary {
244
- border-color: var(--pa-accent);
245
-
246
- .pa-card__header {
247
- background-color: var(--pa-accent);
248
- color: var(--pa-btn-primary-text);
249
-
250
- h1,
251
- h2,
252
- h3,
253
- h4,
254
- h5,
255
- h6 {
256
- color: var(--pa-btn-primary-text);
257
- }
258
- }
259
- }
260
-
261
- &--success {
262
- border-color: var(--pa-success-bg);
263
-
264
- .pa-card__header {
265
- background-color: var(--pa-success-bg);
266
- color: var(--pa-btn-success-text);
267
-
268
- h1,
269
- h2,
270
- h3,
271
- h4,
272
- h5,
273
- h6 {
274
- color: var(--pa-btn-success-text);
275
- }
276
- }
277
- }
278
-
279
- &--warning {
280
- border-color: var(--pa-warning-bg);
281
-
282
- .pa-card__header {
283
- background-color: var(--pa-warning-bg);
284
- color: var(--pa-btn-warning-text);
285
-
286
- h1,
287
- h2,
288
- h3,
289
- h4,
290
- h5,
291
- h6 {
292
- color: var(--pa-btn-warning-text);
293
- }
294
- }
295
- }
296
-
297
- &--danger {
298
- border-color: var(--pa-danger-bg);
299
-
300
- .pa-card__header {
301
- background-color: var(--pa-danger-bg);
302
- color: var(--pa-btn-danger-text);
303
-
304
- h1,
305
- h2,
306
- h3,
307
- h4,
308
- h5,
309
- h6 {
310
- color: var(--pa-btn-danger-text);
311
- }
312
- }
313
- }
314
-
315
- &--stat {
316
- .pa-card__body {
317
- padding: $card-stat-padding-v $card-stat-padding-h;
318
- }
319
- }
320
-
321
- // Ghost card - invisible container, same spacing/sizing behavior
322
- // Uses !important to beat dark-mode scoped overrides like
323
- // `.pa-mode-dark .pa-card { box-shadow: ... }` which have (0,2,0) specificity
324
- &--ghost {
325
- background: transparent !important;
326
- border: none !important;
327
- box-shadow: none !important;
328
-
329
- &:hover {
330
- box-shadow: none !important;
331
- }
332
-
333
- .pa-card__header {
334
- background: transparent !important;
335
- border-bottom: none !important;
336
- }
337
-
338
- .pa-card__footer {
339
- background: transparent !important;
340
- border-top: none !important;
341
- }
342
- }
343
-
344
- // Live-data state — persistent tinted background reflecting latest change
345
- // JS swaps the class on each data update; color stays until next update
346
- &--live-up {
347
- background-color: rgba($success-bg, 0.10);
348
- transition: background-color 0.3s ease;
349
- }
350
-
351
- &--live-down {
352
- background-color: rgba($danger-bg, 0.10);
353
- transition: background-color 0.3s ease;
354
- }
355
-
356
- &--live-neutral {
357
- background-color: $card-bg;
358
- transition: background-color 0.3s ease;
359
- }
360
-
361
- // Theme color variants (color-1 through color-9)
362
- // These use theme-customizable colors from --pa-color-* CSS variables
363
- @for $i from 1 through 9 {
364
- &--color-#{$i} {
365
- border-color: var(--pa-color-#{$i});
366
-
367
- .pa-card__header {
368
- background-color: var(--pa-color-#{$i});
369
- color: var(--pa-color-#{$i}-text);
370
-
371
- h1,
372
- h2,
373
- h3,
374
- h4,
375
- h5,
376
- h6 {
377
- color: var(--pa-color-#{$i}-text);
378
- }
379
- }
380
- }
381
- }
382
-
383
- // Card tabs
384
- &__tabs {
385
- display: flex;
386
- border-bottom: $border-width-base solid var(--pa-border-color);
387
- background: var(--pa-card-tabs-bg);
388
- }
389
-
390
- &__tab {
391
- padding: $card-footer-padding-v $card-footer-padding-h;
392
- border: none;
393
- background: none;
394
- color: var(--pa-text-color-2);
395
- cursor: pointer;
396
- transition: all $transition-fast $easing-snappy;
397
- border-bottom: $border-width-medium solid transparent;
398
-
399
- &:hover {
400
- color: var(--pa-text-color-1);
401
- background-color: rgba($accent-color, $card-tab-hover-opacity);
402
- }
403
-
404
- &--active {
405
- color: var(--pa-accent);
406
- border-bottom-color: var(--pa-accent);
407
- }
408
- }
409
-
410
- &__tab-content {
411
- display: none;
412
-
413
- &--active {
414
- display: block;
415
- }
416
- }
417
-
418
- // Inline tabs in header (for side-by-side card alignment)
419
- &__tabs--inline {
420
- display: flex;
421
- gap: $spacing-xs;
422
- margin: -$card-header-padding-v 0; // Negative margin to fill header height
423
- border-bottom: none;
424
- background: none;
425
-
426
- .pa-card__tab {
427
- padding: $card-tab-inline-padding-v $card-tab-inline-padding-h;
428
- border: none;
429
- border-radius: $border-radius;
430
- font-size: $font-size-sm;
431
- background: transparent;
432
- color: var(--pa-text-color-2);
433
- cursor: pointer;
434
- transition: all $transition-fast $easing-snappy;
435
-
436
- &:hover {
437
- background-color: rgba($accent-color, $card-tab-hover-opacity);
438
- color: var(--pa-text-color-1);
439
- }
440
-
441
- &--active {
442
- background: var(--pa-accent);
443
- color: var(--pa-btn-primary-text);
444
- }
445
- }
446
- }
447
- }
448
-
449
- // Clickable cards (anchor-wrapped)
450
- a.pa-card {
451
- text-decoration: none;
452
- display: block;
453
- color: inherit;
454
-
455
- &:hover,
456
- &:visited {
457
- color: inherit;
458
- }
459
-
460
- // Reset heading colors inside clickable cards
461
- h1, h2, h3, h4, h5, h6 {
462
- color: var(--pa-text-color-1);
463
- }
464
-
465
- p {
466
- color: var(--pa-text-color-2);
467
- }
468
- }
469
-
470
- // Card sections
471
- .pa-section {
472
- margin-bottom: $section-margin-v;
473
-
474
- > h3 {
475
- color: var(--pa-text-color-1);
476
- margin-bottom: $spacing-base;
477
- border-bottom: $border-width-medium solid var(--pa-accent);
478
- padding-bottom: $spacing-sm;
479
- }
480
- }
481
-
482
- // Section title (standalone)
483
- .pa-section-title {
484
- color: var(--pa-text-color-1);
485
- margin-bottom: $spacing-base;
486
- border-bottom: $border-width-medium solid var(--pa-accent);
487
- padding-bottom: $spacing-sm;
488
- }
1
+ /* ========================================
2
+ Card Components
3
+ Cards with headers, bodies, footers, variants, and card sections
4
+ ======================================== */
5
+ @use '../variables' as *;
6
+
7
+ // Cards
8
+ .pa-card {
9
+ background: var(--pa-card-bg);
10
+ border: $card-border-width solid var(--pa-border-color);
11
+ border-radius: var(--pa-border-radius-lg);
12
+ margin-bottom: $spacing-base;
13
+ box-shadow: $shadow-sm;
14
+ transition: box-shadow $transition-fast $easing-snappy;
15
+ display: flex;
16
+ flex-direction: column;
17
+ overflow: hidden;
18
+
19
+ &:hover {
20
+ box-shadow: $shadow-lg;
21
+ }
22
+
23
+ &__header {
24
+ padding: $card-header-padding-v $card-header-padding-h;
25
+ min-height: $card-header-min-height;
26
+ border-top-left-radius: $card-border-radius;
27
+ border-top-right-radius: $card-border-radius;
28
+ border-bottom: $border-width-base solid var(--pa-border-color);
29
+ background: var(--pa-card-header-bg);
30
+ display: flex;
31
+ justify-content: space-between;
32
+ align-items: center;
33
+ gap: $spacing-base; // Gap between header elements (title, description, actions)
34
+ min-width: 0; // Enable text truncation
35
+
36
+ // Reset margins/paddings/borders for all native elements
37
+ // (border-bottom reset prevents .pa-section h3 rule from bleeding in)
38
+ h1,
39
+ h2,
40
+ h3,
41
+ h4,
42
+ h5,
43
+ h6,
44
+ p,
45
+ ul,
46
+ ol,
47
+ dl,
48
+ blockquote,
49
+ pre,
50
+ figure,
51
+ fieldset {
52
+ margin: 0;
53
+ padding: 0;
54
+ border-bottom: none;
55
+ }
56
+
57
+ // Specific heading styles
58
+ h1,
59
+ h2,
60
+ h3,
61
+ h4,
62
+ h5,
63
+ h6 {
64
+ color: var(--pa-text-color-1);
65
+ font-size: $font-size-base;
66
+ }
67
+
68
+ // Direct heading children - truncate when card is narrow
69
+ > h1,
70
+ > h2,
71
+ > h3,
72
+ > h4,
73
+ > h5,
74
+ > h6 {
75
+ min-width: 0;
76
+ overflow: hidden;
77
+ text-overflow: ellipsis;
78
+ white-space: nowrap;
79
+ }
80
+
81
+ // Description paragraphs - flexible middle, truncate with ellipsis
82
+ > p {
83
+ flex: 1;
84
+ min-width: 0;
85
+ overflow: hidden;
86
+ text-overflow: ellipsis;
87
+ white-space: nowrap;
88
+ color: var(--pa-text-color-2);
89
+ font-size: $font-size-sm;
90
+ }
91
+
92
+ // Actions container - fixed, doesn't shrink
93
+ .pa-card__actions,
94
+ .pa-btn-group {
95
+ flex-shrink: 0;
96
+ }
97
+
98
+ // Buttons in card headers - negative margin to prevent header height growth
99
+ .pa-btn {
100
+ margin-top: -0.25rem;
101
+ margin-bottom: -0.25rem;
102
+ flex-shrink: 0;
103
+ }
104
+
105
+ // Underline modifier - accent border under heading inside card header
106
+ &--underlined {
107
+ h1, h2, h3, h4, h5, h6 {
108
+ border-bottom: $border-width-medium solid var(--pa-accent);
109
+ padding-bottom: $spacing-sm;
110
+ }
111
+
112
+ // Semantic color variants
113
+ &.pa-card__header--underline-success h1,
114
+ &.pa-card__header--underline-success h2,
115
+ &.pa-card__header--underline-success h3,
116
+ &.pa-card__header--underline-success h4,
117
+ &.pa-card__header--underline-success h5,
118
+ &.pa-card__header--underline-success h6 {
119
+ border-bottom-color: var(--pa-success-bg);
120
+ }
121
+
122
+ &.pa-card__header--underline-warning h1,
123
+ &.pa-card__header--underline-warning h2,
124
+ &.pa-card__header--underline-warning h3,
125
+ &.pa-card__header--underline-warning h4,
126
+ &.pa-card__header--underline-warning h5,
127
+ &.pa-card__header--underline-warning h6 {
128
+ border-bottom-color: var(--pa-warning-bg);
129
+ }
130
+
131
+ &.pa-card__header--underline-danger h1,
132
+ &.pa-card__header--underline-danger h2,
133
+ &.pa-card__header--underline-danger h3,
134
+ &.pa-card__header--underline-danger h4,
135
+ &.pa-card__header--underline-danger h5,
136
+ &.pa-card__header--underline-danger h6 {
137
+ border-bottom-color: var(--pa-danger-bg);
138
+ }
139
+
140
+ &.pa-card__header--underline-info h1,
141
+ &.pa-card__header--underline-info h2,
142
+ &.pa-card__header--underline-info h3,
143
+ &.pa-card__header--underline-info h4,
144
+ &.pa-card__header--underline-info h5,
145
+ &.pa-card__header--underline-info h6 {
146
+ border-bottom-color: var(--pa-info-bg);
147
+ }
148
+
149
+ // Theme color slots (1-9)
150
+ @for $i from 1 through 9 {
151
+ &.pa-card__header--underline-color-#{$i} h1,
152
+ &.pa-card__header--underline-color-#{$i} h2,
153
+ &.pa-card__header--underline-color-#{$i} h3,
154
+ &.pa-card__header--underline-color-#{$i} h4,
155
+ &.pa-card__header--underline-color-#{$i} h5,
156
+ &.pa-card__header--underline-color-#{$i} h6 {
157
+ border-bottom-color: var(--pa-color-#{$i});
158
+ }
159
+ }
160
+ }
161
+
162
+ // Wrap modifier - allow heading and description to wrap instead of truncating
163
+ &--wrap {
164
+ flex-wrap: wrap;
165
+
166
+ > h1, > h2, > h3, > h4, > h5, > h6 {
167
+ white-space: normal;
168
+ overflow: visible;
169
+ text-overflow: clip;
170
+ }
171
+
172
+ > p {
173
+ white-space: normal;
174
+ flex-basis: 100%;
175
+ order: 1;
176
+ margin-top: $spacing-xs;
177
+ }
178
+ }
179
+ }
180
+
181
+ &__title {
182
+ display: flex;
183
+ align-items: center;
184
+ gap: $spacing-sm;
185
+ min-width: 0; // Enable text truncation
186
+ flex: 1;
187
+
188
+ &-icon {
189
+ flex-shrink: 0;
190
+ font-size: $font-size-base;
191
+ line-height: 1;
192
+ }
193
+
194
+ &-text {
195
+ overflow: hidden;
196
+ text-overflow: ellipsis;
197
+ white-space: nowrap;
198
+ margin: 0;
199
+ color: var(--pa-text-color-1);
200
+ font-size: $font-size-base;
201
+ font-weight: $font-weight-semibold;
202
+ line-height: 1;
203
+ }
204
+ }
205
+
206
+ &__body {
207
+ padding: $card-body-padding-v $card-body-padding-h;
208
+ flex: 1;
209
+
210
+ // Remove top margin from first child to avoid double spacing with padding
211
+ > :first-child {
212
+ margin-top: 0;
213
+ }
214
+
215
+ &--no-padding {
216
+ padding: 0;
217
+ }
218
+ }
219
+
220
+ &__footer {
221
+ padding: $card-footer-padding-v $card-footer-padding-h;
222
+ border-top: $border-width-base solid var(--pa-border-color);
223
+ border-bottom-left-radius: var(--pa-border-radius-lg);
224
+ border-bottom-right-radius: var(--pa-border-radius-lg);
225
+ background: var(--pa-card-footer-bg);
226
+ display: flex;
227
+ justify-content: space-between;
228
+ align-items: center;
229
+ }
230
+
231
+ &__actions {
232
+ display: flex;
233
+ gap: $spacing-sm;
234
+ align-items: center;
235
+ }
236
+
237
+ &__meta {
238
+ color: var(--pa-text-color-2);
239
+ font-size: $font-size-sm;
240
+ }
241
+
242
+ // Card variants
243
+ &--primary {
244
+ border-color: var(--pa-accent);
245
+
246
+ .pa-card__header {
247
+ background-color: var(--pa-accent);
248
+ color: var(--pa-btn-primary-text);
249
+
250
+ h1,
251
+ h2,
252
+ h3,
253
+ h4,
254
+ h5,
255
+ h6 {
256
+ color: var(--pa-btn-primary-text);
257
+ }
258
+ }
259
+ }
260
+
261
+ &--success {
262
+ border-color: var(--pa-success-bg);
263
+
264
+ .pa-card__header {
265
+ background-color: var(--pa-success-bg);
266
+ color: var(--pa-btn-success-text);
267
+
268
+ h1,
269
+ h2,
270
+ h3,
271
+ h4,
272
+ h5,
273
+ h6 {
274
+ color: var(--pa-btn-success-text);
275
+ }
276
+ }
277
+ }
278
+
279
+ &--warning {
280
+ border-color: var(--pa-warning-bg);
281
+
282
+ .pa-card__header {
283
+ background-color: var(--pa-warning-bg);
284
+ color: var(--pa-btn-warning-text);
285
+
286
+ h1,
287
+ h2,
288
+ h3,
289
+ h4,
290
+ h5,
291
+ h6 {
292
+ color: var(--pa-btn-warning-text);
293
+ }
294
+ }
295
+ }
296
+
297
+ &--danger {
298
+ border-color: var(--pa-danger-bg);
299
+
300
+ .pa-card__header {
301
+ background-color: var(--pa-danger-bg);
302
+ color: var(--pa-btn-danger-text);
303
+
304
+ h1,
305
+ h2,
306
+ h3,
307
+ h4,
308
+ h5,
309
+ h6 {
310
+ color: var(--pa-btn-danger-text);
311
+ }
312
+ }
313
+ }
314
+
315
+ &--stat {
316
+ .pa-card__body {
317
+ padding: $card-stat-padding-v $card-stat-padding-h;
318
+ }
319
+ }
320
+
321
+ // Ghost card - invisible container, same spacing/sizing behavior
322
+ // Uses !important to beat dark-mode scoped overrides like
323
+ // `.pa-mode-dark .pa-card { box-shadow: ... }` which have (0,2,0) specificity
324
+ &--ghost {
325
+ background: transparent !important;
326
+ border: none !important;
327
+ box-shadow: none !important;
328
+
329
+ &:hover {
330
+ box-shadow: none !important;
331
+ }
332
+
333
+ .pa-card__header {
334
+ background: transparent !important;
335
+ border-bottom: none !important;
336
+ }
337
+
338
+ .pa-card__footer {
339
+ background: transparent !important;
340
+ border-top: none !important;
341
+ }
342
+ }
343
+
344
+ // Live-data state — persistent tinted background reflecting latest change
345
+ // JS swaps the class on each data update; color stays until next update
346
+ &--live-up {
347
+ background-color: rgba($success-bg, 0.10);
348
+ transition: background-color 0.3s ease;
349
+ }
350
+
351
+ &--live-down {
352
+ background-color: rgba($danger-bg, 0.10);
353
+ transition: background-color 0.3s ease;
354
+ }
355
+
356
+ &--live-neutral {
357
+ background-color: $card-bg;
358
+ transition: background-color 0.3s ease;
359
+ }
360
+
361
+ // Theme color variants (color-1 through color-9)
362
+ // These use theme-customizable colors from --pa-color-* CSS variables
363
+ @for $i from 1 through 9 {
364
+ &--color-#{$i} {
365
+ border-color: var(--pa-color-#{$i});
366
+
367
+ .pa-card__header {
368
+ background-color: var(--pa-color-#{$i});
369
+ color: var(--pa-color-#{$i}-text);
370
+
371
+ h1,
372
+ h2,
373
+ h3,
374
+ h4,
375
+ h5,
376
+ h6 {
377
+ color: var(--pa-color-#{$i}-text);
378
+ }
379
+ }
380
+ }
381
+ }
382
+
383
+ // Card tabs
384
+ &__tabs {
385
+ display: flex;
386
+ border-bottom: $border-width-base solid var(--pa-border-color);
387
+ background: var(--pa-card-tabs-bg);
388
+ }
389
+
390
+ &__tab {
391
+ padding: $card-footer-padding-v $card-footer-padding-h;
392
+ border: none;
393
+ background: none;
394
+ color: var(--pa-text-color-2);
395
+ cursor: pointer;
396
+ transition: all $transition-fast $easing-snappy;
397
+ border-bottom: $border-width-medium solid transparent;
398
+
399
+ &:hover {
400
+ color: var(--pa-text-color-1);
401
+ background-color: rgba($accent-color, $card-tab-hover-opacity);
402
+ }
403
+
404
+ &--active {
405
+ color: var(--pa-accent);
406
+ border-bottom-color: var(--pa-accent);
407
+ }
408
+ }
409
+
410
+ &__tab-content {
411
+ display: none;
412
+
413
+ &--active {
414
+ display: block;
415
+ }
416
+ }
417
+
418
+ // Inline tabs in header (for side-by-side card alignment)
419
+ &__tabs--inline {
420
+ display: flex;
421
+ gap: $spacing-xs;
422
+ margin: -$card-header-padding-v 0; // Negative margin to fill header height
423
+ border-bottom: none;
424
+ background: none;
425
+
426
+ .pa-card__tab {
427
+ padding: $card-tab-inline-padding-v $card-tab-inline-padding-h;
428
+ border: none;
429
+ border-radius: var(--pa-border-radius);
430
+ font-size: $font-size-sm;
431
+ background: transparent;
432
+ color: var(--pa-text-color-2);
433
+ cursor: pointer;
434
+ transition: all $transition-fast $easing-snappy;
435
+
436
+ &:hover {
437
+ background-color: rgba($accent-color, $card-tab-hover-opacity);
438
+ color: var(--pa-text-color-1);
439
+ }
440
+
441
+ &--active {
442
+ background: var(--pa-accent);
443
+ color: var(--pa-btn-primary-text);
444
+ }
445
+ }
446
+ }
447
+ }
448
+
449
+ // Clickable cards (anchor-wrapped)
450
+ a.pa-card {
451
+ text-decoration: none;
452
+ display: block;
453
+ color: inherit;
454
+
455
+ &:hover,
456
+ &:visited {
457
+ color: inherit;
458
+ }
459
+
460
+ // Reset heading colors inside clickable cards
461
+ h1, h2, h3, h4, h5, h6 {
462
+ color: var(--pa-text-color-1);
463
+ }
464
+
465
+ p {
466
+ color: var(--pa-text-color-2);
467
+ }
468
+ }
469
+
470
+ // Card sections
471
+ .pa-section {
472
+ margin-bottom: $section-margin-v;
473
+
474
+ > h3 {
475
+ color: var(--pa-text-color-1);
476
+ margin-bottom: $spacing-base;
477
+ border-bottom: $border-width-medium solid var(--pa-accent);
478
+ padding-bottom: $spacing-sm;
479
+ }
480
+ }
481
+
482
+ // Section title (standalone)
483
+ .pa-section-title {
484
+ color: var(--pa-text-color-1);
485
+ margin-bottom: $spacing-base;
486
+ border-bottom: $border-width-medium solid var(--pa-accent);
487
+ padding-bottom: $spacing-sm;
488
+ }