@klodd/ds 1.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/css/00-primitives.css +62 -0
  2. package/css/10-semantic.css +81 -20
  3. package/css/apps/ekonom.css +9 -0
  4. package/css/base/layout.css +45 -0
  5. package/css/components/auth.css +28 -0
  6. package/css/components/avatar.css +31 -0
  7. package/css/components/badge.css +2 -2
  8. package/css/components/banner.css +63 -0
  9. package/css/components/chip.css +257 -0
  10. package/css/components/collapsible.css +64 -0
  11. package/css/components/divider.css +25 -0
  12. package/css/components/dropdown.css +88 -0
  13. package/css/components/feedback.css +6 -0
  14. package/css/components/form.css +67 -0
  15. package/css/components/hbar.css +64 -0
  16. package/css/components/hero.css +85 -0
  17. package/css/components/hub-card.css +100 -0
  18. package/css/components/inline-edit.css +67 -0
  19. package/css/components/input.css +1 -1
  20. package/css/components/list-row.css +115 -0
  21. package/css/components/overlay.css +3 -0
  22. package/css/components/panel.css +95 -0
  23. package/css/components/progress.css +39 -0
  24. package/css/components/setting-row.css +186 -0
  25. package/css/components/split-bar.css +53 -0
  26. package/css/components/stat.css +55 -0
  27. package/css/components/swipe-stack.css +200 -0
  28. package/css/components/tab-bar.css +58 -0
  29. package/css/components/table.css +39 -0
  30. package/css/components/tooltip.css +50 -0
  31. package/css/components/upload-spinner.css +55 -0
  32. package/css/index.css +32 -0
  33. package/css/utilities.css +81 -0
  34. package/js/bar-styles.js +37 -0
  35. package/js/hero-roll.js +287 -0
  36. package/js/index.js +95 -0
  37. package/js/lucide-init.js +27 -0
  38. package/js/nav-optimistic.js +74 -0
  39. package/js/pull-to-refresh.js +162 -0
  40. package/js/pwa-register.js +132 -0
  41. package/js/sheet-drag.js +163 -0
  42. package/js/turbo-nav.js +353 -0
  43. package/package.json +4 -3
@@ -0,0 +1,95 @@
1
+ /* ================================================================
2
+ components/panel.css
3
+ Allmanna paneler. .panel ar bas. Modifiers: --info, --danger,
4
+ --attention. Slot-element: .panel__title, .panel__title-row,
5
+ .panel__step-row.
6
+
7
+ Skiljer sig fran .card sa: panel ar mer noga med padding och
8
+ margin-bottom (flode i lista). Card ar mer flexibel med slots
9
+ (.card-header, .card-body, .card-footer).
10
+ ================================================================ */
11
+ .panel {
12
+ background: var(--surface-raised);
13
+ border: 1px solid var(--border-subtle);
14
+ border-radius: var(--radius-20);
15
+ padding: var(--space-16) var(--space-18);
16
+ margin-bottom: var(--space-14);
17
+ }
18
+
19
+ .panel__title {
20
+ font-size: var(--fs-10);
21
+ font-weight: var(--fw-medium);
22
+ letter-spacing: var(--ls-tracker-xl, 0.12em);
23
+ text-transform: uppercase;
24
+ color: var(--text-muted);
25
+ margin: 0 0 var(--space-12);
26
+ }
27
+
28
+ .panel__title-row {
29
+ display: flex;
30
+ justify-content: space-between;
31
+ align-items: center;
32
+ gap: var(--space-10);
33
+ margin-bottom: var(--space-12);
34
+ }
35
+ .panel__title-row .panel__title { margin-bottom: 0; }
36
+
37
+ .panel__title-meta {
38
+ font-size: var(--fs-12);
39
+ color: var(--text-muted);
40
+ font-weight: var(--fw-medium);
41
+ font-variant-numeric: tabular-nums;
42
+ }
43
+
44
+ .panel__title-link {
45
+ font-size: var(--fs-12);
46
+ color: var(--accent-text);
47
+ font-weight: var(--fw-medium);
48
+ text-decoration: none;
49
+ }
50
+ @media (hover: hover) and (pointer: fine) {
51
+ .panel__title-link:hover { text-decoration: underline; }
52
+ }
53
+
54
+ .panel--info {
55
+ border-left: 3px solid var(--positive-border);
56
+ }
57
+
58
+ .panel--info-warning {
59
+ border-left: 3px solid var(--warning-border);
60
+ }
61
+
62
+ .panel--danger {
63
+ border: 1px solid var(--accent-danger-border);
64
+ background: var(--accent-danger-dim);
65
+ }
66
+
67
+ .panel--attention {
68
+ background: var(--warning-dim);
69
+ border: 1px solid var(--warning-border);
70
+ }
71
+ .panel--attention .panel__title {
72
+ color: var(--warning);
73
+ }
74
+
75
+ .panel__step-row {
76
+ display: flex;
77
+ align-items: center;
78
+ gap: var(--space-8);
79
+ margin-bottom: var(--space-8);
80
+ }
81
+
82
+ .panel__step-badge {
83
+ display: inline-flex;
84
+ align-items: center;
85
+ height: 20px;
86
+ padding: 0 var(--space-8);
87
+ background: var(--surface-active);
88
+ color: var(--accent-text);
89
+ font-size: var(--fs-11);
90
+ font-weight: var(--fw-medium);
91
+ letter-spacing: 0.04em;
92
+ text-transform: uppercase;
93
+ border-radius: var(--radius-full);
94
+ flex-shrink: 0;
95
+ }
@@ -0,0 +1,39 @@
1
+ /* ================================================================
2
+ components/progress.css
3
+ Linjar progress-indikator. Anvands for budget-burndown, upload-
4
+ status, multi-step-flows. Modifiers for status-fargning.
5
+
6
+ .progress ar wrappern (track), .progress-bar ar fyllnaden.
7
+ Sätt width via inline style eller data-attribut + JS (CSP-safe).
8
+
9
+ Brief-pattern fran Ekonom:
10
+ <div class="progress">
11
+ <div class="progress-bar progress-bar--warning"
12
+ data-bar-width="73%"></div>
13
+ </div>
14
+ bar-styles.js applicerar style.width fran data-bar-width.
15
+ ================================================================ */
16
+ .progress {
17
+ width: 100%;
18
+ height: var(--space-6);
19
+ background: var(--surface-raised);
20
+ border-radius: var(--radius-full);
21
+ overflow: hidden;
22
+ }
23
+
24
+ .progress-bar {
25
+ height: 100%;
26
+ background: var(--accent-9);
27
+ border-radius: var(--radius-full);
28
+ transition: width var(--dur-base) var(--ease-out);
29
+ }
30
+
31
+ .progress-bar--success { background: var(--bg-success); }
32
+ .progress-bar--warning { background: var(--bg-warning); }
33
+ .progress-bar--danger { background: var(--bg-danger); }
34
+
35
+ @media (prefers-reduced-motion: reduce) {
36
+ .progress-bar {
37
+ transition: none;
38
+ }
39
+ }
@@ -0,0 +1,186 @@
1
+ /* ================================================================
2
+ components/setting-row.css
3
+ Tap-to-edit-rad som triggar bottom-sheet. Vanster: label + sub.
4
+ Hoger: varde + chevron. Anvands i settings-vyer.
5
+
6
+ Plus iOS-stil .setting-toggle med native checkbox dolt.
7
+
8
+ .setting-list samlar flera setting-rows med subtle dividers.
9
+ ================================================================ */
10
+ .setting-list {
11
+ list-style: none;
12
+ margin: 0;
13
+ padding: 0;
14
+ display: flex;
15
+ flex-direction: column;
16
+ }
17
+ .setting-list > li { display: block; }
18
+ .setting-list > li + li {
19
+ border-top: 1px solid var(--border-subtle);
20
+ }
21
+
22
+ .setting-row {
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: space-between;
26
+ gap: var(--space-12);
27
+ width: 100%;
28
+ padding: var(--space-14) var(--space-16);
29
+ background: transparent;
30
+ border: 0;
31
+ border-radius: var(--radius-12);
32
+ color: inherit;
33
+ text-align: left;
34
+ cursor: pointer;
35
+ font-family: inherit;
36
+ -webkit-tap-highlight-color: transparent;
37
+ touch-action: manipulation;
38
+ transition: background var(--dur-fast) var(--ease-spring-snappy);
39
+ }
40
+
41
+ .setting-row + .setting-row {
42
+ border-top: 1px solid var(--border-subtle);
43
+ }
44
+
45
+ @media (hover: hover) and (pointer: fine) {
46
+ .setting-row:hover { background: var(--surface-hover); }
47
+ }
48
+
49
+ .setting-row:active {
50
+ background: var(--surface-active);
51
+ transform: scale(0.985);
52
+ transition:
53
+ transform 80ms var(--ease-spring-snappy),
54
+ background var(--dur-fast) var(--ease-spring-snappy);
55
+ }
56
+
57
+ .setting-row:focus-visible {
58
+ outline: 2px solid var(--border-focus);
59
+ outline-offset: -2px;
60
+ }
61
+
62
+ .setting-row__text {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: 2px;
66
+ min-width: 0;
67
+ flex: 1;
68
+ }
69
+
70
+ .setting-row__label {
71
+ font-size: var(--fs-15);
72
+ font-weight: var(--fw-medium);
73
+ color: var(--text-default);
74
+ line-height: var(--lh-snug);
75
+ }
76
+
77
+ .setting-row__sub {
78
+ font-size: var(--fs-12);
79
+ color: var(--text-muted);
80
+ line-height: var(--lh-snug);
81
+ }
82
+
83
+ .setting-row__value {
84
+ display: flex;
85
+ align-items: center;
86
+ gap: var(--space-6);
87
+ flex-shrink: 0;
88
+ }
89
+
90
+ .setting-row__amount {
91
+ font-size: var(--fs-15);
92
+ font-weight: var(--fw-medium);
93
+ color: var(--text-subtle);
94
+ font-variant-numeric: tabular-nums;
95
+ }
96
+
97
+ .setting-row__chevron {
98
+ color: var(--text-disabled);
99
+ flex-shrink: 0;
100
+ }
101
+
102
+ .setting-row__avatar {
103
+ margin-right: var(--space-12);
104
+ flex-shrink: 0;
105
+ }
106
+
107
+ .setting-row--static {
108
+ cursor: default;
109
+ }
110
+ .setting-row--static:active {
111
+ background: transparent;
112
+ transform: none;
113
+ }
114
+ @media (hover: hover) and (pointer: fine) {
115
+ .setting-row--static:hover { background: transparent; }
116
+ }
117
+
118
+ .setting-row--danger .setting-row__label {
119
+ color: var(--accent-danger);
120
+ }
121
+
122
+ .setting-row__pill {
123
+ display: inline-flex;
124
+ align-items: center;
125
+ height: 28px;
126
+ padding: 0 var(--space-12);
127
+ background: var(--accent-9);
128
+ color: var(--text-on-accent);
129
+ font-size: var(--fs-12);
130
+ font-weight: var(--fw-medium);
131
+ border-radius: var(--radius-full);
132
+ white-space: nowrap;
133
+ }
134
+
135
+
136
+ /* ================================================================
137
+ ==== TOGGLE (iOS-stil)
138
+ Native checkbox dolt visuellt men a11y-tillganglig.
139
+ ================================================================ */
140
+ .setting-toggle {
141
+ position: relative;
142
+ display: inline-block;
143
+ width: 44px;
144
+ height: 26px;
145
+ flex-shrink: 0;
146
+ }
147
+ .setting-toggle input {
148
+ position: absolute;
149
+ inset: 0;
150
+ width: 100%;
151
+ height: 100%;
152
+ margin: 0;
153
+ opacity: 0;
154
+ cursor: pointer;
155
+ z-index: 1;
156
+ }
157
+ .setting-toggle__track {
158
+ display: block;
159
+ width: 100%;
160
+ height: 100%;
161
+ background: var(--border-strong);
162
+ border-radius: var(--radius-full);
163
+ transition: background var(--dur-medium) var(--ease-spring-snappy);
164
+ position: relative;
165
+ }
166
+ .setting-toggle__thumb {
167
+ position: absolute;
168
+ top: 2px;
169
+ left: 2px;
170
+ width: 22px;
171
+ height: 22px;
172
+ background: var(--surface-page);
173
+ border-radius: 50%;
174
+ transition: transform var(--dur-medium) var(--ease-spring-snappy);
175
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
176
+ }
177
+ .setting-toggle input:checked + .setting-toggle__track {
178
+ background: var(--accent-9);
179
+ }
180
+ .setting-toggle input:checked + .setting-toggle__track .setting-toggle__thumb {
181
+ transform: translateX(18px);
182
+ }
183
+ .setting-toggle input:focus-visible + .setting-toggle__track {
184
+ outline: 2px solid var(--border-focus);
185
+ outline-offset: 2px;
186
+ }
@@ -0,0 +1,53 @@
1
+ /* ================================================================
2
+ components/split-bar.css
3
+ Visuell proportionsbar dar tva eller flera segment delar baren.
4
+ Anvands for cost-split (vem betalar), debt-vs-equity, time-allocation.
5
+
6
+ Modell: .split-bar har N stycken .split-bar__segment som tillsammans
7
+ fyller 100%. Brett valbart segment satts genom data-bar-width-pattern
8
+ eller manuella width-classes.
9
+ ================================================================ */
10
+ .split-bar {
11
+ display: flex;
12
+ height: 8px;
13
+ border-radius: var(--radius-full);
14
+ overflow: hidden;
15
+ background: var(--surface-active);
16
+ margin: var(--space-8) 0 var(--space-12);
17
+ }
18
+
19
+ .split-bar__segment {
20
+ height: 100%;
21
+ transition: width var(--dur-medium) var(--ease-spring-snappy);
22
+ }
23
+
24
+ .split-bar__segment--primary { background: var(--accent-9); }
25
+ .split-bar__segment--secondary { background: var(--text-disabled); flex: 1; }
26
+ .split-bar__segment--positive { background: var(--positive); }
27
+ .split-bar__segment--negative { background: var(--negative); }
28
+ .split-bar__segment--warning { background: var(--warning); }
29
+
30
+ .split-bar__label {
31
+ font-size: var(--fs-13);
32
+ color: var(--text-subtle);
33
+ margin: 0 0 var(--space-6);
34
+ line-height: var(--lh-snug);
35
+ }
36
+
37
+ .split-bar__label strong {
38
+ color: var(--text-default);
39
+ font-weight: var(--fw-medium);
40
+ }
41
+
42
+ .split-bar__labels {
43
+ display: flex;
44
+ justify-content: space-between;
45
+ gap: var(--space-10);
46
+ margin-top: var(--space-6);
47
+ font-size: var(--fs-12);
48
+ color: var(--text-subtle);
49
+ }
50
+
51
+ @media (prefers-reduced-motion: reduce) {
52
+ .split-bar__segment { transition: none; }
53
+ }
@@ -0,0 +1,55 @@
1
+ /* ================================================================
2
+ components/stat.css
3
+ Stat-card och metric-card - sma kort med stor siffra + label.
4
+ .stat-grid lagger ut flera kort i grid (2 kol mobil, 4 desktop).
5
+
6
+ .stat-card ar nyare BEM-versionen. .metric-card behalls for
7
+ bakatkompat med befintliga vyer som anvander metric-grid.
8
+ ================================================================ */
9
+ .stat-grid {
10
+ display: grid;
11
+ grid-template-columns: repeat(2, 1fr);
12
+ gap: var(--space-12);
13
+ margin-bottom: var(--space-14);
14
+ }
15
+ .stat-grid--single { grid-template-columns: 1fr; }
16
+
17
+ .stat-card {
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: flex-start;
21
+ gap: var(--space-4);
22
+ padding: var(--space-16);
23
+ background: var(--surface-default);
24
+ border-radius: var(--radius-12);
25
+ }
26
+
27
+ .stat-card__value {
28
+ font-size: var(--fs-22);
29
+ font-weight: var(--fw-medium);
30
+ color: var(--text-default);
31
+ font-variant-numeric: tabular-nums;
32
+ line-height: 1;
33
+ }
34
+
35
+ .stat-card__label {
36
+ font-size: var(--fs-12);
37
+ color: var(--text-muted);
38
+ }
39
+
40
+ .stat-card__value--positive { color: var(--positive); }
41
+ .stat-card__value--negative { color: var(--negative); }
42
+ .stat-card__value--accent { color: var(--accent-text); }
43
+ .stat-card__value--warning { color: var(--warning); }
44
+
45
+ .stat-card__unit {
46
+ font-size: var(--fs-11);
47
+ color: var(--text-muted);
48
+ margin-top: var(--space-2);
49
+ }
50
+
51
+ .stat-card__sub {
52
+ font-size: var(--fs-11);
53
+ color: var(--text-subtle);
54
+ margin-top: var(--space-4);
55
+ }
@@ -0,0 +1,200 @@
1
+ /* ================================================================
2
+ components/swipe-stack.css
3
+ Tinder-stil swipe-card-stack med drag-physics. Anvands for
4
+ triage-flow, decision-cards, tutorial-stacks.
5
+
6
+ Klassnamn ar generiska (.swipe-*) - inte vy-specifika (.triage-*).
7
+ App-repots vyer applicerar dessa pa sina specifika data-cards.
8
+
9
+ Element:
10
+ - .swipe-stack: container med relative position
11
+ - .swipe-card: individuellt kort (absolute positionerat)
12
+ - .swipe-card__header: ovre header-omrade
13
+ - .swipe-card__body: huvud-innehall
14
+ - .swipe-card__footer: nedre actions-rad
15
+ - .swipe-card__back: nasta kort i stacken (visuellt bakom)
16
+ - .swipe-decision-overlay: overlay med "spara"/"avfard" indikator
17
+ - .swipe-actions: knapp-rad under stacken
18
+ - .swipe-meta: kort-meta-info
19
+ - .swipe-progress: progress-indikator
20
+ - .swipe-empty: tomt-state
21
+ ================================================================ */
22
+ .swipe-stack {
23
+ position: relative;
24
+ width: 100%;
25
+ max-width: 480px;
26
+ margin: 0 auto;
27
+ height: 480px;
28
+ isolation: isolate;
29
+ }
30
+
31
+ .swipe-card {
32
+ position: absolute;
33
+ inset: 0;
34
+ display: flex;
35
+ flex-direction: column;
36
+ background: var(--surface-raised);
37
+ border: 1px solid var(--border-subtle);
38
+ border-radius: var(--radius-20);
39
+ padding: var(--space-20);
40
+ overflow: hidden;
41
+ cursor: grab;
42
+ user-select: none;
43
+ -webkit-user-select: none;
44
+ touch-action: pan-y;
45
+ transition: transform var(--dur-medium) var(--ease-spring-snappy);
46
+ }
47
+
48
+ .swipe-card:active { cursor: grabbing; }
49
+
50
+ .swipe-card--back {
51
+ transform: scale(0.96);
52
+ opacity: 0.85;
53
+ z-index: 0;
54
+ pointer-events: none;
55
+ }
56
+
57
+ .swipe-card__header {
58
+ display: flex;
59
+ align-items: center;
60
+ justify-content: space-between;
61
+ gap: var(--space-12);
62
+ margin-bottom: var(--space-12);
63
+ }
64
+
65
+ .swipe-card__title {
66
+ font-size: var(--fs-17);
67
+ font-weight: var(--fw-medium);
68
+ color: var(--text-default);
69
+ letter-spacing: var(--ls-tight);
70
+ margin: 0 0 var(--space-6);
71
+ }
72
+
73
+ .swipe-card__body {
74
+ flex: 1;
75
+ overflow-y: auto;
76
+ -webkit-overflow-scrolling: touch;
77
+ font-size: var(--fs-14);
78
+ color: var(--text-subtle);
79
+ line-height: var(--lh-base);
80
+ }
81
+
82
+ .swipe-card__footer {
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: space-between;
86
+ gap: var(--space-12);
87
+ margin-top: var(--space-16);
88
+ padding-top: var(--space-12);
89
+ border-top: 1px solid var(--border-subtle);
90
+ font-size: var(--fs-12);
91
+ color: var(--text-muted);
92
+ }
93
+
94
+ .swipe-decision-overlay {
95
+ position: absolute;
96
+ top: var(--space-20);
97
+ padding: var(--space-8) var(--space-16);
98
+ font-size: var(--fs-15);
99
+ font-weight: var(--fw-medium);
100
+ letter-spacing: 0.05em;
101
+ text-transform: uppercase;
102
+ border-radius: var(--radius-10);
103
+ border: 2px solid currentColor;
104
+ opacity: 0;
105
+ transition: opacity var(--dur-fast) var(--ease-default);
106
+ pointer-events: none;
107
+ }
108
+
109
+ .swipe-decision-overlay--save {
110
+ right: var(--space-20);
111
+ color: var(--positive);
112
+ transform: rotate(8deg);
113
+ }
114
+
115
+ .swipe-decision-overlay--dismiss {
116
+ left: var(--space-20);
117
+ color: var(--negative);
118
+ transform: rotate(-8deg);
119
+ }
120
+
121
+ .swipe-decision-overlay--visible { opacity: 1; }
122
+
123
+ .swipe-actions {
124
+ display: flex;
125
+ justify-content: center;
126
+ gap: var(--space-20);
127
+ margin-top: var(--space-20);
128
+ }
129
+
130
+ .swipe-action-btn {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ justify-content: center;
134
+ width: 56px;
135
+ height: 56px;
136
+ background: var(--surface-raised);
137
+ border: 1px solid var(--border-default);
138
+ border-radius: var(--radius-full);
139
+ color: var(--text-default);
140
+ cursor: pointer;
141
+ -webkit-tap-highlight-color: transparent;
142
+ touch-action: manipulation;
143
+ transition:
144
+ background var(--dur-fast) var(--ease-spring-snappy),
145
+ transform var(--press-out-duration) var(--press-out-easing);
146
+ }
147
+
148
+ @media (hover: hover) and (pointer: fine) {
149
+ .swipe-action-btn:hover { background: var(--surface-hover); }
150
+ }
151
+
152
+ .swipe-action-btn:active {
153
+ transform: scale(0.92);
154
+ transition: transform var(--press-in-duration) var(--press-in-easing);
155
+ }
156
+
157
+ .swipe-action-btn--save { color: var(--positive); }
158
+ .swipe-action-btn--dismiss { color: var(--negative); }
159
+
160
+ .swipe-meta {
161
+ display: flex;
162
+ align-items: center;
163
+ gap: var(--space-8);
164
+ font-size: var(--fs-12);
165
+ color: var(--text-muted);
166
+ }
167
+
168
+ .swipe-meta-sep {
169
+ display: inline-block;
170
+ width: 3px;
171
+ height: 3px;
172
+ background: var(--text-disabled);
173
+ border-radius: var(--radius-full);
174
+ }
175
+
176
+ .swipe-progress {
177
+ text-align: center;
178
+ font-size: var(--fs-12);
179
+ color: var(--text-muted);
180
+ margin: 0 0 var(--space-12);
181
+ font-variant-numeric: tabular-nums;
182
+ }
183
+
184
+ .swipe-empty {
185
+ text-align: center;
186
+ padding: var(--space-40) var(--space-20);
187
+ color: var(--text-subtle);
188
+ }
189
+
190
+ .swipe-hint {
191
+ text-align: center;
192
+ font-size: var(--fs-12);
193
+ color: var(--text-disabled);
194
+ margin-top: var(--space-12);
195
+ }
196
+
197
+ @media (prefers-reduced-motion: reduce) {
198
+ .swipe-card { transition: none; }
199
+ .swipe-decision-overlay { transition: none; }
200
+ }
@@ -0,0 +1,58 @@
1
+ /* ================================================================
2
+ components/tab-bar.css
3
+ Inline tab-grupp for format-val (CSV/Avi, dashboard-vyer m.fl.).
4
+ Inte sticky - placeras inline i template.
5
+
6
+ Existerande nav.css har en kompaktare .tab-bar-variant.
7
+ Denna fil definierar OM och ersatter den - lasta en gang.
8
+ ================================================================ */
9
+ .tab-bar {
10
+ display: flex;
11
+ gap: var(--space-4);
12
+ margin: 0 0 var(--space-16);
13
+ padding: var(--space-4);
14
+ background: var(--surface-default);
15
+ border-radius: var(--radius-12);
16
+ }
17
+
18
+ .tab-bar__item {
19
+ flex: 1;
20
+ display: inline-flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ min-height: 44px;
24
+ padding: 0 var(--space-12);
25
+ background: transparent;
26
+ border: 0;
27
+ border-radius: var(--radius-8);
28
+ color: var(--text-subtle);
29
+ font-family: inherit;
30
+ font-size: var(--fs-14);
31
+ font-weight: var(--fw-medium);
32
+ text-decoration: none;
33
+ cursor: pointer;
34
+ -webkit-tap-highlight-color: transparent;
35
+ touch-action: manipulation;
36
+ transition:
37
+ background var(--dur-fast) var(--ease-spring-snappy),
38
+ color var(--dur-fast) var(--ease-spring-snappy);
39
+ }
40
+
41
+ .tab-bar__item.is-active {
42
+ background: var(--surface-raised);
43
+ color: var(--text-default);
44
+ font-weight: var(--fw-medium);
45
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
46
+ }
47
+
48
+ @media (hover: hover) and (pointer: fine) {
49
+ .tab-bar__item:not(.is-active):hover {
50
+ color: var(--text-default);
51
+ background: var(--surface-hover);
52
+ }
53
+ }
54
+
55
+ .tab-bar__item:active:not(.is-active) {
56
+ transform: scale(0.985);
57
+ transition: transform 80ms var(--ease-spring-snappy);
58
+ }