@klodd/ds 1.2.0 → 3.0.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.
@@ -0,0 +1,45 @@
1
+ /* ================================================================
2
+ base/layout.css
3
+ App-niva-layout: main-content, page-header, page-title.
4
+ Anvands som default-skelett pa varje vy.
5
+ ================================================================ */
6
+ .main-content {
7
+ max-width: var(--content-max-default, 600px);
8
+ margin: 0 auto;
9
+ padding: calc(var(--safe-top) + var(--space-16)) var(--space-14) var(--bottom-nav-clearance);
10
+ position: relative;
11
+ min-height: calc(100dvh - var(--bottom-nav-clearance));
12
+ }
13
+
14
+ .main-content--narrow { max-width: var(--content-max-narrow, 480px); }
15
+ .main-content--wide { max-width: var(--content-max-wide, 800px); }
16
+
17
+ .page-header {
18
+ display: flex;
19
+ align-items: center;
20
+ justify-content: space-between;
21
+ gap: var(--space-12);
22
+ margin-bottom: var(--space-16);
23
+ flex-wrap: wrap;
24
+ }
25
+
26
+ .page-title {
27
+ font-size: var(--fs-22);
28
+ font-weight: var(--fw-medium);
29
+ letter-spacing: var(--ls-tight);
30
+ color: var(--text-default);
31
+ margin: 0;
32
+ }
33
+
34
+ .page-subtitle {
35
+ font-size: var(--fs-13);
36
+ color: var(--text-subtle);
37
+ margin-top: var(--space-2);
38
+ }
39
+
40
+ .split-grid {
41
+ display: grid;
42
+ grid-template-columns: 1fr;
43
+ gap: var(--space-12);
44
+ margin-bottom: var(--space-14);
45
+ }
@@ -0,0 +1,28 @@
1
+ /* ================================================================
2
+ components/auth.css
3
+ Centrerad layout for inloggning + onboarding.
4
+ ================================================================ */
5
+ .auth-container {
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: center;
9
+ justify-content: center;
10
+ min-height: 70vh;
11
+ gap: var(--space-8);
12
+ padding: var(--space-20);
13
+ text-align: center;
14
+ }
15
+
16
+ .auth-container__title {
17
+ font-size: var(--fs-22);
18
+ font-weight: var(--fw-medium);
19
+ letter-spacing: var(--ls-tight);
20
+ color: var(--text-default);
21
+ margin: 0;
22
+ }
23
+
24
+ .auth-container__subtitle {
25
+ color: var(--text-subtle);
26
+ margin: 0 0 var(--space-24);
27
+ font-size: var(--fs-13);
28
+ }
@@ -0,0 +1,31 @@
1
+ /* ================================================================
2
+ components/avatar.css
3
+ Cirkular initial-avatar. Modifier --lg pa profil-vyer.
4
+ ================================================================ */
5
+ .avatar {
6
+ width: 36px;
7
+ height: 36px;
8
+ border-radius: var(--radius-full);
9
+ background: linear-gradient(135deg, var(--accent-9) 0%, var(--accent-10) 100%);
10
+ display: inline-flex;
11
+ align-items: center;
12
+ justify-content: center;
13
+ flex-shrink: 0;
14
+ color: var(--text-on-accent);
15
+ font-size: var(--fs-15);
16
+ font-weight: var(--fw-medium);
17
+ text-transform: uppercase;
18
+ line-height: var(--lh-tight);
19
+ }
20
+
21
+ .avatar--sm {
22
+ width: 28px;
23
+ height: 28px;
24
+ font-size: var(--fs-12);
25
+ }
26
+
27
+ .avatar--lg {
28
+ width: 56px;
29
+ height: 56px;
30
+ font-size: var(--fs-24);
31
+ }
@@ -0,0 +1,63 @@
1
+ /* ================================================================
2
+ components/banner.css
3
+ .banner ar bred informations-rad med titel + sub + content.
4
+ Modifiers: --hero, --accent, --positive, --negative, --warning.
5
+ BEM: .banner__title, .banner__sub, .banner__content.
6
+ ================================================================ */
7
+ .banner {
8
+ display: flex;
9
+ align-items: center;
10
+ justify-content: space-between;
11
+ gap: var(--space-14);
12
+ padding: var(--space-14) var(--space-16);
13
+ border-radius: var(--radius-16);
14
+ margin-bottom: var(--space-14);
15
+ background: var(--surface-raised);
16
+ border: 1px solid var(--border-subtle);
17
+ }
18
+
19
+ .banner__content {
20
+ display: flex;
21
+ flex-direction: column;
22
+ gap: var(--space-2);
23
+ min-width: 0;
24
+ }
25
+
26
+ .banner__title {
27
+ font-size: var(--fs-14);
28
+ font-weight: var(--fw-medium);
29
+ color: var(--text-default);
30
+ margin: 0;
31
+ }
32
+
33
+ .banner__sub {
34
+ font-size: var(--fs-12);
35
+ color: var(--text-subtle);
36
+ }
37
+
38
+ .banner--accent {
39
+ background: var(--accent-a3);
40
+ border-color: var(--accent-a6);
41
+ }
42
+
43
+ .banner--positive {
44
+ background: var(--positive-dim);
45
+ border-color: var(--positive-border);
46
+ }
47
+
48
+ .banner--negative {
49
+ background: var(--negative-dim);
50
+ border-color: var(--negative-border);
51
+ }
52
+
53
+ .banner--warning {
54
+ background: var(--warning-dim);
55
+ border-color: var(--warning-border);
56
+ border-left-width: 3px;
57
+ }
58
+
59
+ .banner--hero {
60
+ flex-direction: column;
61
+ align-items: flex-start;
62
+ padding: var(--space-20);
63
+ }
@@ -0,0 +1,257 @@
1
+ /* ================================================================
2
+ components/chip.css
3
+ Sma status-pills. .chip ar bas. Modifiers: --accent, --positive,
4
+ --negative, --warning, --faint.
5
+
6
+ Plus relaterade pill-mont:
7
+ - .brand-pill: liten pill med projekt-namn
8
+ - .month-pill: navigations-pill for manads-byte
9
+ - .install-chip: PWA install-prompt floating-pill
10
+ - .score-pill: ratings-pill (variants --strong/--medium/--low)
11
+
12
+ .chip-list ar wrapper for flera chips i rad (form-edit-flode).
13
+ ================================================================ */
14
+ .chip {
15
+ display: inline-flex;
16
+ align-items: center;
17
+ gap: var(--space-6);
18
+ font-size: var(--fs-11);
19
+ font-weight: var(--fw-medium);
20
+ padding: var(--space-4) var(--space-10);
21
+ border-radius: var(--radius-full);
22
+ background: var(--surface-default);
23
+ color: var(--text-subtle);
24
+ border: 1px solid var(--border-subtle);
25
+ white-space: nowrap;
26
+ }
27
+
28
+ .chip::before {
29
+ content: '';
30
+ width: 6px;
31
+ height: 6px;
32
+ border-radius: var(--radius-full);
33
+ background: currentColor;
34
+ display: inline-block;
35
+ opacity: 0.75;
36
+ }
37
+
38
+ .chip--accent { color: var(--accent-text); background: var(--accent-a3); border-color: var(--accent-a6); }
39
+ .chip--positive { color: var(--positive); background: var(--positive-dim); border-color: var(--positive-border); }
40
+ .chip--negative { color: var(--negative); background: var(--negative-dim); border-color: var(--negative-border); }
41
+ .chip--warning { color: var(--warning); background: var(--warning-dim); border-color: var(--warning-border); }
42
+ .chip--faint { color: var(--text-muted); background: transparent; border-color: var(--border-subtle); }
43
+
44
+ .chip-list {
45
+ display: flex;
46
+ flex-wrap: wrap;
47
+ gap: var(--space-8);
48
+ margin: 0;
49
+ padding: 0;
50
+ list-style: none;
51
+ }
52
+
53
+ .chip-list__item {
54
+ display: inline-flex;
55
+ align-items: center;
56
+ gap: var(--space-6);
57
+ height: 32px;
58
+ padding: 0 var(--space-12);
59
+ background: var(--surface-default);
60
+ border: 1px solid var(--border-subtle);
61
+ border-radius: var(--radius-full);
62
+ color: var(--text-default);
63
+ font-size: var(--fs-13);
64
+ font-family: inherit;
65
+ white-space: nowrap;
66
+ }
67
+
68
+ .chip-list__delete {
69
+ display: inline-flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ width: 18px;
73
+ height: 18px;
74
+ padding: 0;
75
+ background: transparent;
76
+ border: 0;
77
+ color: var(--text-muted);
78
+ cursor: pointer;
79
+ border-radius: 50%;
80
+ transition: background var(--dur-fast) var(--ease-default);
81
+ }
82
+
83
+ @media (hover: hover) and (pointer: fine) {
84
+ .chip-list__delete:hover {
85
+ background: color-mix(in oklch, var(--accent-danger) 15%, transparent);
86
+ color: var(--accent-danger);
87
+ }
88
+ }
89
+
90
+ .chip-list__add {
91
+ background: transparent;
92
+ border-style: dashed;
93
+ color: var(--text-subtle);
94
+ cursor: pointer;
95
+ font-weight: var(--fw-medium);
96
+ -webkit-tap-highlight-color: transparent;
97
+ touch-action: manipulation;
98
+ transition: background var(--dur-fast) var(--ease-default);
99
+ }
100
+
101
+ @media (hover: hover) and (pointer: fine) {
102
+ .chip-list__add:hover {
103
+ background: var(--surface-hover);
104
+ color: var(--text-default);
105
+ border-color: var(--text-muted);
106
+ }
107
+ }
108
+
109
+
110
+ /* ================================================================
111
+ ==== BRAND-PILL
112
+ Liten pill med projekt-namn i topbar.
113
+ ================================================================ */
114
+ .brand-pill {
115
+ display: inline-flex;
116
+ align-items: center;
117
+ padding: var(--space-4) var(--space-12);
118
+ background: var(--surface-default);
119
+ border: 1px solid var(--border-subtle);
120
+ border-radius: var(--radius-full);
121
+ font-size: var(--fs-13);
122
+ font-weight: var(--fw-medium);
123
+ letter-spacing: var(--ls-snug);
124
+ color: var(--text-default);
125
+ }
126
+
127
+
128
+ /* ================================================================
129
+ ==== MONTH-PILL
130
+ Navigations-pill med manadsbyte (anvands i topbar pa Ekonom).
131
+ ================================================================ */
132
+ .month-pill {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ gap: var(--space-6);
136
+ height: 28px;
137
+ padding: 0 var(--space-12);
138
+ background: var(--surface-default);
139
+ border: 1px solid var(--border-subtle);
140
+ border-radius: var(--radius-full);
141
+ font-size: var(--fs-12);
142
+ font-weight: var(--fw-medium);
143
+ color: var(--text-default);
144
+ cursor: pointer;
145
+ text-decoration: none;
146
+ white-space: nowrap;
147
+ }
148
+
149
+
150
+ /* ================================================================
151
+ ==== SCORE-PILL
152
+ Tabular-nums for sifferjustering. Modifiers: --strong/--medium/--low.
153
+ ================================================================ */
154
+ .score-pill {
155
+ flex-shrink: 0;
156
+ display: inline-flex;
157
+ align-items: center;
158
+ justify-content: center;
159
+ font-size: var(--fs-11);
160
+ font-weight: var(--fw-medium);
161
+ font-variant-numeric: tabular-nums;
162
+ letter-spacing: var(--ls-wide, 0.01em);
163
+ padding: var(--space-2) var(--space-8);
164
+ border-radius: var(--radius-full);
165
+ border: 1px solid transparent;
166
+ white-space: nowrap;
167
+ line-height: 1.4;
168
+ }
169
+
170
+ .score-pill--strong {
171
+ color: var(--positive);
172
+ background: var(--positive-dim);
173
+ border-color: var(--positive-border);
174
+ }
175
+
176
+ .score-pill--medium {
177
+ color: var(--warning);
178
+ background: var(--warning-dim);
179
+ border-color: var(--warning-border);
180
+ }
181
+
182
+ .score-pill--low {
183
+ color: var(--text-muted);
184
+ background: var(--surface-default);
185
+ border-color: var(--border-subtle);
186
+ }
187
+
188
+
189
+ /* ================================================================
190
+ ==== INSTALL-CHIP
191
+ PWA install-prompt som flyter ovan bottom-nav.
192
+ ================================================================ */
193
+ .install-chip {
194
+ position: fixed;
195
+ bottom: calc(84px + var(--safe-bottom));
196
+ left: var(--space-12);
197
+ right: var(--space-12);
198
+ max-width: 480px;
199
+ margin: 0 auto;
200
+ background: var(--surface-raised);
201
+ border: 1px solid var(--border-subtle);
202
+ border-radius: var(--radius-full);
203
+ padding: var(--space-10) var(--space-10) var(--space-10) var(--space-18);
204
+ display: flex;
205
+ align-items: center;
206
+ gap: var(--space-10);
207
+ font-size: var(--fs-13);
208
+ color: var(--text-default);
209
+ z-index: var(--z-overlay, 60);
210
+ animation: install-chip-up 0.28s var(--ease-out);
211
+ box-shadow: var(--shadow-float);
212
+ }
213
+
214
+ .install-chip__text { flex: 1; min-width: 0; }
215
+
216
+ .install-chip__install {
217
+ background: var(--accent-9);
218
+ color: var(--text-on-accent);
219
+ border: none;
220
+ padding: var(--space-8) var(--space-14);
221
+ border-radius: var(--radius-full);
222
+ font-size: var(--fs-12);
223
+ font-weight: var(--fw-medium);
224
+ font-family: inherit;
225
+ cursor: pointer;
226
+ white-space: nowrap;
227
+ transition: background var(--dur-fast) var(--ease-default);
228
+ }
229
+
230
+ @media (hover: hover) and (pointer: fine) {
231
+ .install-chip__install:hover { background: var(--accent-10); }
232
+ }
233
+
234
+ .install-chip__dismiss {
235
+ background: transparent;
236
+ border: none;
237
+ color: var(--text-subtle);
238
+ font-size: var(--fs-18);
239
+ line-height: 1;
240
+ padding: var(--space-6) var(--space-10);
241
+ cursor: pointer;
242
+ min-width: 36px;
243
+ transition: color var(--dur-fast) var(--ease-default);
244
+ }
245
+
246
+ @media (hover: hover) and (pointer: fine) {
247
+ .install-chip__dismiss:hover { color: var(--text-default); }
248
+ }
249
+
250
+ @keyframes install-chip-up {
251
+ from { transform: translateY(calc(100% + 100px)); opacity: 0; }
252
+ to { transform: translateY(0); opacity: 1; }
253
+ }
254
+
255
+ @media (prefers-reduced-motion: reduce) {
256
+ .install-chip { animation: none; }
257
+ }
@@ -0,0 +1,64 @@
1
+ /* ================================================================
2
+ components/collapsible.css
3
+ Panel som expanderar pa klick. Anvands for budget-sektioner,
4
+ kategori-grupper, FAQ-rader.
5
+
6
+ Element: .collapsible-card (root) som ar bas.
7
+ - .collapsible__header klickbar header (button-element)
8
+ - .collapsible__body expanderat innehall (hidden default)
9
+ - .collapsible__chev chevron som roterar 180deg
10
+
11
+ State drivs via [data-expanded] attribut pa root - JS togglar.
12
+ ================================================================ */
13
+ .collapsible-card {
14
+ background: var(--surface-raised);
15
+ border: 1px solid var(--border-subtle);
16
+ border-radius: var(--radius-20);
17
+ margin-bottom: var(--space-14);
18
+ padding: 0;
19
+ }
20
+
21
+ .collapsible__header {
22
+ display: flex;
23
+ align-items: flex-start;
24
+ justify-content: space-between;
25
+ gap: var(--space-12);
26
+ width: 100%;
27
+ padding: var(--space-16) var(--space-18);
28
+ background: transparent;
29
+ border: 0;
30
+ color: inherit;
31
+ text-align: left;
32
+ cursor: pointer;
33
+ font: inherit;
34
+ border-radius: inherit;
35
+ }
36
+
37
+ .collapsible__header:focus-visible {
38
+ outline: 2px solid var(--border-focus);
39
+ outline-offset: -2px;
40
+ }
41
+
42
+ .collapsible__header-text {
43
+ flex: 1;
44
+ min-width: 0;
45
+ }
46
+
47
+ .collapsible__chev {
48
+ flex-shrink: 0;
49
+ margin-top: var(--space-4);
50
+ color: var(--text-muted);
51
+ transition: transform var(--dur-medium) var(--ease-default);
52
+ }
53
+
54
+ .collapsible-card[data-expanded] .collapsible__chev {
55
+ transform: rotate(180deg);
56
+ }
57
+
58
+ .collapsible__body {
59
+ padding: 0 var(--space-18) var(--space-16);
60
+ }
61
+
62
+ @media (prefers-reduced-motion: reduce) {
63
+ .collapsible__chev { transition: none; }
64
+ }
@@ -0,0 +1,67 @@
1
+ /* ================================================================
2
+ components/form.css
3
+ Form-skelett. .form-section, .form-group, .form-row.
4
+
5
+ Skiljer sig fran input.css (input-elementen). form.css ar
6
+ wrapper-strukturen som gor formularet komplett.
7
+ ================================================================ */
8
+ .form-card {
9
+ background: var(--surface-raised);
10
+ border: 1px solid var(--border-subtle);
11
+ border-radius: var(--radius-20);
12
+ padding: var(--space-20);
13
+ max-width: 480px;
14
+ margin-bottom: var(--space-14);
15
+ }
16
+
17
+ .form-section {
18
+ margin-bottom: var(--space-20);
19
+ }
20
+
21
+ .form-section__title {
22
+ font-size: var(--fs-10);
23
+ font-weight: var(--fw-medium);
24
+ letter-spacing: 0.12em;
25
+ text-transform: uppercase;
26
+ color: var(--text-muted);
27
+ margin: 0 0 var(--space-12);
28
+ padding-bottom: var(--space-8);
29
+ border-bottom: 1px solid var(--border-subtle);
30
+ }
31
+
32
+ .form-group {
33
+ margin-bottom: var(--space-14);
34
+ }
35
+
36
+ .form-group__label {
37
+ display: block;
38
+ font-size: var(--fs-11);
39
+ color: var(--text-subtle);
40
+ margin-bottom: var(--space-6);
41
+ letter-spacing: 0.01em;
42
+ }
43
+
44
+ .form-hint {
45
+ font-size: var(--fs-11);
46
+ color: var(--text-muted);
47
+ margin-top: var(--space-6);
48
+ }
49
+
50
+ .form-row {
51
+ display: grid;
52
+ grid-template-columns: 1fr;
53
+ gap: var(--space-12);
54
+ }
55
+
56
+ .form-row--inline {
57
+ flex-wrap: wrap;
58
+ align-items: flex-end;
59
+ }
60
+ .form-row--inline > .form-group {
61
+ margin-bottom: 0;
62
+ flex: 1;
63
+ min-width: 0;
64
+ }
65
+ .form-row--inline > .form-group.is-fixed {
66
+ flex: 0 0 auto;
67
+ }
@@ -0,0 +1,64 @@
1
+ /* ================================================================
2
+ components/hbar.css
3
+ Horisontell bar - generic single-bar med label + value + track + fill.
4
+ Anvands for kategori-utfall, score-distribution, kostnadsfordelningar.
5
+
6
+ .hbar ar bas. .hbar__track ar fyllbar bakgrund. .hbar__fill ar
7
+ det procent-fyllda overlayet. .hbar__label och .hbar__value ar
8
+ text-element under/over baren.
9
+
10
+ Bredd pa .hbar__fill satts via data-bar-width + bar-styles.js
11
+ (CSP-safe). Manuell override-class kan ocksa anvandas (.hbar__fill-50).
12
+ ================================================================ */
13
+ .hbar {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: var(--space-6);
17
+ margin-bottom: var(--space-12);
18
+ }
19
+
20
+ .hbar__item {
21
+ display: flex;
22
+ align-items: baseline;
23
+ justify-content: space-between;
24
+ gap: var(--space-10);
25
+ }
26
+
27
+ .hbar__label {
28
+ font-size: var(--fs-13);
29
+ color: var(--text-subtle);
30
+ flex: 1;
31
+ min-width: 0;
32
+ }
33
+
34
+ .hbar__value {
35
+ font-size: var(--fs-13);
36
+ font-weight: var(--fw-medium);
37
+ color: var(--text-default);
38
+ font-variant-numeric: tabular-nums;
39
+ white-space: nowrap;
40
+ flex-shrink: 0;
41
+ }
42
+
43
+ .hbar__track {
44
+ width: 100%;
45
+ height: var(--space-6);
46
+ background: var(--surface-active);
47
+ border-radius: var(--radius-full);
48
+ overflow: hidden;
49
+ }
50
+
51
+ .hbar__fill {
52
+ height: 100%;
53
+ background: var(--accent-9);
54
+ border-radius: var(--radius-full);
55
+ transition: width var(--dur-medium) var(--ease-spring-snappy);
56
+ }
57
+
58
+ .hbar__fill--positive { background: var(--positive); }
59
+ .hbar__fill--warning { background: var(--warning); }
60
+ .hbar__fill--negative { background: var(--negative); }
61
+
62
+ @media (prefers-reduced-motion: reduce) {
63
+ .hbar__fill { transition: none; }
64
+ }
@@ -0,0 +1,85 @@
1
+ /* ================================================================
2
+ components/hero.css
3
+ Stora display-rubriker med amount + meta. Anvands pa dashboard,
4
+ detaljvyer, primary-page-toppar.
5
+
6
+ Element: .hero (wrapper), .hero__heading, .hero__amount (default 80px),
7
+ .hero__amount--card (40px sekundar), .hero__amount-row, .hero__label,
8
+ .hero__label--muted, .hero__meta, .hero__actions.
9
+
10
+ .hero-amount och .hero__amount-roll anvands av hero-roll-animation
11
+ - se components/hero-roll.css for animation-styling.
12
+ ================================================================ */
13
+ .hero {
14
+ padding: var(--space-20) var(--space-4) var(--space-24);
15
+ text-align: left;
16
+ }
17
+
18
+ .hero__heading {
19
+ font-size: var(--fs-17);
20
+ font-weight: var(--fw-medium);
21
+ letter-spacing: var(--ls-tight);
22
+ color: var(--text-default);
23
+ margin: 0 0 var(--space-4);
24
+ }
25
+
26
+ .hero__label {
27
+ font-size: var(--fs-12);
28
+ font-weight: var(--fw-medium);
29
+ color: var(--text-muted);
30
+ letter-spacing: var(--ls-wider, 0.04em);
31
+ text-transform: uppercase;
32
+ margin: 0 0 var(--space-8);
33
+ }
34
+
35
+ .hero__label--muted {
36
+ font-size: var(--fs-10);
37
+ font-weight: var(--fw-regular);
38
+ color: var(--text-disabled);
39
+ letter-spacing: 0.03em;
40
+ text-transform: lowercase;
41
+ opacity: 0.7;
42
+ }
43
+
44
+ .hero__amount {
45
+ font-size: var(--fs-80);
46
+ font-weight: var(--fw-medium);
47
+ letter-spacing: var(--ls-tightest, -0.04em);
48
+ color: var(--text-default);
49
+ line-height: var(--lh-tight);
50
+ margin: 0 0 var(--space-8);
51
+ font-variant-numeric: tabular-nums;
52
+ }
53
+
54
+ .hero__amount--card {
55
+ font-size: var(--fs-40);
56
+ letter-spacing: var(--ls-tighter, -0.035em);
57
+ line-height: var(--lh-snug);
58
+ }
59
+
60
+ .hero__amount--fluid {
61
+ font-size: clamp(40px, 12vw, 80px);
62
+ }
63
+
64
+ .hero__amount-row {
65
+ display: flex;
66
+ align-items: center;
67
+ gap: var(--space-10);
68
+ margin-bottom: var(--space-8);
69
+ }
70
+
71
+ .hero__amount-row .hero__amount,
72
+ .hero__amount-row .hero__amount--card { margin-bottom: 0; }
73
+
74
+ .hero__meta {
75
+ font-size: var(--fs-13);
76
+ color: var(--text-subtle);
77
+ margin: 0 0 var(--space-20);
78
+ }
79
+
80
+ .hero__actions {
81
+ display: flex;
82
+ gap: var(--space-8);
83
+ align-items: center;
84
+ flex-wrap: wrap;
85
+ }