@kouji-ui/themes 0.0.6

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 ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@kouji-ui/themes",
3
+ "version": "0.0.6",
4
+ "description": "Theme tokens and theme stylesheets for kouji-ui — pure CSS, swappable at runtime via data-theme.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/kouji-dev/kouji-ui.git",
9
+ "directory": "packages/themes"
10
+ },
11
+ "homepage": "https://kouji-ui.onrender.com",
12
+ "bugs": {
13
+ "url": "https://github.com/kouji-dev/kouji-ui/issues"
14
+ },
15
+ "keywords": [
16
+ "css",
17
+ "theme",
18
+ "tokens",
19
+ "design-system",
20
+ "kouji"
21
+ ],
22
+ "publishConfig": {
23
+ "access": "public",
24
+ "provenance": false
25
+ },
26
+ "sideEffects": [
27
+ "**/*.css"
28
+ ],
29
+ "files": [
30
+ "src/"
31
+ ],
32
+ "exports": {
33
+ ".": "./src/index.css",
34
+ "./base.css": "./src/base.css",
35
+ "./themes/dark.css": "./src/themes/dark.css"
36
+ },
37
+ "scripts": {
38
+ "build": "echo 'no build for css-only package'",
39
+ "test": "vitest run",
40
+ "lint": "echo 'no lint for css-only package'"
41
+ }
42
+ }
package/src/base.css ADDED
@@ -0,0 +1,165 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ @kouji-ui/themes — base layer
3
+ Raw primitives. Themes pull values from here.
4
+ Components MUST NOT read base tokens directly.
5
+ ──────────────────────────────────────────────────────────── */
6
+
7
+ @layer kj.reset, kj.base, kj.shared, kj.component;
8
+
9
+ @layer kj.reset {
10
+ /**
11
+ * Theme-scoped resets. Every `[data-theme]` block starts from these so
12
+ * nesting one theme inside another (e.g. the theme-generator preview
13
+ * stage rendered inside the docs `data-theme="kouji"` root) doesn't
14
+ * inherit brutalist defaults. Themes opt back in by declaring the var
15
+ * in `kj.shared` — kj.shared wins over kj.reset via layer ordering,
16
+ * regardless of selector specificity.
17
+ *
18
+ * Button shadow: defaults to `none`; kouji + bauhaus set their offset
19
+ * blocks in their own `[data-theme="X"]` declarations.
20
+ */
21
+ [data-theme] {
22
+ --kj-button-shadow: none;
23
+ --kj-button-shadow-hover: none;
24
+ --kj-button-shadow-active: none;
25
+ }
26
+ }
27
+
28
+ @layer kj.base {
29
+ :root {
30
+ /* ── color palette ── */
31
+ --kj-base-gray-50: oklch(98% 0 0);
32
+ --kj-base-gray-100: oklch(95% 0 0);
33
+ --kj-base-gray-200: oklch(90% 0 0);
34
+ --kj-base-gray-300: oklch(82% 0 0);
35
+ --kj-base-gray-500: oklch(60% 0 0);
36
+ --kj-base-gray-700: oklch(35% 0 0);
37
+ --kj-base-gray-800: oklch(22% 0 0);
38
+ --kj-base-gray-900: oklch(15% 0 0);
39
+ --kj-base-gray-950: oklch(8% 0 0);
40
+
41
+ --kj-base-blue-400: oklch(70% 0.16 250);
42
+ --kj-base-blue-500: oklch(62% 0.19 250);
43
+ --kj-base-blue-600: oklch(55% 0.20 250);
44
+ --kj-base-blue-700: oklch(48% 0.20 250);
45
+
46
+ --kj-base-red-400: oklch(72% 0.18 20);
47
+ --kj-base-red-500: oklch(63% 0.22 20);
48
+ --kj-base-red-600: oklch(55% 0.22 20);
49
+ --kj-base-green-500: oklch(70% 0.18 145);
50
+ --kj-base-yellow-500: oklch(83% 0.16 90);
51
+ --kj-base-amber-500: oklch(78% 0.17 60);
52
+ --kj-base-amber-600: oklch(70% 0.18 55);
53
+
54
+ /* kouji brand lime — #b8f500 */
55
+ --kj-base-lime-500: oklch(91% 0.21 124);
56
+
57
+ /* ── radii ── */
58
+ --kj-base-radius-0: 0px;
59
+ --kj-base-radius-1: 0.25rem;
60
+ --kj-base-radius-2: 0.5rem;
61
+ --kj-base-radius-3: 1rem;
62
+ --kj-base-radius-full: 9999px;
63
+
64
+ /* ── spacing — semantic scale (canonical names) ── */
65
+ --kj-base-space-0: 0;
66
+ --kj-base-space-xs: 0.25rem; /* 4px */
67
+ --kj-base-space-sm: 0.5rem; /* 8px */
68
+ --kj-base-space-md: 0.75rem; /* 12px */
69
+ --kj-base-space-lg: 1rem; /* 16px */
70
+ --kj-base-space-xl: 1.5rem; /* 24px */
71
+ --kj-base-space-2xl: 2rem; /* 32px */
72
+ --kj-base-space-3xl: 3rem; /* 48px */
73
+ --kj-base-space-4xl: 4rem; /* 64px */
74
+ --kj-base-space-5xl: 6rem; /* 96px */
75
+ --kj-base-space-6xl: 8rem; /* 128px */
76
+
77
+ /* ── type ── */
78
+ /* Base font families. Themes alias their --kj-font-{sans,mono,display}
79
+ to one of these. `font-sans` is the workhorse; `font-mono` is for
80
+ code/kbd/tabular numerics; `font-display` is the brand/headline
81
+ face (set per theme, defaults to sans). `font-serif` and
82
+ `font-block` are alternate display options used by editorial /
83
+ brutalist themes (paper/sakura/retro use serif; bauhaus uses block). */
84
+ --kj-base-font-sans: 'Space Grotesk', system-ui, -apple-system, sans-serif;
85
+ --kj-base-font-mono: 'JetBrains Mono', 'Fira Code', monospace;
86
+ --kj-base-font-display: 'Syne', system-ui, sans-serif;
87
+ --kj-base-font-serif: 'DM Serif Display', 'Times New Roman', Georgia, serif;
88
+ --kj-base-font-block: 'Archivo Black', system-ui, sans-serif;
89
+ --kj-base-text-xs: 0.75rem;
90
+ --kj-base-text-sm: 0.875rem;
91
+ --kj-base-text-base: 1rem;
92
+ --kj-base-text-lg: 1.125rem;
93
+ --kj-base-text-xl: 1.25rem;
94
+ --kj-base-text-2xl: 1.5rem;
95
+
96
+ /* ── Semantic defaults (inherited by every theme) ─────────────────
97
+ Themes only redeclare these when they need to differ. The contract
98
+ spec no longer requires per-theme declarations.
99
+
100
+ font-display defaults to sans — the safer, brand-neutral choice.
101
+ Themes that want a real display face (kouji/dark/retro/bauhaus/
102
+ nord → Syne; cyberpunk/terminal → mono) override. */
103
+ --kj-font-sans: var(--kj-base-font-sans);
104
+ --kj-font-mono: var(--kj-base-font-mono);
105
+ --kj-font-display: var(--kj-base-font-sans);
106
+
107
+ --kj-text-xs: var(--kj-base-text-xs);
108
+ --kj-text-sm: var(--kj-base-text-sm);
109
+ --kj-text-base: var(--kj-base-text-base);
110
+ --kj-text-lg: var(--kj-base-text-lg);
111
+ --kj-text-xl: var(--kj-base-text-xl);
112
+ --kj-text-2xl: var(--kj-base-text-2xl);
113
+
114
+ --kj-space-xs: var(--kj-base-space-xs);
115
+ --kj-space-sm: var(--kj-base-space-sm);
116
+ --kj-space-md: var(--kj-base-space-md);
117
+ --kj-space-lg: var(--kj-base-space-lg);
118
+ --kj-space-xl: var(--kj-base-space-xl);
119
+ --kj-space-2xl: var(--kj-base-space-2xl);
120
+ --kj-space-3xl: var(--kj-base-space-3xl);
121
+ --kj-space-4xl: var(--kj-base-space-4xl);
122
+ --kj-space-5xl: var(--kj-base-space-5xl);
123
+ --kj-space-6xl: var(--kj-base-space-6xl);
124
+
125
+ /* ── borders & motion ── */
126
+ --kj-base-border-1: 1px;
127
+ --kj-base-border-2: 2px;
128
+ --kj-base-transition-fast: 0.12s ease;
129
+ --kj-base-transition-base: 0.2s ease;
130
+
131
+ /* ── Display-tone primitives (per-theme overridable, sane defaults)
132
+ Themes only redeclare when their identity calls for it (e.g. retro
133
+ wants italic display; bauhaus wants extra-heavy weight; sakura
134
+ wants light + tighter tracking). Components read these from the
135
+ resolved `--kj-display-*` cascade, not directly from base. */
136
+ --kj-display-weight: 600;
137
+ --kj-display-italic: normal;
138
+ --kj-letter-spacing: -0.02em;
139
+ --kj-hover-translate: -2px;
140
+
141
+ /* Companion radius for box-level chrome (cards, panels, dialogs).
142
+ Distinct from --kj-radius-box so a theme can have small box radius
143
+ (`box`) and a larger hero radius (`box-lg`). Defaults to box. */
144
+ --kj-radius-box-lg: var(--kj-base-radius-3);
145
+
146
+ /* ── Icon tokens ────────────────────────────────────────────
147
+ Map [kjIconColor] semantic tokens to the existing --kj-fg-*
148
+ palette so colored icons inherit theme tone. [kjIconSize]
149
+ resolves to em-relative steps so icons scale with surrounding
150
+ text by default. Themes can override any of these to pin a
151
+ brand-specific icon palette. */
152
+ --kj-color-icon-muted: var(--kj-fg-muted);
153
+ --kj-color-icon-primary: var(--kj-fg-primary);
154
+ --kj-color-icon-success: var(--kj-fg-success);
155
+ --kj-color-icon-warning: var(--kj-fg-warning);
156
+ --kj-color-icon-danger: var(--kj-fg-danger);
157
+ --kj-color-icon-info: var(--kj-fg-info);
158
+
159
+ --kj-icon-size-xs: 0.75em;
160
+ --kj-icon-size-sm: 0.875em;
161
+ --kj-icon-size-md: 1em;
162
+ --kj-icon-size-lg: 1.25em;
163
+ --kj-icon-size-xl: 1.5em;
164
+ }
165
+ }
package/src/index.css ADDED
@@ -0,0 +1,14 @@
1
+ @import './base.css';
2
+ @import './themes/dark.css';
3
+ @import './themes/light.css';
4
+ @import './themes/kouji.css';
5
+ @import './themes/retro.css';
6
+ @import './themes/cyberpunk.css';
7
+ @import './themes/corporate.css';
8
+ @import './themes/sakura.css';
9
+ @import './themes/bauhaus.css';
10
+ @import './themes/dune.css';
11
+ @import './themes/mint.css';
12
+ @import './themes/forest.css';
13
+ @import './themes/nord.css';
14
+ @import './themes/terminal.css';
@@ -0,0 +1,88 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ bauhaus theme — light
3
+ Primary blocks of red, blue, and yellow on warm cream. Sharp
4
+ geometry, no rounding, thick borders. Hard offset shadows
5
+ instead of soft drop-shadows (neo-brutalist signature).
6
+ ──────────────────────────────────────────────────────────── */
7
+
8
+ @layer kj.shared {
9
+ [data-theme="bauhaus"] {
10
+ /* ── shape — sharp, geometric ── */
11
+ --kj-radius-box: var(--kj-base-radius-0);
12
+ --kj-radius-field: var(--kj-base-radius-0);
13
+ --kj-radius-selector: var(--kj-base-radius-0);
14
+ --kj-border: var(--kj-base-border-2);
15
+ --kj-depth: 0;
16
+ /* ── type — Archivo Black for display (constructivist block letters).
17
+ Heaviest weight, tight tracking, deeper hover lift for the
18
+ neo-brutalist offset-shadow motif. */
19
+ --kj-font-display: var(--kj-base-font-block);
20
+ --kj-display-weight: 900;
21
+ --kj-letter-spacing: -0.04em;
22
+ --kj-hover-translate: -4px;
23
+
24
+ /* ── motion ── */
25
+ --kj-transition: var(--kj-base-transition-fast);
26
+
27
+ --kj-bg-body: #f5efe1;
28
+ --kj-bg-surface: #fffaef;
29
+ --kj-bg-field: #efe7d4;
30
+ --kj-bg-elevated: #ffffff;
31
+ --kj-bg-overlay: rgba(26, 26, 26, 0.55);
32
+ --kj-bg-inverse: #1a1a1a;
33
+ --kj-bg-disabled: #e8e0cc;
34
+
35
+ /* Iconic Bauhaus primaries, darkened only as needed to clear AA when
36
+ used as text-on-fill. The red is the iconic note; blue holds the
37
+ accent slot; yellow is reserved for warning (with black text). */
38
+ --kj-bg-primary: #b81728;
39
+ --kj-bg-primary-subtle: #fcd9dd;
40
+ --kj-bg-accent: #1d3aff;
41
+ --kj-bg-accent-subtle: #d8dcff;
42
+
43
+ --kj-bg-info: #1d3aff;
44
+ --kj-bg-info-subtle: #d8dcff;
45
+ --kj-bg-success: #1a7a3d;
46
+ --kj-bg-success-subtle: #cde6d4;
47
+ --kj-bg-warning: #f4c20d;
48
+ --kj-bg-warning-subtle: #fcefb8;
49
+ --kj-bg-danger: #b81728;
50
+ --kj-bg-danger-subtle: #fcd9dd;
51
+
52
+ --kj-fg-default: #1a1a1a;
53
+ --kj-fg-muted: #3a3a3a;
54
+ --kj-fg-subtle: #5a5a5a;
55
+ --kj-fg-disabled: #b8b0a0;
56
+
57
+ --kj-fg-on-primary: #ffffff;
58
+ --kj-fg-on-accent: #ffffff;
59
+ --kj-fg-on-info: #ffffff;
60
+ --kj-fg-on-success: #ffffff;
61
+ --kj-fg-on-warning: #1a1a1a;
62
+ --kj-fg-on-danger: #ffffff;
63
+ --kj-fg-on-inverse: #f5efe1;
64
+
65
+ --kj-fg-primary: #b81728;
66
+ --kj-fg-accent: #1d3aff;
67
+ --kj-fg-info: #1d3aff;
68
+ --kj-fg-success: #156033;
69
+ --kj-fg-warning: #6b4a00;
70
+ --kj-fg-danger: #b81728;
71
+
72
+ --kj-border-default: #1a1a1a;
73
+ --kj-border-muted: #4a4a4a;
74
+ --kj-border-strong: #1a1a1a;
75
+ --kj-border-focus: #1d3aff;
76
+ --kj-border-disabled: #b8b0a0;
77
+ --kj-border-primary: #b81728;
78
+ --kj-border-danger: #b81728;
79
+
80
+ /* Hard offset shadow — neo-brutalist signature. No blur. */
81
+ --kj-shadow-sm: 2px 2px 0 #1a1a1a;
82
+ --kj-shadow-md: 4px 4px 0 #1a1a1a;
83
+ --kj-shadow-lg: 8px 8px 0 #1a1a1a;
84
+ --kj-shadow-focus: 0 0 0 3px #1d3aff;
85
+
86
+ --kj-button-bg-hover: #8e0f1d;
87
+ }
88
+ }
@@ -0,0 +1,91 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ corporate theme — "Navy (banking)"
3
+ Institutional / banking feel: cool off-white surfaces, deep
4
+ navy as a single signature hue (primary === accent === info).
5
+ Subdued intent colors (forest/oxblood/dark amber) and sharp
6
+ small-radius geometry. Restrained shadows.
7
+ ──────────────────────────────────────────────────────────── */
8
+
9
+ @layer kj.shared {
10
+ [data-theme="corporate"] {
11
+ /* ── shape — sharp, institutional ── */
12
+ --kj-radius-box: var(--kj-base-radius-1);
13
+ --kj-radius-field: var(--kj-base-radius-1);
14
+ --kj-radius-selector: var(--kj-base-radius-1);
15
+ --kj-border: var(--kj-base-border-1);
16
+ --kj-depth: 1;
17
+
18
+ /* ── type — sans display (banking ≠ decorative). Tighter tracking
19
+ than the default for confident corporate headlines. */
20
+ --kj-display-weight: 600;
21
+ --kj-letter-spacing: -0.035em;
22
+
23
+ /* ── motion ── */
24
+ --kj-transition: var(--kj-base-transition-fast);
25
+
26
+ --kj-bg-body: #f5f7fa;
27
+ --kj-bg-surface: #ffffff;
28
+ --kj-bg-field: #eef1f5;
29
+ --kj-bg-elevated: #ffffff;
30
+ --kj-bg-overlay: rgba(10, 37, 64, 0.55);
31
+ --kj-bg-inverse: #0a2540;
32
+ --kj-bg-disabled: #dde2ea;
33
+
34
+ /* Single signature navy. primary === accent === info on purpose —
35
+ this is the banking-mono identity. Intent colors stay subdued
36
+ (forest, oxblood, dark amber) so the navy reads as the only
37
+ confident hue in the palette. */
38
+ --kj-bg-primary: #0a2540;
39
+ --kj-bg-primary-subtle: #dce4f0;
40
+ --kj-bg-accent: #0a2540;
41
+ --kj-bg-accent-subtle: #dce4f0;
42
+
43
+ --kj-bg-info: #0a2540;
44
+ --kj-bg-info-subtle: #dce4f0;
45
+ --kj-bg-success: #15543d;
46
+ --kj-bg-success-subtle: #d9eae0;
47
+ --kj-bg-warning: #a05a00;
48
+ --kj-bg-warning-subtle: #f6e2c5;
49
+ --kj-bg-danger: #8b1a1a;
50
+ --kj-bg-danger-subtle: #f0d4d4;
51
+
52
+ --kj-fg-default: #0a2540;
53
+ --kj-fg-muted: #2d3e54;
54
+ --kj-fg-subtle: #4a5568;
55
+ --kj-fg-disabled: #aebbcb;
56
+
57
+ --kj-fg-on-primary: #ffffff;
58
+ --kj-fg-on-accent: #ffffff;
59
+ --kj-fg-on-info: #ffffff;
60
+ --kj-fg-on-success: #ffffff;
61
+ --kj-fg-on-warning: #ffffff;
62
+ --kj-fg-on-danger: #ffffff;
63
+ --kj-fg-on-inverse: #ffffff;
64
+
65
+ /* fg-warning darkened so warning-tinted text passes AA on bg-body. */
66
+ --kj-fg-primary: #0a2540;
67
+ --kj-fg-accent: #0a2540;
68
+ --kj-fg-info: #0a2540;
69
+ --kj-fg-success: #15543d;
70
+ --kj-fg-warning: #804600;
71
+ --kj-fg-danger: #7a1414;
72
+
73
+ --kj-border-default: #d8dee5;
74
+ --kj-border-muted: #e6ebf0;
75
+ --kj-border-strong: #b0bac5;
76
+ --kj-border-focus: #0a2540;
77
+ --kj-border-disabled: #dde2ea;
78
+ --kj-border-primary: #0a2540;
79
+ --kj-border-danger: #8b1a1a;
80
+
81
+ /* Restrained shadows — banking doesn't float. */
82
+ --kj-shadow-sm: 0 1px 2px rgba(10, 37, 64, 0.06);
83
+ --kj-shadow-md: 0 4px 10px rgba(10, 37, 64, 0.09);
84
+ --kj-shadow-lg: 0 12px 28px rgba(10, 37, 64, 0.14);
85
+ --kj-shadow-focus: 0 0 0 3px rgba(10, 37, 64, 0.30);
86
+
87
+ /* 8% darken on #0a2540 is invisible; lift to #15355a so the hover
88
+ reads against the deep navy primary. */
89
+ --kj-button-bg-hover: #15355a;
90
+ }
91
+ }
@@ -0,0 +1,82 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ cyberpunk theme — shared layer
3
+ Hot yellow on near-black, magenta + cyan accents, hard edges.
4
+ ──────────────────────────────────────────────────────────── */
5
+
6
+ @layer kj.shared {
7
+ [data-theme="cyberpunk"] {
8
+ /* ── shape — sharp, no rounding ── */
9
+ --kj-radius-box: var(--kj-base-radius-0);
10
+ --kj-radius-field: var(--kj-base-radius-0);
11
+ --kj-radius-selector: var(--kj-base-radius-0);
12
+ --kj-border: var(--kj-base-border-2);
13
+ --kj-depth: 0;
14
+
15
+ /* ── type — mono everywhere. Heavy weight + tight tracking gives
16
+ the headlines an aggressive techno-poster feel. */
17
+ --kj-font-sans: var(--kj-base-font-mono);
18
+ --kj-font-display: var(--kj-base-font-mono);
19
+ --kj-display-weight: 800;
20
+ --kj-letter-spacing: -0.04em;
21
+ /* ── motion ── */
22
+ --kj-transition: var(--kj-base-transition-fast);
23
+
24
+ --kj-bg-body: #ffee00;
25
+ --kj-bg-surface: #f0d808;
26
+ --kj-bg-field: #f8e604;
27
+ --kj-bg-elevated: #fff84e;
28
+ --kj-bg-overlay: rgba(10, 10, 10, 0.7);
29
+ --kj-bg-inverse: #0a0a0a;
30
+ --kj-bg-disabled: #d6c008;
31
+
32
+ --kj-bg-primary: #ff007f;
33
+ --kj-bg-primary-subtle: #ffd1e6;
34
+ --kj-bg-accent: #4d00b8;
35
+ --kj-bg-accent-subtle: #d8c4f2;
36
+
37
+ --kj-bg-info: #00f0ff;
38
+ --kj-bg-info-subtle: #c4f8fb;
39
+ --kj-bg-success: #39ff14;
40
+ --kj-bg-success-subtle: #d4f8ce;
41
+ --kj-bg-warning: #ff8c00;
42
+ --kj-bg-warning-subtle: #ffe1c4;
43
+ --kj-bg-danger: #ff0040;
44
+ --kj-bg-danger-subtle: #ffd2dc;
45
+
46
+ --kj-fg-default: #0a0a0a;
47
+ --kj-fg-muted: #1a1a1a;
48
+ --kj-fg-subtle: #3a3a3a;
49
+ --kj-fg-disabled: #8a8000;
50
+
51
+ /* Yellow on hot-pink/red fails AA (3.14:1); swap to near-black on
52
+ primary + danger. Accent stays yellow (8.71:1 on deep violet). */
53
+ --kj-fg-on-primary: #0a0a0a;
54
+ --kj-fg-on-accent: #ffee00;
55
+ --kj-fg-on-info: #0a0a0a;
56
+ --kj-fg-on-success: #0a0a0a;
57
+ --kj-fg-on-warning: #0a0a0a;
58
+ --kj-fg-on-danger: #0a0a0a;
59
+ --kj-fg-on-inverse: #ffee00;
60
+
61
+ /* fg.primary must meet AA on yellow body — pink darkened from #ff007f */
62
+ --kj-fg-primary: #8c003f;
63
+ --kj-fg-accent: #2a0066;
64
+ --kj-fg-info: #006670;
65
+ --kj-fg-success: #1a7a08;
66
+ --kj-fg-warning: #6b3a00;
67
+ --kj-fg-danger: #8c0024;
68
+
69
+ --kj-border-default: #0a0a0a;
70
+ --kj-border-muted: #d6c008;
71
+ --kj-border-strong: #0a0a0a;
72
+ --kj-border-focus: #ff007f;
73
+ --kj-border-disabled: #d6c008;
74
+ --kj-border-primary: #ff007f;
75
+ --kj-border-danger: #ff0040;
76
+
77
+ --kj-shadow-sm: 2px 2px 0 #0a0a0a;
78
+ --kj-shadow-md: 4px 4px 0 #0a0a0a;
79
+ --kj-shadow-lg: 8px 8px 0 #0a0a0a;
80
+ --kj-shadow-focus: 0 0 0 3px #ff007f;
81
+ }
82
+ }
@@ -0,0 +1,91 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ dark theme — shared layer
3
+ Sets every shared-layer token from the contract.
4
+ ──────────────────────────────────────────────────────────── */
5
+
6
+ @layer kj.shared {
7
+ [data-theme="dark"] {
8
+ /* ── shape ── */
9
+ --kj-radius-box: var(--kj-base-radius-2);
10
+ --kj-radius-field: var(--kj-base-radius-1);
11
+ --kj-radius-selector: var(--kj-base-radius-1);
12
+ --kj-border: var(--kj-base-border-1);
13
+ --kj-depth: 1;
14
+ /* ── type — crisp modern sans for headlines (Space Grotesk via
15
+ --kj-base-font-sans). Cobalt mono's identity is the palette, not
16
+ a decorative typeface. */
17
+ --kj-display-weight: 600;
18
+ --kj-letter-spacing: -0.04em;
19
+
20
+ /* ── motion ── */
21
+ --kj-transition: var(--kj-base-transition-fast);
22
+
23
+ /* Pure neutral charcoal. The single cobalt accent below carries the
24
+ brand colour; everything else stays grey or semantic. */
25
+ --kj-bg-body: #1a1a1a;
26
+ --kj-bg-surface: #232323;
27
+ --kj-bg-field: #232323;
28
+ --kj-bg-elevated: #383838;
29
+ --kj-bg-overlay: rgba(0, 0, 0, 0.7);
30
+ --kj-bg-inverse: var(--kj-base-gray-50);
31
+ --kj-bg-disabled: #232323;
32
+
33
+ /* "Cobalt mono" dark palette — single signature cobalt blue is reused
34
+ for primary/accent/info. Success/warning/danger remain semantically
35
+ distinct but at low chroma so the cobalt stays the hero. White text
36
+ passes AA 4.5:1 on every fill except warning, which carries dark text. */
37
+ --kj-bg-primary: #2b62db;
38
+ --kj-bg-primary-subtle: #16243d;
39
+ --kj-bg-accent: #2b62db;
40
+ --kj-bg-accent-subtle: #16243d;
41
+
42
+ --kj-bg-info: #2b62db;
43
+ --kj-bg-info-subtle: #16243d;
44
+ --kj-bg-success: #1f7a4a;
45
+ --kj-bg-success-subtle: #14271c;
46
+ --kj-bg-warning: #d59930;
47
+ --kj-bg-warning-subtle: #2a2114;
48
+ --kj-bg-danger: #c83026;
49
+ --kj-bg-danger-subtle: #2a1414;
50
+
51
+ --kj-fg-default: var(--kj-base-gray-50);
52
+ --kj-fg-muted: var(--kj-base-gray-300);
53
+ /* gray-500 (oklch 60%) renders as #808080 and only hits 4.40:1 on
54
+ bg-body; bump to oklch 65% (~#8e8e8e) so subtle labels pass AA. */
55
+ --kj-fg-subtle: oklch(65% 0 0);
56
+ --kj-fg-disabled: var(--kj-base-gray-700);
57
+
58
+ /* Synthwave palette uses #fff on deep saturated fills; only warning
59
+ (gold, lightest) keeps near-black text. */
60
+ --kj-fg-on-primary: #ffffff;
61
+ --kj-fg-on-accent: #ffffff;
62
+ --kj-fg-on-info: #ffffff;
63
+ --kj-fg-on-success: #ffffff;
64
+ --kj-fg-on-warning: var(--kj-base-gray-950);
65
+ --kj-fg-on-danger: #ffffff;
66
+ --kj-fg-on-inverse: var(--kj-base-gray-950);
67
+
68
+ /* Class C — intent as text against body. Lifted versions of bg-{intent}
69
+ so they read on the dark body. Cobalt-as-text uses a lighter sky
70
+ shade for readability. */
71
+ --kj-fg-primary: #6ea1ff;
72
+ --kj-fg-accent: #6ea1ff;
73
+ --kj-fg-info: #6ea1ff;
74
+ --kj-fg-success: #5fbf8a;
75
+ --kj-fg-warning: #e0b266;
76
+ --kj-fg-danger: #ee7d6e;
77
+
78
+ --kj-border-default: var(--kj-base-gray-700);
79
+ --kj-border-muted: var(--kj-base-gray-800);
80
+ --kj-border-strong: var(--kj-base-gray-500);
81
+ --kj-border-focus: #2b62db;
82
+ --kj-border-disabled: var(--kj-base-gray-700);
83
+ --kj-border-primary: #2b62db;
84
+ --kj-border-danger: #c83026;
85
+
86
+ --kj-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
87
+ --kj-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
88
+ --kj-shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.6);
89
+ --kj-shadow-focus: 0 0 0 3px rgba(43, 98, 219, 0.5);
90
+ }
91
+ }
@@ -0,0 +1,85 @@
1
+ /* ─────────────────────────────────────────────────────────────
2
+ dune theme — light
3
+ Desert warmth: coral cream body, terracotta surfaces, deep
4
+ indigo ink, burnt-orange accent. Earthy, hand-printed feel.
5
+ ──────────────────────────────────────────────────────────── */
6
+
7
+ @layer kj.shared {
8
+ [data-theme="dune"] {
9
+ /* ── shape — soft, hand-made ── */
10
+ --kj-radius-box: var(--kj-base-radius-2);
11
+ --kj-radius-field: var(--kj-base-radius-1);
12
+ --kj-radius-selector: var(--kj-base-radius-1);
13
+ --kj-border: var(--kj-base-border-1);
14
+ --kj-depth: 1;
15
+
16
+ /* ── type — light serif headlines on a sans body; warm hand-printed
17
+ feel without being overwrought. */
18
+ --kj-font-display: var(--kj-base-font-serif);
19
+ --kj-display-weight: 400;
20
+ --kj-letter-spacing: -0.02em;
21
+
22
+ /* ── motion ── */
23
+ --kj-transition: var(--kj-base-transition-base);
24
+
25
+ --kj-bg-body: #f5e9d6;
26
+ --kj-bg-surface: #ead4b3;
27
+ --kj-bg-field: #f0dcc0;
28
+ --kj-bg-elevated: #faf0db;
29
+ --kj-bg-overlay: rgba(42, 26, 64, 0.55);
30
+ --kj-bg-inverse: #2a1a40;
31
+ --kj-bg-disabled: #ddc5a3;
32
+
33
+ --kj-bg-primary: #3a2862;
34
+ --kj-bg-primary-subtle: #d4ccdf;
35
+ --kj-bg-accent: #a8401a;
36
+ --kj-bg-accent-subtle: #f5d8c8;
37
+
38
+ --kj-bg-info: #1e3a8a;
39
+ --kj-bg-info-subtle: #d4dcec;
40
+ --kj-bg-success: #4a6b2b;
41
+ --kj-bg-success-subtle: #dde4c8;
42
+ --kj-bg-warning: #b8841f;
43
+ --kj-bg-warning-subtle: #f5dfb8;
44
+ --kj-bg-danger: #8b1818;
45
+ --kj-bg-danger-subtle: #f3d8d4;
46
+
47
+ --kj-fg-default: #2a1a40;
48
+ --kj-fg-muted: #4a3258;
49
+ --kj-fg-subtle: #6a5278;
50
+ --kj-fg-disabled: #b8a085;
51
+
52
+ --kj-fg-on-primary: #f5e9d6;
53
+ --kj-fg-on-accent: #ffffff;
54
+ --kj-fg-on-info: #ffffff;
55
+ --kj-fg-on-success: #ffffff;
56
+ --kj-fg-on-warning: #2a1a40;
57
+ --kj-fg-on-danger: #ffffff;
58
+ --kj-fg-on-inverse: #f5e9d6;
59
+
60
+ --kj-fg-primary: #3a2862;
61
+ --kj-fg-accent: #8a3415;
62
+ --kj-fg-info: #1e3a8a;
63
+ --kj-fg-success: #4a6b2b;
64
+ --kj-fg-warning: #6b4a0e;
65
+ --kj-fg-danger: #8b1818;
66
+
67
+ --kj-border-default: #d4c2a0;
68
+ --kj-border-muted: #e0d2b8;
69
+ --kj-border-strong: #ad9468;
70
+ --kj-border-focus: #3a2862;
71
+ --kj-border-disabled: #ddc5a3;
72
+ --kj-border-primary: #3a2862;
73
+ --kj-border-danger: #8b1818;
74
+
75
+ /* Warm earth-tinted shadows. */
76
+ --kj-shadow-sm: 0 1px 3px rgba(80, 50, 20, 0.12);
77
+ --kj-shadow-md: 0 6px 16px rgba(80, 50, 20, 0.18);
78
+ --kj-shadow-lg: 0 20px 48px rgba(80, 50, 20, 0.26);
79
+ --kj-shadow-focus: 0 0 0 3px rgba(58, 40, 98, 0.35);
80
+
81
+ /* Indigo deepens on hover; fg stays cream to match the desert tone
82
+ (already the default fg-on-primary, so no fg-hover needed). */
83
+ --kj-button-bg-hover: #281a48;
84
+ }
85
+ }