@keenmate/pure-admin-core 2.6.0 → 2.7.1
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.
- package/README.md +24 -16
- package/dist/css/main.css +1865 -257
- package/package.json +1 -1
- package/src/scss/_base-css-variables.scss +37 -19
- package/src/scss/_core.scss +11 -0
- package/src/scss/core-components/_alerts.scss +2 -2
- package/src/scss/core-components/_base.scss +19 -2
- package/src/scss/core-components/_buttons.scss +12 -8
- package/src/scss/core-components/_callouts.scss +1 -1
- package/src/scss/core-components/_cards.scss +4 -4
- package/src/scss/core-components/_checkbox-lists.scss +2 -2
- package/src/scss/core-components/_comparison.scss +7 -4
- package/src/scss/core-components/_data-display.scss +24 -15
- package/src/scss/core-components/_data-viz.scss +139 -131
- package/src/scss/core-components/_file-selector.scss +34 -34
- package/src/scss/core-components/_kpi-base.scss +169 -0
- package/src/scss/core-components/_kpi-bento.scss +182 -0
- package/src/scss/core-components/_kpi-comparison-gauges.scss +132 -0
- package/src/scss/core-components/_kpi-editorial-minimal.scss +128 -0
- package/src/scss/core-components/_kpi-hero-supporting.scss +210 -0
- package/src/scss/core-components/_kpi-numeric-strip.scss +154 -0
- package/src/scss/core-components/_kpi-sparkline-list.scss +171 -0
- package/src/scss/core-components/_kpi-terminal.scss +229 -0
- package/src/scss/core-components/_lists.scss +4 -4
- package/src/scss/core-components/_logic-tree.scss +2 -2
- package/src/scss/core-components/_modals.scss +69 -0
- package/src/scss/core-components/_notifications.scss +17 -17
- package/src/scss/core-components/_popconfirm.scss +1 -1
- package/src/scss/core-components/_statistics.scss +25 -19
- package/src/scss/core-components/_tabs.scss +12 -12
- package/src/scss/core-components/_timeline.scss +30 -30
- package/src/scss/core-components/badges/_composite-badge-variants.scss +7 -7
- package/src/scss/core-components/badges/_composite-badge.scss +1 -1
- package/src/scss/core-components/badges/_labels.scss +6 -6
- package/src/scss/core-components/forms/_input-wrapper.scss +1 -1
- package/src/scss/core-components/forms/_query-editor.scss +10 -10
- package/src/scss/core-components/layout/_sidebar-states.scss +1 -0
- package/src/scss/core-components/layout/_sidebar.scss +1 -0
- package/src/scss/variables/_colors.scss +1 -0
- package/src/scss/variables/_components.scss +3 -2
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
cursor: pointer;
|
|
46
46
|
|
|
47
47
|
&:hover {
|
|
48
|
-
border-color:
|
|
49
|
-
background:
|
|
48
|
+
border-color: var(--pa-accent);
|
|
49
|
+
background: color-mix(in srgb, var(--pa-accent) 5%, transparent);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
&--active {
|
|
53
|
-
border-color:
|
|
54
|
-
background:
|
|
53
|
+
border-color: var(--pa-accent);
|
|
54
|
+
background: color-mix(in srgb, var(--pa-accent) 10%, transparent);
|
|
55
55
|
border-style: solid;
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
margin-bottom: $spacing-xs;
|
|
82
82
|
|
|
83
83
|
strong {
|
|
84
|
-
color:
|
|
84
|
+
color: var(--pa-accent);
|
|
85
85
|
font-weight: $font-weight-semibold;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
transition: all $transition-fast $easing-snappy;
|
|
128
128
|
|
|
129
129
|
&:hover {
|
|
130
|
-
border-color:
|
|
130
|
+
border-color: var(--pa-accent);
|
|
131
131
|
box-shadow: 0 1.6px 4.8px rgba(0, 0, 0, 0.1);
|
|
132
132
|
}
|
|
133
133
|
|
|
@@ -159,7 +159,7 @@
|
|
|
159
159
|
width: 2rem;
|
|
160
160
|
height: 2rem;
|
|
161
161
|
border: none;
|
|
162
|
-
background:
|
|
162
|
+
background: var(--pa-danger);
|
|
163
163
|
color: #ffffff;
|
|
164
164
|
cursor: pointer;
|
|
165
165
|
border-radius: 50%;
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
|
|
183
183
|
&-remove:hover {
|
|
184
184
|
transform: scale(1.1);
|
|
185
|
-
background:
|
|
185
|
+
background: color-mix(in srgb, var(--pa-danger) 90%, transparent);
|
|
186
186
|
}
|
|
187
187
|
}
|
|
188
188
|
|
|
@@ -230,7 +230,7 @@
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
&-remove:hover {
|
|
233
|
-
background:
|
|
233
|
+
background: var(--pa-danger);
|
|
234
234
|
transform: scale(1.1);
|
|
235
235
|
}
|
|
236
236
|
}
|
|
@@ -252,7 +252,7 @@
|
|
|
252
252
|
transition: background-color $transition-fast $easing-snappy;
|
|
253
253
|
|
|
254
254
|
&:hover {
|
|
255
|
-
background-color:
|
|
255
|
+
background-color: color-mix(in srgb, var(--pa-accent) 10%, transparent);
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
&:not(:last-child)::after {
|
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
|
|
267
267
|
&-count {
|
|
268
268
|
font-weight: $font-weight-medium;
|
|
269
|
-
color:
|
|
269
|
+
color: var(--pa-accent);
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
&-size {
|
|
@@ -350,7 +350,7 @@
|
|
|
350
350
|
justify-content: center;
|
|
351
351
|
|
|
352
352
|
&:hover {
|
|
353
|
-
background:
|
|
353
|
+
background: color-mix(in srgb, var(--pa-text-color-2) 10%, transparent);
|
|
354
354
|
color: var(--pa-text-color-1);
|
|
355
355
|
}
|
|
356
356
|
}
|
|
@@ -391,11 +391,11 @@
|
|
|
391
391
|
|
|
392
392
|
tbody tr {
|
|
393
393
|
&:hover {
|
|
394
|
-
background:
|
|
394
|
+
background: color-mix(in srgb, var(--pa-accent) 5%, transparent);
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
&.uploading {
|
|
398
|
-
background:
|
|
398
|
+
background: color-mix(in srgb, var(--pa-accent) 10%, transparent);
|
|
399
399
|
}
|
|
400
400
|
}
|
|
401
401
|
}
|
|
@@ -418,7 +418,7 @@
|
|
|
418
418
|
|
|
419
419
|
&__progress-bar {
|
|
420
420
|
height: 6.4px;
|
|
421
|
-
background:
|
|
421
|
+
background: color-mix(in srgb, var(--pa-accent) 20%, transparent);
|
|
422
422
|
border-radius: var(--pa-border-radius-sm);
|
|
423
423
|
overflow: hidden;
|
|
424
424
|
margin-bottom: $spacing-xs;
|
|
@@ -426,7 +426,7 @@
|
|
|
426
426
|
|
|
427
427
|
&__progress-fill {
|
|
428
428
|
height: 100%;
|
|
429
|
-
background:
|
|
429
|
+
background: var(--pa-accent);
|
|
430
430
|
border-radius: var(--pa-border-radius-sm);
|
|
431
431
|
transition: width 0.48s ease;
|
|
432
432
|
}
|
|
@@ -446,15 +446,15 @@
|
|
|
446
446
|
}
|
|
447
447
|
|
|
448
448
|
&--uploading {
|
|
449
|
-
color:
|
|
449
|
+
color: var(--pa-accent);
|
|
450
450
|
}
|
|
451
451
|
|
|
452
452
|
&--complete {
|
|
453
|
-
color:
|
|
453
|
+
color: var(--pa-success);
|
|
454
454
|
}
|
|
455
455
|
|
|
456
456
|
&--error {
|
|
457
|
-
color:
|
|
457
|
+
color: var(--pa-danger);
|
|
458
458
|
}
|
|
459
459
|
}
|
|
460
460
|
|
|
@@ -469,7 +469,7 @@
|
|
|
469
469
|
height: 3.2rem;
|
|
470
470
|
border: $border-width-base solid var(--pa-border-color);
|
|
471
471
|
background: var(--pa-card-bg);
|
|
472
|
-
color:
|
|
472
|
+
color: var(--pa-danger);
|
|
473
473
|
cursor: pointer;
|
|
474
474
|
border-radius: var(--pa-border-radius-sm);
|
|
475
475
|
font-size: $font-size-2xl;
|
|
@@ -481,9 +481,9 @@
|
|
|
481
481
|
font-weight: $font-weight-bold;
|
|
482
482
|
|
|
483
483
|
&:hover {
|
|
484
|
-
background:
|
|
484
|
+
background: var(--pa-danger);
|
|
485
485
|
color: #ffffff;
|
|
486
|
-
border-color:
|
|
486
|
+
border-color: var(--pa-danger);
|
|
487
487
|
transform: scale(1.1);
|
|
488
488
|
}
|
|
489
489
|
}
|
|
@@ -529,9 +529,9 @@
|
|
|
529
529
|
display: flex;
|
|
530
530
|
align-items: center;
|
|
531
531
|
justify-content: center;
|
|
532
|
-
background:
|
|
532
|
+
background: color-mix(in srgb, var(--pa-accent) 10%, transparent);
|
|
533
533
|
border-radius: var(--pa-border-radius);
|
|
534
|
-
color:
|
|
534
|
+
color: var(--pa-accent);
|
|
535
535
|
}
|
|
536
536
|
|
|
537
537
|
&__info {
|
|
@@ -571,8 +571,8 @@
|
|
|
571
571
|
justify-content: center;
|
|
572
572
|
|
|
573
573
|
&:hover {
|
|
574
|
-
background:
|
|
575
|
-
color:
|
|
574
|
+
background: color-mix(in srgb, var(--pa-danger) 10%, transparent);
|
|
575
|
+
color: var(--pa-danger);
|
|
576
576
|
}
|
|
577
577
|
|
|
578
578
|
&::before {
|
|
@@ -626,7 +626,7 @@
|
|
|
626
626
|
justify-content: center;
|
|
627
627
|
|
|
628
628
|
&:hover {
|
|
629
|
-
background:
|
|
629
|
+
background: var(--pa-danger);
|
|
630
630
|
transform: scale(1.1);
|
|
631
631
|
}
|
|
632
632
|
|
|
@@ -656,14 +656,14 @@
|
|
|
656
656
|
|
|
657
657
|
&__bar {
|
|
658
658
|
height: 6.4px;
|
|
659
|
-
background:
|
|
659
|
+
background: color-mix(in srgb, var(--pa-accent) 20%, transparent);
|
|
660
660
|
border-radius: var(--pa-border-radius-sm);
|
|
661
661
|
overflow: hidden;
|
|
662
662
|
}
|
|
663
663
|
|
|
664
664
|
&__fill {
|
|
665
665
|
height: 100%;
|
|
666
|
-
background:
|
|
666
|
+
background: var(--pa-accent);
|
|
667
667
|
border-radius: var(--pa-border-radius-sm);
|
|
668
668
|
transition: width 0.48s ease;
|
|
669
669
|
}
|
|
@@ -682,11 +682,11 @@
|
|
|
682
682
|
font-weight: $font-weight-semibold;
|
|
683
683
|
|
|
684
684
|
&--complete {
|
|
685
|
-
color:
|
|
685
|
+
color: var(--pa-success);
|
|
686
686
|
}
|
|
687
687
|
|
|
688
688
|
&--error {
|
|
689
|
-
color:
|
|
689
|
+
color: var(--pa-danger);
|
|
690
690
|
}
|
|
691
691
|
}
|
|
692
692
|
}
|
|
@@ -753,9 +753,9 @@
|
|
|
753
753
|
|
|
754
754
|
// Drag Overlay (for data-overlay-target feature)
|
|
755
755
|
.pa-file-dropzone-overlay {
|
|
756
|
-
background:
|
|
756
|
+
background: color-mix(in srgb, var(--pa-accent) 15%, transparent);
|
|
757
757
|
backdrop-filter: blur(3.2px);
|
|
758
|
-
border: 4.8px dashed
|
|
758
|
+
border: 4.8px dashed var(--pa-accent);
|
|
759
759
|
border-radius: var(--pa-border-radius);
|
|
760
760
|
display: flex;
|
|
761
761
|
align-items: center;
|
|
@@ -775,6 +775,6 @@
|
|
|
775
775
|
&__text {
|
|
776
776
|
font-size: $font-size-xl;
|
|
777
777
|
font-weight: $font-weight-semibold;
|
|
778
|
-
color:
|
|
778
|
+
color: var(--pa-accent);
|
|
779
779
|
}
|
|
780
780
|
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/* ========================================
|
|
2
|
+
KPI · shared base
|
|
3
|
+
Cross-cutting building blocks used by every pa-kpi-* showcase.
|
|
4
|
+
Tokens (--pa-positive, --pa-detail-bg, --pa-chart-trendline-*) live in
|
|
5
|
+
_base-css-variables.scss; this file only defines the shared class
|
|
6
|
+
surface that consumes them.
|
|
7
|
+
======================================== */
|
|
8
|
+
@use '../variables' as *;
|
|
9
|
+
|
|
10
|
+
/* ----- LIVE indicator (title-bar pulse) ---------------------------------
|
|
11
|
+
Used in every KPI card header — a small mono "LIVE" caption with a
|
|
12
|
+
pulsing green dot. Sits next to the card title. */
|
|
13
|
+
.pa-kpi-live {
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: 0.6rem;
|
|
17
|
+
font-family: var(--base-font-family-mono);
|
|
18
|
+
font-size: 1.2rem;
|
|
19
|
+
font-weight: 600;
|
|
20
|
+
letter-spacing: 0.06em;
|
|
21
|
+
color: var(--pa-text-secondary);
|
|
22
|
+
|
|
23
|
+
&__dot {
|
|
24
|
+
width: 0.8rem;
|
|
25
|
+
height: 0.8rem;
|
|
26
|
+
border-radius: 50%;
|
|
27
|
+
background: var(--pa-positive);
|
|
28
|
+
box-shadow: 0 0 6px var(--pa-positive);
|
|
29
|
+
animation: pa-kpi-pulse 1.6s ease-in-out infinite;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@keyframes pa-kpi-pulse {
|
|
34
|
+
50% { opacity: 0.35; }
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* ----- Card header row --------------------------------------------------
|
|
38
|
+
Title (h2/h3 by author choice) on one side, controls + LIVE on the other.
|
|
39
|
+
Wraps onto multiple rows on narrow cards. Every showcase uses this shape. */
|
|
40
|
+
.pa-kpi-header {
|
|
41
|
+
display: flex;
|
|
42
|
+
justify-content: space-between;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: 1.6rem;
|
|
45
|
+
flex-wrap: wrap;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* ----- Card footer caption ---------------------------------------------
|
|
49
|
+
Two-line mono caption row at the bottom of the card (left: data source,
|
|
50
|
+
right: timestamp). Strong text inside picks up the focal color so things
|
|
51
|
+
like a metric name or count stand out. */
|
|
52
|
+
.pa-kpi-footer {
|
|
53
|
+
display: flex;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
align-items: center;
|
|
56
|
+
flex-wrap: wrap;
|
|
57
|
+
gap: 1rem;
|
|
58
|
+
font-family: var(--base-font-family-mono);
|
|
59
|
+
font-size: 1.2rem;
|
|
60
|
+
color: var(--pa-text-secondary);
|
|
61
|
+
|
|
62
|
+
strong {
|
|
63
|
+
color: var(--pa-text-color-1);
|
|
64
|
+
font-weight: 700;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ----- Sparkline endpoint dot ------------------------------------------
|
|
69
|
+
The SVG circle that marks the end of a sparkline is converted to a CSS
|
|
70
|
+
span at init time — the SVG uses preserveAspectRatio="none" so an
|
|
71
|
+
embedded <circle> renders as an oval at non-square aspect ratios.
|
|
72
|
+
See kpi-showcases.js for the conversion; here we only style the result. */
|
|
73
|
+
.pa-kpi-spark-dot {
|
|
74
|
+
position: absolute;
|
|
75
|
+
width: 6px;
|
|
76
|
+
height: 6px;
|
|
77
|
+
margin: -3px 0 0 -3px; /* centre on the (left, top) anchor */
|
|
78
|
+
border-radius: 50%;
|
|
79
|
+
background: currentColor; /* inherits sentiment color from chart wrapper */
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Wrapper inserted around an SVG sparkline at init time when its parent
|
|
84
|
+
isn't already a positioned anchor — so the .pa-kpi-spark-dot can be
|
|
85
|
+
absolutely positioned relative to the chart. */
|
|
86
|
+
.pa-kpi-spark-wrap {
|
|
87
|
+
display: block;
|
|
88
|
+
position: relative;
|
|
89
|
+
width: 100%;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* ----- Hover detail popover --------------------------------------------
|
|
93
|
+
Bloomberg-dark by default regardless of host theme (terminal/data-dashboard
|
|
94
|
+
aesthetic). Override the --pa-detail-* tokens at :root or .pa-kpi-detail
|
|
95
|
+
level for a light/theme-aware variant.
|
|
96
|
+
|
|
97
|
+
Positioned by Floating UI anchored to a virtual element at the cursor —
|
|
98
|
+
the JS appends each popover to <body> at init so ancestor overflow:hidden
|
|
99
|
+
doesn't clip it. position: fixed because cursor coords are viewport-
|
|
100
|
+
relative; pointer-events:none so the cursor passes through cleanly and
|
|
101
|
+
tile mouseleave fires reliably. */
|
|
102
|
+
.pa-kpi-detail {
|
|
103
|
+
position: fixed;
|
|
104
|
+
top: 0;
|
|
105
|
+
left: 0;
|
|
106
|
+
visibility: hidden;
|
|
107
|
+
pointer-events: none;
|
|
108
|
+
z-index: 9000;
|
|
109
|
+
min-width: 26rem;
|
|
110
|
+
max-width: 32rem;
|
|
111
|
+
background: var(--pa-detail-bg);
|
|
112
|
+
color: var(--pa-detail-text);
|
|
113
|
+
padding: 1.2rem 1.5rem;
|
|
114
|
+
font-family: var(--base-font-family-mono);
|
|
115
|
+
font-size: 1.25rem;
|
|
116
|
+
line-height: 1.5;
|
|
117
|
+
border-radius: 0.4rem;
|
|
118
|
+
box-shadow: var(--pa-detail-shadow);
|
|
119
|
+
|
|
120
|
+
&[data-show] {
|
|
121
|
+
visibility: visible;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
&__title {
|
|
125
|
+
text-transform: uppercase;
|
|
126
|
+
letter-spacing: 0.08em;
|
|
127
|
+
font-size: 1.05rem;
|
|
128
|
+
font-weight: 700;
|
|
129
|
+
color: var(--pa-detail-title);
|
|
130
|
+
margin-bottom: 0.6rem;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
dl {
|
|
134
|
+
display: grid;
|
|
135
|
+
grid-template-columns: 1fr auto;
|
|
136
|
+
gap: 0.35rem 1.6rem;
|
|
137
|
+
margin: 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
dt {
|
|
141
|
+
margin: 0;
|
|
142
|
+
color: var(--pa-detail-row-label);
|
|
143
|
+
font-weight: 400;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
dd {
|
|
147
|
+
margin: 0;
|
|
148
|
+
text-align: end;
|
|
149
|
+
font-weight: 600;
|
|
150
|
+
font-variant-numeric: tabular-nums;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Inline sentiment hints for dd content (e.g. <dd>+12% <span class="pos">…</span></dd>) */
|
|
154
|
+
.pos { color: var(--pa-positive); }
|
|
155
|
+
.neg { color: var(--pa-negative); }
|
|
156
|
+
.warn { color: var(--pa-warning); }
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* ----- Section heading strip used outside card chrome -------------------
|
|
160
|
+
The 7 showcases each render a "stress-test" section that places tiles
|
|
161
|
+
directly inside .pa-col-* page-grid cells (no card wrapper). The strip
|
|
162
|
+
above those layouts hosts a label or LIVE indicator at the row's end. */
|
|
163
|
+
.pa-kpi-sectionhead {
|
|
164
|
+
display: flex;
|
|
165
|
+
justify-content: flex-end;
|
|
166
|
+
align-items: center;
|
|
167
|
+
gap: 1.6rem;
|
|
168
|
+
margin-bottom: 1.2rem;
|
|
169
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/* ========================================
|
|
2
|
+
KPI · Bento layout
|
|
3
|
+
Magazine-style asymmetric tile sizing with sparklines as soft background
|
|
4
|
+
fills behind the values. 6 tiles arranged on a 6-col × 3-row grid
|
|
5
|
+
(hero left-half × 2 rows, two stacked right-half × 2 rows, three equal
|
|
6
|
+
tiles bottom row). Tile placement by source order via :nth-child.
|
|
7
|
+
======================================== */
|
|
8
|
+
@use '../variables' as *;
|
|
9
|
+
|
|
10
|
+
.pa-kpi-bento {
|
|
11
|
+
container-type: inline-size;
|
|
12
|
+
}
|
|
13
|
+
.pa-kpi-bento__body { padding: 1.6rem; }
|
|
14
|
+
|
|
15
|
+
/* ----- Bento grid ------------------------------------------------------- */
|
|
16
|
+
.pa-kpi-bento__grid {
|
|
17
|
+
display: grid;
|
|
18
|
+
grid-template-columns: repeat(6, 1fr);
|
|
19
|
+
grid-template-rows: 12rem 12rem 12rem;
|
|
20
|
+
grid-template-areas:
|
|
21
|
+
"hero hero hero a a a"
|
|
22
|
+
"hero hero hero b b b"
|
|
23
|
+
"c c d d e e";
|
|
24
|
+
gap: 1rem;
|
|
25
|
+
|
|
26
|
+
> :nth-child(1) { grid-area: hero; }
|
|
27
|
+
> :nth-child(2) { grid-area: a; }
|
|
28
|
+
> :nth-child(3) { grid-area: b; }
|
|
29
|
+
> :nth-child(4) { grid-area: c; }
|
|
30
|
+
> :nth-child(5) { grid-area: d; }
|
|
31
|
+
> :nth-child(6) { grid-area: e; }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Narrow card → stack everything single column. Hero modifier still
|
|
35
|
+
bumps the value font-size so it reads as the headline. */
|
|
36
|
+
@container (max-width: 700px) {
|
|
37
|
+
.pa-kpi-bento__grid {
|
|
38
|
+
grid-template-columns: 1fr;
|
|
39
|
+
grid-template-rows: auto;
|
|
40
|
+
grid-template-areas: none;
|
|
41
|
+
gap: 0.8rem;
|
|
42
|
+
|
|
43
|
+
> :nth-child(n) { grid-area: auto; }
|
|
44
|
+
}
|
|
45
|
+
.pa-kpi-bento-tile { min-height: 10rem; }
|
|
46
|
+
.pa-kpi-bento-tile--hero { min-height: 14rem; }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ----- Tile (per-KPI bento cell) ---------------------------------------- */
|
|
50
|
+
.pa-kpi-bento-tile {
|
|
51
|
+
/* Per-tile inline-size container so the value font-size scales with
|
|
52
|
+
*this* tile's width via cqi (not the outer card's width). The hero
|
|
53
|
+
and the smaller bottom tiles each scale to their own column. */
|
|
54
|
+
container-type: inline-size;
|
|
55
|
+
position: relative;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
padding: 1.3rem 1.5rem;
|
|
58
|
+
border: 1px solid var(--pa-border-color);
|
|
59
|
+
background: var(--pa-card-bg);
|
|
60
|
+
display: grid;
|
|
61
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
62
|
+
grid-template-rows: auto 1fr auto;
|
|
63
|
+
grid-template-areas:
|
|
64
|
+
"label delta"
|
|
65
|
+
". . "
|
|
66
|
+
"value value";
|
|
67
|
+
gap: 0.4rem 1rem;
|
|
68
|
+
|
|
69
|
+
/* Sparkline + delta sentiment cascade via currentColor. */
|
|
70
|
+
--pa-kpi-accent: var(--pa-positive);
|
|
71
|
+
|
|
72
|
+
&--positive { --pa-kpi-accent: var(--pa-positive); }
|
|
73
|
+
&--negative { --pa-kpi-accent: var(--pa-negative); }
|
|
74
|
+
&--neutral { --pa-kpi-accent: var(--pa-neutral); }
|
|
75
|
+
&--up-strong { --pa-kpi-accent: var(--pa-very-positive); }
|
|
76
|
+
&--down-strong { --pa-kpi-accent: var(--pa-very-negative); }
|
|
77
|
+
|
|
78
|
+
&--hero {
|
|
79
|
+
padding: 1.6rem 1.8rem;
|
|
80
|
+
|
|
81
|
+
.pa-kpi-bento-tile__num { font-size: clamp(3.6rem, 22cqi, 7rem); }
|
|
82
|
+
.pa-kpi-bento-tile__unit { font-size: clamp(1.6rem, 9cqi, 2.6rem); }
|
|
83
|
+
.pa-kpi-bento-tile__label,
|
|
84
|
+
.pa-kpi-bento-tile__delta { font-size: 1.4rem; }
|
|
85
|
+
.pa-kpi-bento-tile__chart { height: 70%; }
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* ----- Top row: label + delta, both layered over the chart -------------- */
|
|
90
|
+
.pa-kpi-bento-tile__label {
|
|
91
|
+
grid-area: label;
|
|
92
|
+
font-family: var(--base-font-family-mono);
|
|
93
|
+
font-size: 1.3rem;
|
|
94
|
+
font-weight: 700;
|
|
95
|
+
letter-spacing: 0.1em;
|
|
96
|
+
text-transform: uppercase;
|
|
97
|
+
color: color-mix(in srgb, var(--pa-text-color-1) 60%, transparent);
|
|
98
|
+
z-index: 1;
|
|
99
|
+
line-height: 1.2;
|
|
100
|
+
}
|
|
101
|
+
.pa-kpi-bento-tile__delta {
|
|
102
|
+
grid-area: delta;
|
|
103
|
+
font-family: var(--base-font-family-mono);
|
|
104
|
+
font-size: 1.3rem;
|
|
105
|
+
font-weight: 700;
|
|
106
|
+
color: var(--pa-kpi-accent);
|
|
107
|
+
z-index: 1;
|
|
108
|
+
align-self: start;
|
|
109
|
+
line-height: 1.2;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* ----- Value (bottom of grid, layered over chart) ----------------------- */
|
|
113
|
+
.pa-kpi-bento-tile__value {
|
|
114
|
+
grid-area: value;
|
|
115
|
+
align-self: end;
|
|
116
|
+
position: relative;
|
|
117
|
+
z-index: 1;
|
|
118
|
+
font-family: var(--base-font-family-mono);
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
align-items: baseline;
|
|
121
|
+
line-height: 1;
|
|
122
|
+
white-space: nowrap;
|
|
123
|
+
}
|
|
124
|
+
.pa-kpi-bento-tile__num {
|
|
125
|
+
font-size: clamp(2rem, 14cqi, 3.2rem);
|
|
126
|
+
font-weight: 700;
|
|
127
|
+
letter-spacing: -0.02em;
|
|
128
|
+
color: var(--pa-text-color-1);
|
|
129
|
+
}
|
|
130
|
+
.pa-kpi-bento-tile__unit {
|
|
131
|
+
font-size: clamp(1.2rem, 7cqi, 1.6rem);
|
|
132
|
+
font-weight: 500;
|
|
133
|
+
color: color-mix(in srgb, var(--pa-text-color-1) 50%, transparent);
|
|
134
|
+
margin: 0 0.3rem;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* ----- Sparkline background ---------------------------------------------
|
|
138
|
+
Absolutely positioned, fills the bottom 65% of the tile. The value sits
|
|
139
|
+
over it (z-index: 1 above). The line/area read through behind the
|
|
140
|
+
digits at lower opacity so the value remains the focal point. SVG is
|
|
141
|
+
nested in a fixed-height wrapper so taller tiles don't distort the line
|
|
142
|
+
shape (preserveAspectRatio="none" would otherwise stretch the Y axis). */
|
|
143
|
+
.pa-kpi-bento-tile__chart {
|
|
144
|
+
position: absolute;
|
|
145
|
+
left: 0;
|
|
146
|
+
right: 0;
|
|
147
|
+
bottom: 0;
|
|
148
|
+
height: 65%;
|
|
149
|
+
pointer-events: none;
|
|
150
|
+
color: var(--pa-kpi-accent);
|
|
151
|
+
z-index: 0;
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: flex-end;
|
|
154
|
+
|
|
155
|
+
svg {
|
|
156
|
+
display: block;
|
|
157
|
+
width: 100%;
|
|
158
|
+
height: 100%;
|
|
159
|
+
overflow: visible;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
polyline {
|
|
163
|
+
fill: none;
|
|
164
|
+
stroke: currentColor;
|
|
165
|
+
stroke-opacity: 0.55;
|
|
166
|
+
stroke-width: var(--pa-chart-trendline-stroke);
|
|
167
|
+
stroke-linecap: round;
|
|
168
|
+
stroke-linejoin: round;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
polygon {
|
|
172
|
+
fill: currentColor;
|
|
173
|
+
fill-opacity: 0.10;
|
|
174
|
+
stroke: none;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
.pa-kpi-bento-tile__chart-svg {
|
|
178
|
+
position: relative;
|
|
179
|
+
display: block;
|
|
180
|
+
width: 100%;
|
|
181
|
+
height: var(--pa-chart-trendline-height);
|
|
182
|
+
}
|