@kolkrabbi/kol-theme 0.1.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.
- package/README.md +26 -0
- package/kol-base-tokens.css +74 -0
- package/kol-color.css +280 -0
- package/kol-components-atoms.css +709 -0
- package/kol-components-molecules.css +255 -0
- package/kol-components-organisms.css +220 -0
- package/kol-opacity.css +369 -0
- package/kol-opaque.css +203 -0
- package/kol-theme.css +110 -0
- package/kol-type-mono-classes.css +115 -0
- package/kol-typography-mono.css +64 -0
- package/kol-typography.css +1090 -0
- package/kol-utilities.css +92 -0
- package/package.json +34 -0
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* KOL components — atom tier
|
|
3
|
+
*
|
|
4
|
+
* Shared chrome primitive for interactive controls. Every chromed control
|
|
5
|
+
* (Input, Stepper, Dropdown trigger, ViewToggle option, etc.) composes
|
|
6
|
+
* from these classes instead of reinventing bg/border/padding/transitions.
|
|
7
|
+
*
|
|
8
|
+
* ─────────────────────────────────────────────────────────────────────
|
|
9
|
+
* .kol-control — control shell primitive
|
|
10
|
+
* ─────────────────────────────────────────────────────────────────────
|
|
11
|
+
*
|
|
12
|
+
* Apply: <div class="kol-control kol-control--{variant} kol-control-{size} kol-mono-{N}">
|
|
13
|
+
*
|
|
14
|
+
* Always:
|
|
15
|
+
* .kol-control base (transition, radius 4px, layout border)
|
|
16
|
+
*
|
|
17
|
+
* Variant (visual treatment) — pick one:
|
|
18
|
+
* .kol-control--filled persistent solid bg
|
|
19
|
+
* (Input filled, Stepper, ViewToggle active)
|
|
20
|
+
* .kol-control--ghost transparent at rest, border reveals on
|
|
21
|
+
* hover / focus-within
|
|
22
|
+
* (Input ghost, hex chip, inline editable)
|
|
23
|
+
* .kol-control--outline bordered, transparent bg
|
|
24
|
+
* (Dropdown default trigger, segmented bar,
|
|
25
|
+
* also: forced-reveal "is-edited" state on
|
|
26
|
+
* what would otherwise be a ghost)
|
|
27
|
+
*
|
|
28
|
+
* Size (padding + matched type class) — pick one:
|
|
29
|
+
* .kol-control-sm padding 4px 12px → pair w/ kol-mono-12
|
|
30
|
+
* .kol-control-md padding 6px 16px → pair w/ kol-mono-14
|
|
31
|
+
* .kol-control-lg padding 8px 20px → pair w/ kol-mono-16
|
|
32
|
+
*
|
|
33
|
+
* State:
|
|
34
|
+
* [aria-disabled="true"] /
|
|
35
|
+
* :disabled auto opacity-50 + pointer-events-none
|
|
36
|
+
*
|
|
37
|
+
* Single visible-border tone (--kol-fg-16). No hover/focus escalation,
|
|
38
|
+
* no `--bordered` modifier. When you want a ghost field to render
|
|
39
|
+
* persistently visible (e.g. "is-edited" indicator), switch the variant
|
|
40
|
+
* to `--outline` — same visual, clearer semantic.
|
|
41
|
+
*
|
|
42
|
+
* Type class is JSX-applied (`kol-mono-12 / -14 / -16`) — the shell controls
|
|
43
|
+
* spacing + chrome, the type class controls font. Two reasons: (1) the type
|
|
44
|
+
* system is a separate locked surface (typography.js), and (2) consumers can
|
|
45
|
+
* override the type class for one-off cases (e.g. uppercase labels in helpers)
|
|
46
|
+
* without forking the size variant.
|
|
47
|
+
*
|
|
48
|
+
* Radius is hard-coded to var(--kol-radius-sm) (4px). Repo invariant — never
|
|
49
|
+
* exceed 4px.
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
.kol-control {
|
|
53
|
+
display: inline-flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
border-radius: var(--kol-radius-sm);
|
|
56
|
+
border: 1px solid transparent;
|
|
57
|
+
transition: background-color 150ms ease,
|
|
58
|
+
border-color 150ms ease,
|
|
59
|
+
color 150ms ease;
|
|
60
|
+
cursor: pointer;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* ─── Variants ─── */
|
|
64
|
+
|
|
65
|
+
.kol-control--filled {
|
|
66
|
+
background-color: var(--kol-surface-secondary);
|
|
67
|
+
color: var(--kol-surface-on-primary);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.kol-control--ghost {
|
|
71
|
+
/* Subtle resting bg so the input bounds are discoverable without
|
|
72
|
+
* hovering. Theme-independent darken via fg-absolute-04 (4% black);
|
|
73
|
+
* on dark theme this reads as a softly sunken input area, on light
|
|
74
|
+
* theme as a faintly tinted field. Hover/focus then reveals the
|
|
75
|
+
* border for affordance. */
|
|
76
|
+
background-color: var(--kol-fg-absolute-04);
|
|
77
|
+
color: var(--kol-fg-meta);
|
|
78
|
+
}
|
|
79
|
+
.kol-control--ghost:hover,
|
|
80
|
+
.kol-control--ghost:focus-within {
|
|
81
|
+
border-color: var(--kol-fg-16);
|
|
82
|
+
color: var(--kol-surface-on-primary);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.kol-control--outline {
|
|
86
|
+
background-color: transparent;
|
|
87
|
+
color: var(--kol-surface-on-primary);
|
|
88
|
+
border-color: var(--kol-fg-16);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* Textarea modifier — flips the inline-flex shell to block so a multi-line
|
|
92
|
+
* textarea takes full width. Resize is disabled (textarea is fixed at its
|
|
93
|
+
* `rows` count, content scrolls). The kol resize-corner icon in the
|
|
94
|
+
* bottom-right is decorative. Used by atoms/Textarea.jsx. */
|
|
95
|
+
.kol-control--textarea {
|
|
96
|
+
display: block;
|
|
97
|
+
position: relative;
|
|
98
|
+
padding: 0; /* outer label is purely a wrapper; inner textarea owns padding */
|
|
99
|
+
}
|
|
100
|
+
.kol-control--textarea > textarea {
|
|
101
|
+
padding: 4px 12px;
|
|
102
|
+
}
|
|
103
|
+
.kol-control--textarea.kol-control-md > textarea { padding: 6px 16px; }
|
|
104
|
+
.kol-control--textarea.kol-control-lg > textarea { padding: 8px 20px; }
|
|
105
|
+
.kol-textarea-resize-icon {
|
|
106
|
+
position: absolute;
|
|
107
|
+
bottom: 4px;
|
|
108
|
+
right: 4px;
|
|
109
|
+
display: inline-flex;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* ─── Sizes (padding only — type class applied via JSX) ─── */
|
|
113
|
+
|
|
114
|
+
.kol-control-sm { padding: 4px 12px; }
|
|
115
|
+
.kol-control-md { padding: 6px 16px; }
|
|
116
|
+
.kol-control-lg { padding: 8px 20px; }
|
|
117
|
+
|
|
118
|
+
/* ─── Disabled ─── */
|
|
119
|
+
|
|
120
|
+
.kol-control[aria-disabled="true"],
|
|
121
|
+
.kol-control:disabled,
|
|
122
|
+
.kol-control:has(:disabled) {
|
|
123
|
+
opacity: 0.5;
|
|
124
|
+
pointer-events: none;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
129
|
+
* Button — atoms/Button.jsx
|
|
130
|
+
*
|
|
131
|
+
* Variants:
|
|
132
|
+
* .kol-btn-primary subtle bg-fg-04 fill, daily chrome (default)
|
|
133
|
+
* .kol-btn-secondary heavy inverted ink, CTA-adjacent (font-weight 500)
|
|
134
|
+
* .kol-btn-accent brand-yellow filled CTA (font-weight 500)
|
|
135
|
+
* .kol-btn-outline bordered, transparent bg
|
|
136
|
+
*
|
|
137
|
+
* Sizes (padding shared with .kol-control):
|
|
138
|
+
* .kol-btn-sm 4px 12px → kol-mono-12
|
|
139
|
+
* .kol-btn-md 6px 16px → kol-mono-14
|
|
140
|
+
* .kol-btn-lg 8px 20px → kol-mono-16
|
|
141
|
+
*
|
|
142
|
+
* Modifiers:
|
|
143
|
+
* .kol-btn-animate disables default hover states (consumer drives)
|
|
144
|
+
* :disabled opacity-disabled + not-allowed cursor
|
|
145
|
+
*
|
|
146
|
+
* Type: applied via .kol-mono-{12,14,16} on the size variant in JSX.
|
|
147
|
+
* No uppercase / capitalize — author strings in the case they should
|
|
148
|
+
* render (per ARCHITECTURE.md §2). Radius hard 4px (--kol-radius-sm).
|
|
149
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
150
|
+
|
|
151
|
+
.kol-btn {
|
|
152
|
+
display: inline-flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: center;
|
|
155
|
+
border-radius: var(--kol-radius-sm);
|
|
156
|
+
white-space: nowrap;
|
|
157
|
+
transition: background-color var(--kol-transition-base),
|
|
158
|
+
color var(--kol-transition-base),
|
|
159
|
+
border-color var(--kol-transition-base);
|
|
160
|
+
cursor: pointer;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.kol-btn-primary {
|
|
164
|
+
background: var(--kol-surface-secondary);
|
|
165
|
+
color: var(--kol-surface-on-primary);
|
|
166
|
+
border: 1px solid transparent;
|
|
167
|
+
}
|
|
168
|
+
.kol-btn-primary:not(.kol-btn-animate):hover {
|
|
169
|
+
background-color: var(--kol-fg-08);
|
|
170
|
+
color: var(--kol-surface-on-primary);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.kol-btn-secondary {
|
|
174
|
+
background: var(--kol-surface-on-primary);
|
|
175
|
+
color: var(--kol-surface-primary);
|
|
176
|
+
border: 1px solid transparent;
|
|
177
|
+
font-weight: 500;
|
|
178
|
+
}
|
|
179
|
+
.kol-btn-secondary:not(.kol-btn-animate):hover {
|
|
180
|
+
background-color: color-mix(in srgb, var(--kol-surface-on-primary) 20%, transparent);
|
|
181
|
+
color: var(--kol-surface-on-primary);
|
|
182
|
+
border-color: transparent;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.kol-btn-accent {
|
|
186
|
+
background: var(--kol-accent-primary);
|
|
187
|
+
color: var(--kol-accent-on-primary);
|
|
188
|
+
border: 1px solid transparent;
|
|
189
|
+
font-weight: 500;
|
|
190
|
+
}
|
|
191
|
+
.kol-btn-accent:not(.kol-btn-animate):hover {
|
|
192
|
+
background-color: var(--kol-accent-primary-strong);
|
|
193
|
+
color: var(--kol-accent-on-primary);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.kol-btn-outline {
|
|
197
|
+
background: transparent;
|
|
198
|
+
color: var(--kol-surface-on-primary);
|
|
199
|
+
border: 1px solid var(--kol-fg-16);
|
|
200
|
+
}
|
|
201
|
+
.kol-btn-outline:not(.kol-btn-animate):hover {
|
|
202
|
+
background-color: var(--kol-fg-08);
|
|
203
|
+
border-color: color-mix(in srgb, var(--kol-surface-on-primary) 25%, transparent);
|
|
204
|
+
color: var(--kol-surface-on-primary);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.kol-btn-ghost {
|
|
208
|
+
background: transparent;
|
|
209
|
+
color: var(--kol-fg-48);
|
|
210
|
+
border: 1px solid transparent;
|
|
211
|
+
}
|
|
212
|
+
.kol-btn-ghost:not(.kol-btn-animate):hover {
|
|
213
|
+
background-color: var(--kol-fg-08);
|
|
214
|
+
color: var(--kol-surface-on-primary);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.kol-btn-sm { padding: 4px 12px; }
|
|
218
|
+
.kol-btn-md { padding: 6px 16px; }
|
|
219
|
+
.kol-btn-lg { padding: 8px 20px; }
|
|
220
|
+
|
|
221
|
+
.kol-btn:disabled,
|
|
222
|
+
.kol-btn[disabled] {
|
|
223
|
+
opacity: var(--kol-opacity-disabled);
|
|
224
|
+
cursor: not-allowed;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.kol-btn-animate {
|
|
228
|
+
/* Consumer-driven hover behavior; disables default :hover rules above. */
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* .kol-btn-quiet — secondary-action icon button: dimmed at rest, brightens
|
|
232
|
+
* on hover, stays dimmed when disabled (no hover lift on a non-actionable
|
|
233
|
+
* state). For icon-only buttons in panel chrome (add layer, delete, etc.)
|
|
234
|
+
* that shouldn't compete with primary content visually. */
|
|
235
|
+
.kol-btn-quiet {
|
|
236
|
+
opacity: var(--kol-opacity-disabled);
|
|
237
|
+
transition: opacity 150ms ease;
|
|
238
|
+
}
|
|
239
|
+
.kol-btn-quiet:not(:disabled):hover {
|
|
240
|
+
opacity: 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Icon-swap animation (Button.jsx iconLeft / iconRight with hover icon) */
|
|
244
|
+
|
|
245
|
+
.kol-icon-swap-container {
|
|
246
|
+
position: relative;
|
|
247
|
+
display: inline-flex;
|
|
248
|
+
overflow: hidden;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.kol-icon-default {
|
|
252
|
+
position: absolute;
|
|
253
|
+
transition: opacity var(--kol-transition-base),
|
|
254
|
+
transform var(--kol-transition-base);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.kol-icon-hover {
|
|
258
|
+
position: absolute;
|
|
259
|
+
opacity: 0;
|
|
260
|
+
transform: translateY(4px);
|
|
261
|
+
transition: opacity var(--kol-transition-base),
|
|
262
|
+
transform var(--kol-transition-base);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.kol-btn:hover .kol-icon-default {
|
|
266
|
+
opacity: 0;
|
|
267
|
+
transform: translateY(-4px);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.kol-btn:hover .kol-icon-hover {
|
|
271
|
+
opacity: 1;
|
|
272
|
+
transform: translateY(0);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
277
|
+
* Toggle Bracket — molecules/ToggleBracket.jsx
|
|
278
|
+
*
|
|
279
|
+
* Default-variant chrome comes from .kol-control--filled. The active
|
|
280
|
+
* state overrides bg + color via this modifier — preserves the
|
|
281
|
+
* accent-yellow identity while the rest of the chrome stays shell.
|
|
282
|
+
* Plain variant is bare-text with no shell (defined inline in JSX).
|
|
283
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
284
|
+
|
|
285
|
+
.toggle-bracket--active {
|
|
286
|
+
background-color: var(--kol-accent-primary);
|
|
287
|
+
color: var(--kol-accent-on-primary);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
292
|
+
* Toggle Switch — atoms/ToggleSwitch.jsx
|
|
293
|
+
*
|
|
294
|
+
* Custom-shape control (not shell-based — slidey indicator geometry).
|
|
295
|
+
* Default + plain variants. ON state inverts: pill bg
|
|
296
|
+
* absolute-white, indicator absolute-black (theme-invariant).
|
|
297
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
298
|
+
|
|
299
|
+
.toggle-switch {
|
|
300
|
+
display: flex;
|
|
301
|
+
align-items: center;
|
|
302
|
+
justify-content: space-between;
|
|
303
|
+
gap: 12px;
|
|
304
|
+
padding: 10px 14px;
|
|
305
|
+
border-radius: 4px;
|
|
306
|
+
border: 1px solid color-mix(in srgb, var(--kol-surface-on-primary) 12%, transparent);
|
|
307
|
+
background-color: transparent;
|
|
308
|
+
color: var(--kol-surface-on-primary);
|
|
309
|
+
transition: background-color var(--kol-transition-base),
|
|
310
|
+
border-color var(--kol-transition-base);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.toggle-switch:hover,
|
|
314
|
+
.toggle-switch:focus-visible {
|
|
315
|
+
border-color: color-mix(in srgb, var(--kol-surface-on-primary) 18%, transparent);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
.toggle-switch-label {
|
|
319
|
+
font-family: var(--kol-font-family-mono);
|
|
320
|
+
font-size: 11px;
|
|
321
|
+
text-transform: uppercase;
|
|
322
|
+
letter-spacing: 0.08em;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.toggle-switch-indicator {
|
|
326
|
+
width: 20px;
|
|
327
|
+
height: 12px;
|
|
328
|
+
border-radius: var(--kol-radius-full);
|
|
329
|
+
background-color: color-mix(in srgb, var(--kol-surface-on-primary) 16%, transparent);
|
|
330
|
+
position: relative;
|
|
331
|
+
transition: background-color var(--kol-transition-base);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.toggle-switch-indicator::after {
|
|
335
|
+
content: '';
|
|
336
|
+
position: absolute;
|
|
337
|
+
top: 2px;
|
|
338
|
+
left: 2px;
|
|
339
|
+
width: 8px;
|
|
340
|
+
height: 8px;
|
|
341
|
+
border-radius: var(--kol-radius-full);
|
|
342
|
+
background-color: var(--kol-surface-primary);
|
|
343
|
+
transition: transform var(--kol-transition-base),
|
|
344
|
+
background-color var(--kol-transition-base);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.toggle-switch[data-state='on'] .toggle-switch-indicator {
|
|
348
|
+
background-color: var(--kol-color-absolute-white);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.toggle-switch[data-state='on'] .toggle-switch-indicator::after {
|
|
352
|
+
transform: translateX(8px);
|
|
353
|
+
background-color: var(--kol-color-absolute-black);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.toggle-switch--plain {
|
|
357
|
+
padding: 0;
|
|
358
|
+
border: none;
|
|
359
|
+
background-color: transparent;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.toggle-switch--plain:hover,
|
|
363
|
+
.toggle-switch--plain:focus-visible {
|
|
364
|
+
background-color: transparent;
|
|
365
|
+
border-color: transparent;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
370
|
+
* Toggle Checkbox — atoms/ToggleCheckbox.jsx
|
|
371
|
+
*
|
|
372
|
+
* Custom-shape control. Active state inverts: box bg absolute-white,
|
|
373
|
+
* no border, check stroke absolute-black (theme-invariant).
|
|
374
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
375
|
+
|
|
376
|
+
.toggle-checkbox {
|
|
377
|
+
display: inline-flex;
|
|
378
|
+
align-items: center;
|
|
379
|
+
gap: 8px;
|
|
380
|
+
cursor: pointer;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.toggle-checkbox input {
|
|
384
|
+
display: none;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.toggle-checkbox-indicator {
|
|
388
|
+
display: inline-flex;
|
|
389
|
+
align-items: center;
|
|
390
|
+
justify-content: center;
|
|
391
|
+
width: 16px;
|
|
392
|
+
height: 16px;
|
|
393
|
+
border-radius: 3px;
|
|
394
|
+
border: 1px solid color-mix(in srgb, var(--kol-surface-on-primary) 25%, transparent);
|
|
395
|
+
background-color: transparent;
|
|
396
|
+
transition: background-color var(--kol-transition-base),
|
|
397
|
+
border-color var(--kol-transition-base);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.toggle-checkbox-indicator svg {
|
|
401
|
+
width: 10px;
|
|
402
|
+
height: 8px;
|
|
403
|
+
stroke: var(--kol-color-absolute-black);
|
|
404
|
+
opacity: 0;
|
|
405
|
+
transition: opacity var(--kol-transition-base);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.toggle-checkbox.is-active .toggle-checkbox-indicator {
|
|
409
|
+
background-color: var(--kol-color-absolute-white);
|
|
410
|
+
border-color: transparent;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.toggle-checkbox.is-active .toggle-checkbox-indicator svg {
|
|
414
|
+
opacity: 1;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
419
|
+
* Slider — atoms/Slider.jsx
|
|
420
|
+
*
|
|
421
|
+
* Range-input with custom track + thumb pseudo-elements. Two variants
|
|
422
|
+
* post-2026-04-30 restructure (bordered `default` retired):
|
|
423
|
+
*
|
|
424
|
+
* default bare track + boxed value (was `minimal`). Most-used —
|
|
425
|
+
* Pattern Lab cols/rows/gap, Compositor sliders, Type Lab.
|
|
426
|
+
* subtle filled rounded chip — for inspector-style controls.
|
|
427
|
+
*
|
|
428
|
+
* Track color is exposed as `--kol-slider-track` (set on `.slider-black`)
|
|
429
|
+
* so consumers can override per-instance via inline style or className.
|
|
430
|
+
* Default = fg-64 (dim grey); subtle overrides to full ink.
|
|
431
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
432
|
+
|
|
433
|
+
.control-slider {
|
|
434
|
+
display: inline-flex;
|
|
435
|
+
flex-direction: row;
|
|
436
|
+
align-items: center;
|
|
437
|
+
padding: 0;
|
|
438
|
+
border-radius: 0;
|
|
439
|
+
background-color: transparent;
|
|
440
|
+
border: none;
|
|
441
|
+
height: 24px;
|
|
442
|
+
transition: color var(--kol-transition-base);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.control-slider label { color: var(--kol-fg-80); }
|
|
446
|
+
.control-slider span {
|
|
447
|
+
color: var(--kol-surface-on-primary);
|
|
448
|
+
padding: 8px 0;
|
|
449
|
+
border-radius: 4px;
|
|
450
|
+
background-color: var(--kol-surface-secondary);
|
|
451
|
+
width: 64px;
|
|
452
|
+
text-align: center;
|
|
453
|
+
flex-shrink: 0;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.control-slider-subtle {
|
|
457
|
+
display: inline-flex;
|
|
458
|
+
flex-direction: row;
|
|
459
|
+
align-items: center;
|
|
460
|
+
padding: 6px 16px;
|
|
461
|
+
border-radius: 4px;
|
|
462
|
+
background-color: var(--kol-surface-secondary);
|
|
463
|
+
border: none;
|
|
464
|
+
transition: background-color var(--kol-transition-base),
|
|
465
|
+
color var(--kol-transition-base);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.control-slider-subtle label {
|
|
469
|
+
color: var(--kol-fg-48);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.control-slider-subtle .slider-black {
|
|
473
|
+
--kol-slider-track: var(--kol-surface-on-primary);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.slider-black {
|
|
477
|
+
--kol-slider-track: var(--kol-fg-64);
|
|
478
|
+
-webkit-appearance: none;
|
|
479
|
+
appearance: none;
|
|
480
|
+
background: transparent;
|
|
481
|
+
cursor: pointer;
|
|
482
|
+
height: 2px;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
.slider-black::-webkit-slider-runnable-track {
|
|
486
|
+
background: var(--kol-slider-track);
|
|
487
|
+
height: 2px;
|
|
488
|
+
border-radius: 0;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.slider-black::-moz-range-track {
|
|
492
|
+
background: var(--kol-slider-track);
|
|
493
|
+
height: 2px;
|
|
494
|
+
border-radius: 0;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.slider-black::-webkit-slider-thumb {
|
|
498
|
+
-webkit-appearance: none;
|
|
499
|
+
appearance: none;
|
|
500
|
+
background: var(--kol-surface-on-primary);
|
|
501
|
+
height: 12px;
|
|
502
|
+
width: 12px;
|
|
503
|
+
border-radius: 50%;
|
|
504
|
+
margin-top: -5px;
|
|
505
|
+
border: none;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.slider-black::-moz-range-thumb {
|
|
509
|
+
appearance: none;
|
|
510
|
+
background: var(--kol-surface-on-primary);
|
|
511
|
+
height: 12px;
|
|
512
|
+
width: 12px;
|
|
513
|
+
border-radius: 50%;
|
|
514
|
+
border: none;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
519
|
+
* Sidenav primitives — promoted from kol-framework.css 2026-04-30.
|
|
520
|
+
*
|
|
521
|
+
* .kol-sidenav-hop row primitive (icon + label, full-width)
|
|
522
|
+
* .kol-sidenav-hop-icon icon slot inside the hop
|
|
523
|
+
* .kol-sidenav-hop-label label slot — collapses to display:none in
|
|
524
|
+
* rail mode (responsive cascade in framework.css)
|
|
525
|
+
* .kol-sidenav-link nav link with active-dot indicator
|
|
526
|
+
* .kol-sidenav-group small vertical wrapper
|
|
527
|
+
*
|
|
528
|
+
* Layout/sizing/responsive collapse rules stay in kol-framework.css
|
|
529
|
+
* (they're page-grid concerns, not component chrome).
|
|
530
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
531
|
+
|
|
532
|
+
.kol-sidenav-hop {
|
|
533
|
+
color: var(--kol-fg-80);
|
|
534
|
+
text-transform: uppercase;
|
|
535
|
+
letter-spacing: 0.06em;
|
|
536
|
+
transition: color 150ms ease, background 150ms ease;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.kol-sidenav-hop:hover {
|
|
540
|
+
color: var(--kol-fg-96);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.kol-sidenav-hop.is-active {
|
|
544
|
+
color: var(--kol-surface-on-primary);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.kol-sidenav-hop-icon {
|
|
548
|
+
color: var(--kol-fg-80);
|
|
549
|
+
transition: color 150ms ease;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
.kol-sidenav-hop:hover .kol-sidenav-hop-icon {
|
|
553
|
+
color: var(--kol-surface-on-primary);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.kol-sidenav-hop.is-active .kol-sidenav-hop-icon {
|
|
557
|
+
color: var(--kol-accent-primary);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.kol-sidenav-group {
|
|
561
|
+
padding: 4px 0 4px;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.kol-sidenav-link.is-active {
|
|
565
|
+
color: var(--kol-surface-on-primary);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.kol-sidenav-link.is-active::before {
|
|
569
|
+
content: "";
|
|
570
|
+
position: absolute;
|
|
571
|
+
left: var(--kol-sidenav-dot-left, 2px);
|
|
572
|
+
top: 50%;
|
|
573
|
+
transform: translateY(-50%);
|
|
574
|
+
width: 4px;
|
|
575
|
+
height: 4px;
|
|
576
|
+
border-radius: 50%;
|
|
577
|
+
background: var(--kol-accent-primary);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
|
|
581
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
582
|
+
* Page section divider — promoted from kol-framework.css.
|
|
583
|
+
* Helper class on the Divider atom when used as a PageSection lead-in.
|
|
584
|
+
* Hides on the first PageSection of a page.
|
|
585
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
586
|
+
|
|
587
|
+
.kol-page-section-divider {
|
|
588
|
+
margin-top: -64px;
|
|
589
|
+
margin-bottom: 64px;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
.kol-page-section:first-of-type > .kol-page-section-divider {
|
|
593
|
+
display: none;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
|
|
597
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
598
|
+
* Section label typography — promoted from residual kol-components.css.
|
|
599
|
+
* Used by molecules/SectionLabel.jsx. Mono variants + compact variants.
|
|
600
|
+
* Typography-adjacent; lives here because consumed by atom-tier
|
|
601
|
+
* components (SectionLabel etc.).
|
|
602
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
603
|
+
|
|
604
|
+
.kol-label-mono-sm {
|
|
605
|
+
font-family: var(--kol-font-family-mono);
|
|
606
|
+
font-weight: 470;
|
|
607
|
+
font-size: clamp(14px, 1.5vw, 24px);
|
|
608
|
+
line-height: 100%;
|
|
609
|
+
text-transform: uppercase;
|
|
610
|
+
letter-spacing: 0.05em;
|
|
611
|
+
color: var(--kol-surface-on-primary);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.kol-label-mono-md {
|
|
615
|
+
font-family: var(--kol-font-family-mono);
|
|
616
|
+
font-weight: 470;
|
|
617
|
+
font-size: clamp(12px, 1vw, 16px);
|
|
618
|
+
line-height: 125%;
|
|
619
|
+
text-transform: uppercase;
|
|
620
|
+
letter-spacing: 0.05em;
|
|
621
|
+
color: var(--kol-surface-on-primary);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.kol-label-mono-xs {
|
|
625
|
+
font-family: var(--kol-font-family-mono);
|
|
626
|
+
font-weight: 470;
|
|
627
|
+
font-size: clamp(10px, 0.8vw, 14px);
|
|
628
|
+
line-height: 100%;
|
|
629
|
+
text-transform: uppercase;
|
|
630
|
+
letter-spacing: 0.05em;
|
|
631
|
+
color: var(--kol-surface-on-primary);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
.kol-label-compact-lg {
|
|
635
|
+
font-family: var(--kol-font-family-mono);
|
|
636
|
+
font-weight: 500;
|
|
637
|
+
font-size: clamp(24px, 2vw, 28px);
|
|
638
|
+
line-height: 100%;
|
|
639
|
+
text-transform: uppercase;
|
|
640
|
+
letter-spacing: 0.03em;
|
|
641
|
+
color: var(--kol-surface-on-primary);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
.kol-label-compact-md {
|
|
645
|
+
font-family: var(--kol-font-family-mono);
|
|
646
|
+
font-weight: 500;
|
|
647
|
+
font-size: clamp(12px, 1vw, 16px);
|
|
648
|
+
line-height: 100%;
|
|
649
|
+
text-transform: uppercase;
|
|
650
|
+
letter-spacing: 0.03em;
|
|
651
|
+
color: var(--kol-surface-on-primary);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.kol-label {
|
|
655
|
+
font-family: var(--kol-font-family-mono);
|
|
656
|
+
font-weight: 470;
|
|
657
|
+
font-size: clamp(14px, 1.5vw, 24px);
|
|
658
|
+
line-height: 100%;
|
|
659
|
+
text-transform: uppercase;
|
|
660
|
+
letter-spacing: 0.05em;
|
|
661
|
+
color: var(--kol-surface-on-primary);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
.kol-label-compact {
|
|
665
|
+
font-family: var(--kol-font-family-mono);
|
|
666
|
+
font-weight: 500;
|
|
667
|
+
font-size: clamp(12px, 1vw, 16px);
|
|
668
|
+
line-height: 100%;
|
|
669
|
+
text-transform: uppercase;
|
|
670
|
+
letter-spacing: 0.03em;
|
|
671
|
+
color: var(--kol-surface-on-primary);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
|
|
675
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
676
|
+
* Icon-swap utility — promoted from residual kol-components.css.
|
|
677
|
+
* Used by molecules/SectionLabel.jsx and any <button>/<a> with
|
|
678
|
+
* .icon-default / .icon-hover children.
|
|
679
|
+
* (Distinct from .kol-icon-swap-* used internally by atoms/Button.jsx
|
|
680
|
+
* — see Button section above.)
|
|
681
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
682
|
+
|
|
683
|
+
.icon-default {
|
|
684
|
+
transform: translate(0, 0) scale(1);
|
|
685
|
+
opacity: 1;
|
|
686
|
+
transition: transform var(--kol-transition-base) ease,
|
|
687
|
+
opacity var(--kol-transition-base) ease;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.icon-hover {
|
|
691
|
+
transform: translate(-100%, -100%) scale(0.8);
|
|
692
|
+
opacity: 0;
|
|
693
|
+
transition: transform var(--kol-transition-base) ease,
|
|
694
|
+
opacity var(--kol-transition-base) ease;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
button:hover .icon-default,
|
|
698
|
+
a:hover .icon-default,
|
|
699
|
+
.section-label-wrapper:hover .icon-default {
|
|
700
|
+
transform: translate(100%, 100%) scale(0.8);
|
|
701
|
+
opacity: 0;
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
button:hover .icon-hover,
|
|
705
|
+
a:hover .icon-hover,
|
|
706
|
+
.section-label-wrapper:hover .icon-hover {
|
|
707
|
+
transform: translate(0, 0) scale(1);
|
|
708
|
+
opacity: 1;
|
|
709
|
+
}
|