@kouji-ui/themes 0.0.6 → 0.1.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/package.json +3 -2
- package/src/base.css +20 -0
- package/src/density.css +135 -0
- package/src/density.spec.ts +144 -0
- package/src/index.css +3 -0
- package/src/themes/bauhaus.css +7 -0
- package/src/themes/corporate.css +7 -0
- package/src/themes/cyberpunk.css +7 -0
- package/src/themes/dark.css +7 -0
- package/src/themes/dune.css +7 -0
- package/src/themes/forest.css +7 -0
- package/src/themes/kouji.css +7 -0
- package/src/themes/light.css +7 -0
- package/src/themes/mint.css +7 -0
- package/src/themes/nord.css +7 -0
- package/src/themes/orrery-light.css +103 -0
- package/src/themes/orrery.css +108 -0
- package/src/themes/retro.css +8 -0
- package/src/themes/sakura.css +7 -0
- package/src/themes/terminal.css +7 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kouji-ui/themes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Theme tokens and theme stylesheets for kouji-ui — pure CSS, swappable at runtime via data-theme.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"exports": {
|
|
33
33
|
".": "./src/index.css",
|
|
34
34
|
"./base.css": "./src/base.css",
|
|
35
|
-
"./
|
|
35
|
+
"./density.css": "./src/density.css",
|
|
36
|
+
"./themes/*.css": "./src/themes/*.css"
|
|
36
37
|
},
|
|
37
38
|
"scripts": {
|
|
38
39
|
"build": "echo 'no build for css-only package'",
|
package/src/base.css
CHANGED
|
@@ -128,6 +128,26 @@
|
|
|
128
128
|
--kj-base-transition-fast: 0.12s ease;
|
|
129
129
|
--kj-base-transition-base: 0.2s ease;
|
|
130
130
|
|
|
131
|
+
/* Motion primitives — durations + easings for the motion preset
|
|
132
|
+
library (@kouji-ui/core motion.css). Semantic --kj-motion-* tokens
|
|
133
|
+
below resolve from these; motion.css also carries inline fallbacks
|
|
134
|
+
so it works when themes aren't loaded. Themes may retune any of
|
|
135
|
+
these for a distinct motion identity. */
|
|
136
|
+
--kj-base-duration-fast: 150ms;
|
|
137
|
+
--kj-base-duration-base: 250ms;
|
|
138
|
+
--kj-base-duration-slow: 400ms;
|
|
139
|
+
--kj-base-ease-emphasized: cubic-bezier(0.16, 1, 0.3, 1);
|
|
140
|
+
--kj-base-ease-in: cubic-bezier(0.7, 0, 0.84, 0);
|
|
141
|
+
--kj-base-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
142
|
+
|
|
143
|
+
--kj-motion-duration-sm: var(--kj-base-duration-fast);
|
|
144
|
+
--kj-motion-duration-md: var(--kj-base-duration-base);
|
|
145
|
+
--kj-motion-duration-lg: var(--kj-base-duration-slow);
|
|
146
|
+
--kj-motion-ease: var(--kj-base-ease-emphasized);
|
|
147
|
+
--kj-motion-ease-in: var(--kj-base-ease-in);
|
|
148
|
+
--kj-motion-ease-spring: var(--kj-base-ease-spring);
|
|
149
|
+
--kj-motion-distance: 0.5rem;
|
|
150
|
+
|
|
131
151
|
/* ── Display-tone primitives (per-theme overridable, sane defaults)
|
|
132
152
|
Themes only redeclare when their identity calls for it (e.g. retro
|
|
133
153
|
wants italic display; bauhaus wants extra-heavy weight; sakura
|
package/src/density.css
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────────────────────
|
|
2
|
+
@kouji-ui/themes — density layer
|
|
3
|
+
App-wide density. Before this, density existed only on the table
|
|
4
|
+
(--kj-table-row-height); everything else was fixed.
|
|
5
|
+
|
|
6
|
+
Mechanism: two inherited scalars, not per-component selectors.
|
|
7
|
+
Components use ViewEncapsulation.None, so a [data-density] selector
|
|
8
|
+
WOULD reach them — but it would need one block per component per level,
|
|
9
|
+
and the ratio would live in dozens of places. Two inherited numbers put
|
|
10
|
+
the ratio in one place and, because custom properties inherit, a dense
|
|
11
|
+
region nests correctly inside a comfortable app with no extra rules.
|
|
12
|
+
|
|
13
|
+
Every derived value is round()ed to a whole pixel. Fractional heights
|
|
14
|
+
blur hairlines and desync rows from any JS/SVG surface that mirrors them.
|
|
15
|
+
|
|
16
|
+
Layer note: these rules join the EXISTING kj.base layer. Do not add a
|
|
17
|
+
kj.density sublayer — that would mean editing the @layer statement in
|
|
18
|
+
base.css, which desyncs consumers who re-declare the layer order.
|
|
19
|
+
Sitting in kj.base keeps themes (kj.shared) and consumer CSS above it.
|
|
20
|
+
──────────────────────────────────────────────────────────── */
|
|
21
|
+
|
|
22
|
+
/* Registered so JS can read a resolved px value. An UNregistered custom
|
|
23
|
+
property has no computed value: getComputedStyle() returns the raw token
|
|
24
|
+
stream ("round(calc(...))"), and parseFloat gives NaN.
|
|
25
|
+
|
|
26
|
+
Only the scalars and the JS-read ladders are registered. The existing
|
|
27
|
+
--kj-space-* / --kj-text-* deliberately are NOT: registration makes
|
|
28
|
+
invalid-at-computed-value-time *apply*, which would silently discard a
|
|
29
|
+
legitimate consumer override and is a breaking change. */
|
|
30
|
+
@property --kj-density { syntax: "<number>"; inherits: true; initial-value: 1; }
|
|
31
|
+
@property --kj-type-scale { syntax: "<number>"; inherits: true; initial-value: 1; }
|
|
32
|
+
|
|
33
|
+
@property --kj-ctl-h-xs { syntax: "<length>"; inherits: true; initial-value: 28px; }
|
|
34
|
+
@property --kj-ctl-h-sm { syntax: "<length>"; inherits: true; initial-value: 32px; }
|
|
35
|
+
@property --kj-ctl-h-md { syntax: "<length>"; inherits: true; initial-value: 36px; }
|
|
36
|
+
@property --kj-ctl-h-lg { syntax: "<length>"; inherits: true; initial-value: 44px; }
|
|
37
|
+
@property --kj-ctl-h-xl { syntax: "<length>"; inherits: true; initial-value: 52px; }
|
|
38
|
+
@property --kj-row-h { syntax: "<length>"; inherits: true; initial-value: 36px; }
|
|
39
|
+
|
|
40
|
+
@layer kj.base {
|
|
41
|
+
:root {
|
|
42
|
+
--kj-density: 1;
|
|
43
|
+
--kj-type-scale: 1;
|
|
44
|
+
|
|
45
|
+
/* ── numeric spacing ladder ──
|
|
46
|
+
The t-shirt names below re-point at these. Values are kept in rem so
|
|
47
|
+
spacing still tracks the root font size, exactly as before. At
|
|
48
|
+
density 1 every t-shirt token resolves to its previous value to the
|
|
49
|
+
byte — this is a re-pointing, not a re-scaling. */
|
|
50
|
+
--kj-space-1: round(calc(0.125rem * var(--kj-density)), 1px); /* 2px */
|
|
51
|
+
--kj-space-2: round(calc(0.25rem * var(--kj-density)), 1px); /* 4px */
|
|
52
|
+
--kj-space-3: round(calc(0.375rem * var(--kj-density)), 1px); /* 6px */
|
|
53
|
+
--kj-space-4: round(calc(0.5rem * var(--kj-density)), 1px); /* 8px */
|
|
54
|
+
--kj-space-5: round(calc(0.625rem * var(--kj-density)), 1px); /* 10px */
|
|
55
|
+
--kj-space-6: round(calc(0.75rem * var(--kj-density)), 1px); /* 12px */
|
|
56
|
+
--kj-space-7: round(calc(1rem * var(--kj-density)), 1px); /* 16px */
|
|
57
|
+
--kj-space-8: round(calc(1.25rem * var(--kj-density)), 1px); /* 20px */
|
|
58
|
+
--kj-space-9: round(calc(1.5rem * var(--kj-density)), 1px); /* 24px */
|
|
59
|
+
--kj-space-10: round(calc(1.75rem * var(--kj-density)), 1px); /* 28px */
|
|
60
|
+
--kj-space-11: round(calc(2rem * var(--kj-density)), 1px); /* 32px */
|
|
61
|
+
|
|
62
|
+
/* t-shirt names stay the documented API; numeric is the dense-UI
|
|
63
|
+
escape hatch. These land on the same values they always had. */
|
|
64
|
+
--kj-space-xs: var(--kj-space-2); /* 4px */
|
|
65
|
+
--kj-space-sm: var(--kj-space-4); /* 8px */
|
|
66
|
+
--kj-space-md: var(--kj-space-6); /* 12px */
|
|
67
|
+
--kj-space-lg: var(--kj-space-7); /* 16px */
|
|
68
|
+
--kj-space-xl: var(--kj-space-9); /* 24px */
|
|
69
|
+
--kj-space-2xl: var(--kj-space-11); /* 32px */
|
|
70
|
+
--kj-space-3xl: round(calc(3rem * var(--kj-density)), 1px); /* 48px */
|
|
71
|
+
--kj-space-4xl: round(calc(4rem * var(--kj-density)), 1px); /* 64px */
|
|
72
|
+
--kj-space-5xl: round(calc(6rem * var(--kj-density)), 1px); /* 96px */
|
|
73
|
+
--kj-space-6xl: round(calc(8rem * var(--kj-density)), 1px); /* 128px */
|
|
74
|
+
|
|
75
|
+
/* ── type ──
|
|
76
|
+
xs..2xl keep their existing values at scale 1. 3xs/2xs and 3xl/4xl/
|
|
77
|
+
display are ADDITIVE: dense UIs need badge- and meta-sized steps that
|
|
78
|
+
a 6-step scale cannot express, and new names mean no reflow for
|
|
79
|
+
existing consumers. Type is snapped to a half pixel, not a whole one —
|
|
80
|
+
fonts render fine on halves and it keeps the ramp from collapsing. */
|
|
81
|
+
--kj-text-3xs: round(calc(0.625rem * var(--kj-type-scale)), 0.5px); /* 10px */
|
|
82
|
+
--kj-text-2xs: round(calc(0.6875rem * var(--kj-type-scale)), 0.5px); /* 11px */
|
|
83
|
+
--kj-text-xs: round(calc(0.75rem * var(--kj-type-scale)), 0.5px); /* 12px */
|
|
84
|
+
--kj-text-sm: round(calc(0.875rem * var(--kj-type-scale)), 0.5px); /* 14px */
|
|
85
|
+
--kj-text-base: round(calc(1rem * var(--kj-type-scale)), 0.5px); /* 16px */
|
|
86
|
+
--kj-text-lg: round(calc(1.125rem * var(--kj-type-scale)), 0.5px); /* 18px */
|
|
87
|
+
--kj-text-xl: round(calc(1.25rem * var(--kj-type-scale)), 0.5px); /* 20px */
|
|
88
|
+
--kj-text-2xl: round(calc(1.5rem * var(--kj-type-scale)), 0.5px); /* 24px */
|
|
89
|
+
--kj-text-3xl: round(calc(2rem * var(--kj-type-scale)), 0.5px); /* 32px */
|
|
90
|
+
--kj-text-4xl: round(calc(2.5rem * var(--kj-type-scale)), 0.5px); /* 40px */
|
|
91
|
+
--kj-text-display: round(calc(3rem * var(--kj-type-scale)), 0.5px); /* 48px */
|
|
92
|
+
|
|
93
|
+
/* Code surfaces (Monaco, terminals) take metrics as JS numbers — they
|
|
94
|
+
cannot inherit font-size — so they read these two directly. */
|
|
95
|
+
--kj-text-code: round(calc(0.8125rem * var(--kj-type-scale)), 0.5px); /* 13px */
|
|
96
|
+
--kj-leading-code: round(calc(1.125rem * var(--kj-type-scale)), 1px); /* 18px */
|
|
97
|
+
|
|
98
|
+
/* ── control heights ──
|
|
99
|
+
sm/md/lg stay each component's semantic API; this shared ladder is
|
|
100
|
+
what those variants resolve to, so density scales every variant
|
|
101
|
+
uniformly instead of each component hardcoding a rem value. Values
|
|
102
|
+
match the current button heights exactly at density 1. */
|
|
103
|
+
--kj-ctl-h-xs: round(calc(1.75rem * var(--kj-density)), 1px); /* 28px */
|
|
104
|
+
--kj-ctl-h-sm: round(calc(2rem * var(--kj-density)), 1px); /* 32px */
|
|
105
|
+
--kj-ctl-h-md: round(calc(2.25rem * var(--kj-density)), 1px); /* 36px */
|
|
106
|
+
--kj-ctl-h-lg: round(calc(2.75rem * var(--kj-density)), 1px); /* 44px */
|
|
107
|
+
--kj-ctl-h-xl: round(calc(3.25rem * var(--kj-density)), 1px); /* 52px */
|
|
108
|
+
|
|
109
|
+
/* Row height for list/table/tree surfaces. */
|
|
110
|
+
--kj-row-h: var(--kj-ctl-h-md);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* ── presets ──
|
|
114
|
+
Ratios validated in a dense IDE: type breathes more gently than boxes,
|
|
115
|
+
because an 0.85 squeeze that flatters padding is punishing on 12px text.
|
|
116
|
+
|
|
117
|
+
"standard" is declared as an explicit no-op so KjTableDensity's existing
|
|
118
|
+
three values all remain valid — renaming or dropping one would be an API
|
|
119
|
+
break. "comfy" is accepted as an alias; "comfortable" stays canonical. */
|
|
120
|
+
[data-density="compact"] {
|
|
121
|
+
--kj-density: 0.85;
|
|
122
|
+
--kj-type-scale: 0.875;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
[data-density="standard"] {
|
|
126
|
+
--kj-density: 1;
|
|
127
|
+
--kj-type-scale: 1;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
[data-density="comfortable"],
|
|
131
|
+
[data-density="comfy"] {
|
|
132
|
+
--kj-density: 1.18;
|
|
133
|
+
--kj-type-scale: 1.125;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import postcss from 'postcss';
|
|
4
|
+
import { describe, expect, test } from 'vitest';
|
|
5
|
+
|
|
6
|
+
const css = readFileSync(resolve(import.meta.dirname, 'density.css'), 'utf-8');
|
|
7
|
+
const baseCss = readFileSync(resolve(import.meta.dirname, 'base.css'), 'utf-8');
|
|
8
|
+
const indexCss = readFileSync(resolve(import.meta.dirname, 'index.css'), 'utf-8');
|
|
9
|
+
|
|
10
|
+
/** Custom properties registered via `@property` in density.css. */
|
|
11
|
+
function registeredProps(text: string): Set<string> {
|
|
12
|
+
const out = new Set<string>();
|
|
13
|
+
postcss.parse(text).walkAtRules('property', rule => out.add(rule.params.trim()));
|
|
14
|
+
return out;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Declarations inside a rule whose selector matches `selector`. */
|
|
18
|
+
function declsFor(text: string, selector: string): Map<string, string> {
|
|
19
|
+
const out = new Map<string, string>();
|
|
20
|
+
postcss.parse(text).walkRules(rule => {
|
|
21
|
+
if (!rule.selector.includes(selector)) return;
|
|
22
|
+
rule.walkDecls(decl => out.set(decl.prop, decl.value));
|
|
23
|
+
});
|
|
24
|
+
return out;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
describe('density layer', () => {
|
|
28
|
+
test('is exported from the package entry', () => {
|
|
29
|
+
expect(indexCss).toContain("@import './density.css';");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test('joins the existing kj.base layer without redeclaring layer order', () => {
|
|
33
|
+
// Editing the `@layer kj.reset, kj.base, kj.shared, kj.component` statement
|
|
34
|
+
// desyncs consumers who re-declare it, so density.css must not carry one.
|
|
35
|
+
expect(css).toMatch(/@layer\s+kj\.base\s*\{/);
|
|
36
|
+
expect(css).not.toMatch(/@layer\s+[\w.]+\s*,/);
|
|
37
|
+
expect(baseCss).toMatch(/@layer kj\.reset, kj\.base, kj\.shared, kj\.component;/);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe('@property registration', () => {
|
|
41
|
+
const registered = registeredProps(css);
|
|
42
|
+
|
|
43
|
+
test('registers the two scalars', () => {
|
|
44
|
+
expect(registered).toContain('--kj-density');
|
|
45
|
+
expect(registered).toContain('--kj-type-scale');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('registers the height ladder that JS reads', () => {
|
|
49
|
+
for (const t of ['xs', 'sm', 'md', 'lg', 'xl']) {
|
|
50
|
+
expect(registered).toContain(`--kj-ctl-h-${t}`);
|
|
51
|
+
}
|
|
52
|
+
expect(registered).toContain('--kj-row-h');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('does NOT register the pre-existing space/text tokens', () => {
|
|
56
|
+
// Registering them would make invalid-at-computed-value-time APPLY,
|
|
57
|
+
// silently discarding a legitimate consumer override such as
|
|
58
|
+
// `--kj-space-md: 0`. That is a breaking change, so it must not happen.
|
|
59
|
+
for (const prop of registered) {
|
|
60
|
+
expect(prop, `${prop} must not be registered`).not.toMatch(
|
|
61
|
+
/^--kj-(space|text)-/,
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('scale', () => {
|
|
68
|
+
const root = declsFor(css, ':root');
|
|
69
|
+
|
|
70
|
+
test('every t-shirt spacing name re-points at the numeric ladder', () => {
|
|
71
|
+
const expected: Record<string, string> = {
|
|
72
|
+
'--kj-space-xs': 'var(--kj-space-2)',
|
|
73
|
+
'--kj-space-sm': 'var(--kj-space-4)',
|
|
74
|
+
'--kj-space-md': 'var(--kj-space-6)',
|
|
75
|
+
'--kj-space-lg': 'var(--kj-space-7)',
|
|
76
|
+
'--kj-space-xl': 'var(--kj-space-9)',
|
|
77
|
+
'--kj-space-2xl': 'var(--kj-space-11)',
|
|
78
|
+
};
|
|
79
|
+
for (const [name, target] of Object.entries(expected)) {
|
|
80
|
+
expect(root.get(name), `${name} must re-point at ${target}`).toBe(target);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test('the numeric ladder and heights derive from --kj-density', () => {
|
|
85
|
+
for (const n of [1, 4, 7, 11]) {
|
|
86
|
+
expect(root.get(`--kj-space-${n}`)).toMatch(
|
|
87
|
+
/round\(calc\(.*var\(--kj-density\).*\),\s*1px\)/,
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
for (const t of ['xs', 'sm', 'md', 'lg', 'xl']) {
|
|
91
|
+
expect(root.get(`--kj-ctl-h-${t}`)).toMatch(
|
|
92
|
+
/round\(calc\(.*var\(--kj-density\).*\),\s*1px\)/,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test('the type ramp derives from --kj-type-scale, snapped to a half px', () => {
|
|
98
|
+
for (const t of ['3xs', '2xs', 'xs', 'sm', 'base', 'lg', 'xl', '2xl']) {
|
|
99
|
+
expect(root.get(`--kj-text-${t}`)).toMatch(
|
|
100
|
+
/round\(calc\(.*var\(--kj-type-scale\).*\),\s*0\.5px\)/,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('exposes code metrics for editor and terminal surfaces', () => {
|
|
106
|
+
expect(root.get('--kj-text-code')).toBeDefined();
|
|
107
|
+
expect(root.get('--kj-leading-code')).toBeDefined();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('presets', () => {
|
|
112
|
+
test('all three KjTableDensity values remain valid selectors', () => {
|
|
113
|
+
// Renaming or dropping one would break the existing table API.
|
|
114
|
+
for (const level of ['compact', 'standard', 'comfortable']) {
|
|
115
|
+
expect(css).toContain(`[data-density="${level}"]`);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('standard is an explicit no-op', () => {
|
|
120
|
+
const standard = declsFor(css, '[data-density="standard"]');
|
|
121
|
+
expect(standard.get('--kj-density')).toBe('1');
|
|
122
|
+
expect(standard.get('--kj-type-scale')).toBe('1');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('comfy is accepted as an alias of comfortable', () => {
|
|
126
|
+
expect(css).toMatch(/\[data-density="comfortable"\],\s*\[data-density="comfy"\]/);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('type breathes more gently than boxes at both ends', () => {
|
|
130
|
+
const compact = declsFor(css, '[data-density="compact"]');
|
|
131
|
+
const comfortable = declsFor(css, '[data-density="comfortable"]');
|
|
132
|
+
|
|
133
|
+
const cDensity = Number(compact.get('--kj-density'));
|
|
134
|
+
const cType = Number(compact.get('--kj-type-scale'));
|
|
135
|
+
const fDensity = Number(comfortable.get('--kj-density'));
|
|
136
|
+
const fType = Number(comfortable.get('--kj-type-scale'));
|
|
137
|
+
|
|
138
|
+
// An 0.85 squeeze that flatters padding is punishing on 12px text, so the
|
|
139
|
+
// type scalar must always sit closer to 1 than the box scalar.
|
|
140
|
+
expect(1 - cType).toBeLessThan(1 - cDensity);
|
|
141
|
+
expect(fType - 1).toBeLessThan(fDensity - 1);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
});
|
package/src/index.css
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
@import './base.css';
|
|
2
|
+
@import './density.css';
|
|
2
3
|
@import './themes/dark.css';
|
|
3
4
|
@import './themes/light.css';
|
|
4
5
|
@import './themes/kouji.css';
|
|
@@ -12,3 +13,5 @@
|
|
|
12
13
|
@import './themes/forest.css';
|
|
13
14
|
@import './themes/nord.css';
|
|
14
15
|
@import './themes/terminal.css';
|
|
16
|
+
@import './themes/orrery.css';
|
|
17
|
+
@import './themes/orrery-light.css';
|
package/src/themes/bauhaus.css
CHANGED
|
@@ -84,5 +84,12 @@
|
|
|
84
84
|
--kj-shadow-focus: 0 0 0 3px #1d3aff;
|
|
85
85
|
|
|
86
86
|
--kj-button-bg-hover: #8e0f1d;
|
|
87
|
+
/* ── chart palette ── */
|
|
88
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
89
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
90
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
91
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
92
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
93
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
87
94
|
}
|
|
88
95
|
}
|
package/src/themes/corporate.css
CHANGED
|
@@ -87,5 +87,12 @@
|
|
|
87
87
|
/* 8% darken on #0a2540 is invisible; lift to #15355a so the hover
|
|
88
88
|
reads against the deep navy primary. */
|
|
89
89
|
--kj-button-bg-hover: #15355a;
|
|
90
|
+
/* ── chart palette ── */
|
|
91
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
92
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
93
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
94
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
95
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
96
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
90
97
|
}
|
|
91
98
|
}
|
package/src/themes/cyberpunk.css
CHANGED
|
@@ -78,5 +78,12 @@
|
|
|
78
78
|
--kj-shadow-md: 4px 4px 0 #0a0a0a;
|
|
79
79
|
--kj-shadow-lg: 8px 8px 0 #0a0a0a;
|
|
80
80
|
--kj-shadow-focus: 0 0 0 3px #ff007f;
|
|
81
|
+
/* ── chart palette ── */
|
|
82
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
83
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
84
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
85
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
86
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
87
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
81
88
|
}
|
|
82
89
|
}
|
package/src/themes/dark.css
CHANGED
|
@@ -87,5 +87,12 @@
|
|
|
87
87
|
--kj-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
|
|
88
88
|
--kj-shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.6);
|
|
89
89
|
--kj-shadow-focus: 0 0 0 3px rgba(43, 98, 219, 0.5);
|
|
90
|
+
/* ── chart palette ── */
|
|
91
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
92
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
93
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
94
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
95
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
96
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
90
97
|
}
|
|
91
98
|
}
|
package/src/themes/dune.css
CHANGED
|
@@ -81,5 +81,12 @@
|
|
|
81
81
|
/* Indigo deepens on hover; fg stays cream to match the desert tone
|
|
82
82
|
(already the default fg-on-primary, so no fg-hover needed). */
|
|
83
83
|
--kj-button-bg-hover: #281a48;
|
|
84
|
+
/* ── chart palette ── */
|
|
85
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
86
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
87
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
88
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
89
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
90
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
84
91
|
}
|
|
85
92
|
}
|
package/src/themes/forest.css
CHANGED
|
@@ -83,5 +83,12 @@
|
|
|
83
83
|
/* Mustard gold brightens on hover (8% black-mix would push it duller
|
|
84
84
|
on a dark theme — we want it more luminous against the moss bg). */
|
|
85
85
|
--kj-button-bg-hover: #e8b22a;
|
|
86
|
+
/* ── chart palette ── */
|
|
87
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
88
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
89
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
90
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
91
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
92
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
86
93
|
}
|
|
87
94
|
}
|
package/src/themes/kouji.css
CHANGED
|
@@ -98,6 +98,13 @@
|
|
|
98
98
|
--kj-shadow-md: 0 0 0 1px #1a1a1a;
|
|
99
99
|
--kj-shadow-lg: 0 0 0 2px #1a1a1a;
|
|
100
100
|
--kj-shadow-focus: 0 0 0 2px #c4ff3d;
|
|
101
|
+
/* ── chart palette ── */
|
|
102
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
103
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
104
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
105
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
106
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
107
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
110
|
|
package/src/themes/light.css
CHANGED
|
@@ -93,5 +93,12 @@
|
|
|
93
93
|
/* 8% darken against #1a1a1a is nearly imperceptible; lift toward
|
|
94
94
|
#3a3a3a so the hover reads as a deliberate state change. */
|
|
95
95
|
--kj-button-bg-hover: #3a3a3a;
|
|
96
|
+
/* ── chart palette ── */
|
|
97
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
98
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
99
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
100
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
101
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
102
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
96
103
|
}
|
|
97
104
|
}
|
package/src/themes/mint.css
CHANGED
|
@@ -95,5 +95,12 @@
|
|
|
95
95
|
/* Deepen the spearmint on hover (~10% darker) so the interaction
|
|
96
96
|
reads on the bright body. */
|
|
97
97
|
--kj-button-bg-hover: #035a42;
|
|
98
|
+
/* ── chart palette ── */
|
|
99
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
100
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
101
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
102
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
103
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
104
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
98
105
|
}
|
|
99
106
|
}
|
package/src/themes/nord.css
CHANGED
|
@@ -81,5 +81,12 @@
|
|
|
81
81
|
/* Brighten frost teal on hover (dark themes need luminosity lift,
|
|
82
82
|
not the default 8% black-mix darken). */
|
|
83
83
|
--kj-button-bg-hover: #a3d4e2;
|
|
84
|
+
/* ── chart palette ── */
|
|
85
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
86
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
87
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
88
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
89
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
90
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
84
91
|
}
|
|
85
92
|
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────────────────────
|
|
2
|
+
orrery-light theme — shared layer
|
|
3
|
+
"Paper": One Light's structure and soft ink, shifted down into real grey.
|
|
4
|
+
Pure neutral (chroma 0.0000). Elevation goes DOWN, not up — the editor is
|
|
5
|
+
the single brightest surface and everything else recedes, and `elevated`
|
|
6
|
+
is capped short of white so popovers never glare.
|
|
7
|
+
──────────────────────────────────────────────────────────── */
|
|
8
|
+
|
|
9
|
+
@layer kj.shared {
|
|
10
|
+
[data-theme="orrery-light"] {
|
|
11
|
+
/* ── shape ── */
|
|
12
|
+
--kj-radius-box: 0.5rem;
|
|
13
|
+
--kj-radius-box-lg: 0.75rem;
|
|
14
|
+
--kj-radius-field: 0.3125rem;
|
|
15
|
+
--kj-radius-selector: 0.3125rem;
|
|
16
|
+
--kj-border: var(--kj-base-border-1);
|
|
17
|
+
--kj-depth: 1;
|
|
18
|
+
|
|
19
|
+
/* ── type ── */
|
|
20
|
+
--kj-font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
21
|
+
--kj-font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
|
|
22
|
+
--kj-font-display: var(--kj-font-sans);
|
|
23
|
+
--kj-display-weight: 600;
|
|
24
|
+
--kj-letter-spacing: -0.01em;
|
|
25
|
+
|
|
26
|
+
/* ── motion ── */
|
|
27
|
+
--kj-transition: var(--kj-base-transition-fast);
|
|
28
|
+
|
|
29
|
+
/* ── neutral surfaces ── */
|
|
30
|
+
--kj-bg-body: #dedede;
|
|
31
|
+
--kj-bg-surface: #e8e8e8;
|
|
32
|
+
--kj-bg-field: #e4e4e4;
|
|
33
|
+
--kj-bg-elevated: #f7f7f7;
|
|
34
|
+
--kj-bg-overlay: rgba(30, 30, 30, 0.34);
|
|
35
|
+
--kj-bg-inverse: #1d1e20;
|
|
36
|
+
--kj-bg-disabled: #e4e4e4;
|
|
37
|
+
|
|
38
|
+
/* ── intent surfaces ──
|
|
39
|
+
One Light's own syntax palette fails AA on light (#50a14f = 2.86:1,
|
|
40
|
+
#4078f2 = 3.62:1), so these keep its muted character while clearing
|
|
41
|
+
4.6:1. They are dark enough to carry white ink. */
|
|
42
|
+
--kj-bg-primary: #752cb3;
|
|
43
|
+
--kj-bg-primary-subtle: color-mix(in oklch, #752cb3 12%, #dedede);
|
|
44
|
+
--kj-bg-accent: #752cb3;
|
|
45
|
+
--kj-bg-accent-subtle: color-mix(in oklch, #752cb3 12%, #dedede);
|
|
46
|
+
|
|
47
|
+
--kj-bg-info: #1c6dc8;
|
|
48
|
+
--kj-bg-info-subtle: color-mix(in oklch, #1c6dc8 12%, #dedede);
|
|
49
|
+
--kj-bg-success: #1e7d3e;
|
|
50
|
+
--kj-bg-success-subtle: color-mix(in oklch, #1e7d3e 12%, #dedede);
|
|
51
|
+
--kj-bg-warning: #996100;
|
|
52
|
+
--kj-bg-warning-subtle: color-mix(in oklch, #996100 12%, #dedede);
|
|
53
|
+
--kj-bg-danger: #bf4240;
|
|
54
|
+
--kj-bg-danger-subtle: color-mix(in oklch, #bf4240 12%, #dedede);
|
|
55
|
+
|
|
56
|
+
/* ── fg class A — soft foreground, not near-black (~10:1, not 16:1) ── */
|
|
57
|
+
--kj-fg-default: #3b3b3b; /* 10.0:1 */
|
|
58
|
+
--kj-fg-muted: #515151; /* 7.1:1 */
|
|
59
|
+
--kj-fg-subtle: #6e6e6e; /* 4.6:1 */
|
|
60
|
+
--kj-fg-disabled: #8c8c8c; /* 3.0:1 — non-text / disabled only */
|
|
61
|
+
|
|
62
|
+
/* ── fg class B — every intent fill here is dark enough for white ink,
|
|
63
|
+
which is the inverse of the dark theme's pastel fills. ── */
|
|
64
|
+
--kj-fg-on-primary: #ffffff;
|
|
65
|
+
--kj-fg-on-accent: #ffffff;
|
|
66
|
+
--kj-fg-on-info: #ffffff;
|
|
67
|
+
--kj-fg-on-success: #ffffff;
|
|
68
|
+
--kj-fg-on-warning: #ffffff;
|
|
69
|
+
--kj-fg-on-danger: #ffffff;
|
|
70
|
+
--kj-fg-on-inverse: #dee0e2;
|
|
71
|
+
|
|
72
|
+
/* ── fg class C — intent as text on the body ── */
|
|
73
|
+
--kj-fg-primary: #8d4dcc; /* 4.6:1 */
|
|
74
|
+
--kj-fg-accent: #8d4dcc;
|
|
75
|
+
--kj-fg-info: #1c6dc8;
|
|
76
|
+
--kj-fg-success: #1e7d3e;
|
|
77
|
+
--kj-fg-warning: #996100;
|
|
78
|
+
--kj-fg-danger: #bf4240;
|
|
79
|
+
|
|
80
|
+
/* ── borders ── */
|
|
81
|
+
--kj-border-default: #d1d1d1;
|
|
82
|
+
--kj-border-muted: #e4e4e4;
|
|
83
|
+
--kj-border-strong: #bababa;
|
|
84
|
+
--kj-border-focus: #8d4dcc;
|
|
85
|
+
--kj-border-disabled: #d1d1d1;
|
|
86
|
+
--kj-border-primary: #8d4dcc;
|
|
87
|
+
--kj-border-danger: #bf4240;
|
|
88
|
+
|
|
89
|
+
/* ── shadows — shorter and weaker than dark; light elevation recedes ── */
|
|
90
|
+
--kj-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.12);
|
|
91
|
+
--kj-shadow-md: 0 6px 18px -10px rgba(0, 0, 0, 0.28);
|
|
92
|
+
--kj-shadow-lg: 0 14px 32px -12px rgba(0, 0, 0, 0.34);
|
|
93
|
+
--kj-shadow-focus: 0 0 0 3px color-mix(in oklch, #8d4dcc, transparent 80%);
|
|
94
|
+
|
|
95
|
+
/* ── chart palette — lane identity, darkened for the paper ground ── */
|
|
96
|
+
--kj-chart-1: #6b53b8;
|
|
97
|
+
--kj-chart-2: #3f6d96;
|
|
98
|
+
--kj-chart-3: #3f8664;
|
|
99
|
+
--kj-chart-4: #9a7530;
|
|
100
|
+
--kj-chart-5: #96566c;
|
|
101
|
+
--kj-chart-6: #4d6da2;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────────────────────
|
|
2
|
+
orrery theme — shared layer
|
|
3
|
+
Graphite: a dense IDE palette. Chroma is held flat at ~0.005 OKLCH
|
|
4
|
+
across the whole neutral ramp — elevation is a lightness step plus a
|
|
5
|
+
hairline, never a hue shift. The single violet accent carries meaning;
|
|
6
|
+
everything else stays grey or semantic.
|
|
7
|
+
──────────────────────────────────────────────────────────── */
|
|
8
|
+
|
|
9
|
+
@layer kj.shared {
|
|
10
|
+
[data-theme="orrery"] {
|
|
11
|
+
/* ── shape ── */
|
|
12
|
+
--kj-radius-box: 0.5rem;
|
|
13
|
+
--kj-radius-box-lg: 0.75rem;
|
|
14
|
+
--kj-radius-field: 0.3125rem;
|
|
15
|
+
--kj-radius-selector: 0.3125rem;
|
|
16
|
+
--kj-border: var(--kj-base-border-1);
|
|
17
|
+
--kj-depth: 1;
|
|
18
|
+
|
|
19
|
+
/* ── type — Inter for chrome, JetBrains Mono for code, paths, shas and
|
|
20
|
+
figures. Display is sans: an IDE has no headline face. ── */
|
|
21
|
+
--kj-font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
|
|
22
|
+
--kj-font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;
|
|
23
|
+
--kj-font-display: var(--kj-font-sans);
|
|
24
|
+
--kj-display-weight: 600;
|
|
25
|
+
--kj-letter-spacing: -0.01em;
|
|
26
|
+
|
|
27
|
+
/* ── motion ── */
|
|
28
|
+
--kj-transition: var(--kj-base-transition-fast);
|
|
29
|
+
|
|
30
|
+
/* ── neutral surfaces — the graphite ramp ── */
|
|
31
|
+
--kj-bg-body: #121315;
|
|
32
|
+
--kj-bg-surface: #17181a;
|
|
33
|
+
--kj-bg-field: #232427;
|
|
34
|
+
--kj-bg-elevated: #2c2d30;
|
|
35
|
+
--kj-bg-overlay: rgba(4, 5, 9, 0.58);
|
|
36
|
+
--kj-bg-inverse: #f2f2f2;
|
|
37
|
+
--kj-bg-disabled: #232427;
|
|
38
|
+
|
|
39
|
+
/* ── intent surfaces ──
|
|
40
|
+
Accent aliases primary: graphite is a single-hue system. The `-subtle`
|
|
41
|
+
fills are mixed INTO the body rather than made translucent, so a subtle
|
|
42
|
+
surface stays opaque over any parent. */
|
|
43
|
+
--kj-bg-primary: #b082f7;
|
|
44
|
+
--kj-bg-primary-subtle: color-mix(in oklch, #b082f7 14%, #121315);
|
|
45
|
+
--kj-bg-accent: #b082f7;
|
|
46
|
+
--kj-bg-accent-subtle: color-mix(in oklch, #b082f7 14%, #121315);
|
|
47
|
+
|
|
48
|
+
--kj-bg-info: #5e9cf5;
|
|
49
|
+
--kj-bg-info-subtle: color-mix(in oklch, #5e9cf5 14%, #121315);
|
|
50
|
+
--kj-bg-success: #57c98a;
|
|
51
|
+
--kj-bg-success-subtle: color-mix(in oklch, #57c98a 14%, #121315);
|
|
52
|
+
--kj-bg-warning: #d9a441;
|
|
53
|
+
--kj-bg-warning-subtle: color-mix(in oklch, #d9a441 14%, #121315);
|
|
54
|
+
--kj-bg-danger: #e06c7a;
|
|
55
|
+
--kj-bg-danger-subtle: color-mix(in oklch, #e06c7a 14%, #121315);
|
|
56
|
+
|
|
57
|
+
/* ── fg class A — the ink ramp, contrast-checked against bg-field ── */
|
|
58
|
+
--kj-fg-default: #dee0e2; /* 12.6:1 */
|
|
59
|
+
--kj-fg-muted: #b0b1b3; /* 7.8:1 */
|
|
60
|
+
--kj-fg-subtle: #8a8b8c; /* 4.9:1 */
|
|
61
|
+
--kj-fg-disabled: #68696b; /* 3.0:1 — non-text / disabled only */
|
|
62
|
+
|
|
63
|
+
/* ── fg class B — ink ON a solid intent fill.
|
|
64
|
+
Every intent hue here is a light pastel (they double as ink on the dark
|
|
65
|
+
body), so near-black is the only choice that clears AA on the fill —
|
|
66
|
+
white would land near 2:1 on all of them. */
|
|
67
|
+
--kj-fg-on-primary: #0d0d0f;
|
|
68
|
+
--kj-fg-on-accent: #0d0d0f;
|
|
69
|
+
--kj-fg-on-info: #0d0d0f;
|
|
70
|
+
--kj-fg-on-success: #0d0d0f;
|
|
71
|
+
--kj-fg-on-warning: #0d0d0f;
|
|
72
|
+
--kj-fg-on-danger: #0d0d0f;
|
|
73
|
+
--kj-fg-on-inverse: #3b3b3b;
|
|
74
|
+
|
|
75
|
+
/* ── fg class C — intent as text on the body ── */
|
|
76
|
+
--kj-fg-primary: #c39afc;
|
|
77
|
+
--kj-fg-accent: #c39afc;
|
|
78
|
+
--kj-fg-info: #5e9cf5;
|
|
79
|
+
--kj-fg-success: #57c98a;
|
|
80
|
+
--kj-fg-warning: #d9a441;
|
|
81
|
+
--kj-fg-danger: #e06c7a;
|
|
82
|
+
|
|
83
|
+
/* ── borders — hairlines, not boxes ── */
|
|
84
|
+
--kj-border-default: #353739;
|
|
85
|
+
--kj-border-muted: #232427;
|
|
86
|
+
--kj-border-strong: #444548;
|
|
87
|
+
--kj-border-focus: #a855f7;
|
|
88
|
+
--kj-border-disabled: #353739;
|
|
89
|
+
--kj-border-primary: #a855f7;
|
|
90
|
+
--kj-border-danger: #e06c7a;
|
|
91
|
+
|
|
92
|
+
/* ── shadows — long and soft, lifted off pure black ── */
|
|
93
|
+
--kj-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
|
|
94
|
+
--kj-shadow-md: 0 8px 24px -10px rgba(0, 0, 0, 0.65);
|
|
95
|
+
--kj-shadow-lg: 0 16px 40px -12px rgba(0, 0, 0, 0.72);
|
|
96
|
+
--kj-shadow-focus: 0 0 0 3px color-mix(in oklch, #a855f7, transparent 84%);
|
|
97
|
+
|
|
98
|
+
/* ── chart palette — the lane identity colours.
|
|
99
|
+
Series need identity, not intent: six distinguishable hues at matched
|
|
100
|
+
lightness beat six semantic colours that all mean something else. */
|
|
101
|
+
--kj-chart-1: #8f7bd6;
|
|
102
|
+
--kj-chart-2: #5e8fb8;
|
|
103
|
+
--kj-chart-3: #67a888;
|
|
104
|
+
--kj-chart-4: #c09a54;
|
|
105
|
+
--kj-chart-5: #b8798f;
|
|
106
|
+
--kj-chart-6: #6f8fc4;
|
|
107
|
+
}
|
|
108
|
+
}
|
package/src/themes/retro.css
CHANGED
|
@@ -85,5 +85,13 @@
|
|
|
85
85
|
reads better than the default ink on the deepened terracotta. */
|
|
86
86
|
--kj-button-bg-hover: #d05c57;
|
|
87
87
|
--kj-button-fg-hover: #fff5e4;
|
|
88
|
+
|
|
89
|
+
/* ── chart palette ── */
|
|
90
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
91
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
92
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
93
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
94
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
95
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
88
96
|
}
|
|
89
97
|
}
|
package/src/themes/sakura.css
CHANGED
|
@@ -81,5 +81,12 @@
|
|
|
81
81
|
/* Lift the cherry magenta to a deeper rose so the hover reads
|
|
82
82
|
against the warm body. */
|
|
83
83
|
--kj-button-bg-hover: #a01548;
|
|
84
|
+
/* ── chart palette ── */
|
|
85
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
86
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
87
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
88
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
89
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
90
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
84
91
|
}
|
|
85
92
|
}
|
package/src/themes/terminal.css
CHANGED
|
@@ -82,5 +82,12 @@
|
|
|
82
82
|
/* Dim the phosphor green on hover (slight green-down) instead of
|
|
83
83
|
black-mixing — keeps the CRT look. */
|
|
84
84
|
--kj-button-bg-hover: #00cc52;
|
|
85
|
+
/* ── chart palette ── */
|
|
86
|
+
--kj-chart-1: var(--kj-bg-primary);
|
|
87
|
+
--kj-chart-2: var(--kj-bg-accent);
|
|
88
|
+
--kj-chart-3: var(--kj-bg-success);
|
|
89
|
+
--kj-chart-4: var(--kj-bg-warning);
|
|
90
|
+
--kj-chart-5: var(--kj-bg-info, var(--kj-bg-accent-subtle));
|
|
91
|
+
--kj-chart-6: var(--kj-bg-danger);
|
|
85
92
|
}
|
|
86
93
|
}
|