bank20baht-ui 0.1.9 → 0.2.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 CHANGED
@@ -211,9 +211,10 @@ el.registry = {
211
211
 
212
212
  ## Design system — 20baht
213
213
 
214
- Ships themed as the **20baht design system**: banknote green (`#1F7A4E`), cream
215
- paper background, Bricolage Grotesque / Geist / Geist Mono, borders-over-shadows,
216
- "paper" easing. 35+ components:
214
+ Ships themed as the **20baht design system**: olive intaglio (`#5C7A33`), rose
215
+ underprint (`#A9645A`), foil gold on note paper (`#FBFAF3`), Bricolage Grotesque /
216
+ Geist / Geist Mono, borders-over-shadows, "paper" easing plus a dark theme
217
+ (`<html data-baht-theme="dark">`, OS-following by default). 35+ components:
217
218
 
218
219
  ```html
219
220
  <baht-button variant="secondary" size="sm">Cancel</baht-button>
package/dist/tokens.css CHANGED
@@ -1,6 +1,6 @@
1
1
  /* ============================================================
2
2
  bahtui design tokens — 20baht design system
3
- Banknote green · cream paper · engraved details.
3
+ Olive intaglio · rose underprint · foil gold on note paper.
4
4
 
5
5
  Every value below is a CSS custom property. Override any of
6
6
  them on :root (or any ancestor) to retheme — at build time,
@@ -11,82 +11,147 @@
11
11
  @import url("https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700&family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500;600&display=swap");
12
12
 
13
13
  :root {
14
- /* ---------- Raw scales (reference — prefer the semantic tokens below) ---------- */
15
-
16
- /* Primary banknote green */
17
- --baht-green-50: #EAF5EE;
18
- --baht-green-100: #D4ECDD;
19
- --baht-green-200: #AEDABF;
20
- --baht-green-300: #82C39E;
21
- --baht-green-400: #4FA577;
22
- --baht-green-500: #2C8C5B;
23
- --baht-green-600: #1F7A4E; /* primary */
24
- --baht-green-700: #186540;
25
- --baht-green-800: #134F33;
26
- --baht-green-900: #0D3422;
27
- --baht-green-950: #061C12;
28
-
29
- /* Cream / paper neutrals */
30
- --baht-cream-50: #FDFCF7;
31
- --baht-cream-100: #FAF6EA; /* page background */
32
- --baht-cream-200: #F2EBD6;
33
- --baht-cream-300: #E7E0CD; /* warm border */
34
- --baht-cream-400: #C9C1A8;
35
-
36
- /* Cool neutrals (on white surfaces) */
37
- --baht-gray-50: #F7F8F7;
38
- --baht-gray-100: #EEF0EE;
39
- --baht-gray-200: #E5E7E5; /* cool border */
40
- --baht-gray-300: #CFD2CF;
41
- --baht-gray-400: #9AA09B;
42
- --baht-gray-500: #6B7370;
43
- --baht-gray-600: #4A5249;
44
- --baht-gray-700: #333A33;
45
- --baht-gray-800: #1F2521;
46
- --baht-gray-900: #0E1F17; /* ink */
47
-
48
- /* Accents */
49
- --baht-gold-50: #FAF3E0;
50
- --baht-gold-400: #D9B97A;
51
- --baht-gold-500: #C9A55C; /* royal gold */
14
+ /* ---------- Raw scales (reference — prefer the semantic tokens below) ----------
15
+ Sampled from the ฿20 note: olive-green intaglio, rose underprint, foil gold.
16
+ --baht-green-* keeps its name: it is the documented override point that
17
+ banknote themes swap wholesale, and every semantic token derives from it. */
18
+
19
+ /* Primary — olive intaglio */
20
+ --baht-green-50: #EDF2E1;
21
+ --baht-green-100: #DCE7C9;
22
+ --baht-green-200: #C4D6A9;
23
+ --baht-green-300: #A9C598; /* dark-mode success / soft olive text */
24
+ --baht-green-400: #8FA85A; /* dark-mode primary */
25
+ --baht-green-500: #6E8C3F;
26
+ --baht-green-600: #5C7A33; /* primary */
27
+ --baht-green-700: #4A6229;
28
+ --baht-green-750: #3F5622; /* success ink on the light tint */
29
+ --baht-green-800: #3A4A24; /* neutral table header, ink blocks */
30
+ --baht-green-900: #2F4020; /* dark-mode neutral */
31
+ --baht-green-950: #1B2A14; /* content on green-400 */
32
+
33
+ /* aliases — --baht-green-* stays the override point (banknote themes
34
+ swap the whole scale); --baht-olive-* names the same ramp by its hue. */
35
+ --baht-olive-50: var(--baht-green-50);
36
+ --baht-olive-100: var(--baht-green-100);
37
+ --baht-olive-200: var(--baht-green-200);
38
+ --baht-olive-300: var(--baht-green-300);
39
+ --baht-olive-400: var(--baht-green-400);
40
+ --baht-olive-500: var(--baht-green-500);
41
+ --baht-olive-600: var(--baht-green-600);
42
+ --baht-olive-700: var(--baht-green-700);
43
+ --baht-olive-750: var(--baht-green-750);
44
+ --baht-olive-800: var(--baht-green-800);
45
+ --baht-olive-900: var(--baht-green-900);
46
+ --baht-olive-950: var(--baht-green-950);
47
+ /* Note paper — warm neutrals for pages and rails */
48
+ --baht-cream-50: #FEFDF8;
49
+ --baht-cream-100: #FBFAF3; /* page background (base-200) */
50
+ --baht-cream-200: #F2F0E2; /* sunken wells, rails */
51
+ --baht-cream-300: #E3E0CC; /* warm border */
52
+ --baht-cream-400: #C9C6B0;
53
+
54
+ /* Ink neutrals — warm, olive-tinted (never blue-gray on note paper) */
55
+ --baht-gray-50: #F7F6EE;
56
+ --baht-gray-100: #EFEDE0; /* row divider */
57
+ --baht-gray-200: #E3E0CC; /* border */
58
+ --baht-gray-300: #C9C6B0; /* strong border */
59
+ --baht-gray-400: #9A9C90;
60
+ --baht-gray-500: #6B7359; /* tertiary text */
61
+ --baht-gray-600: #4E5A44; /* secondary text */
62
+ --baht-gray-700: #3F4A34;
63
+ --baht-gray-800: #2F3A26;
64
+ --baht-gray-900: #22331A; /* ink (body) */
65
+
66
+ /* Secondary — rose underprint */
67
+ --baht-rose-50: #F8E7E3;
68
+ --baht-rose-100: #F0D2CB;
69
+ --baht-rose-200: #E4B6AC;
70
+ --baht-rose-300: #D9A398; /* dark-mode secondary */
71
+ --baht-rose-400: #C58274;
72
+ --baht-rose-500: #A9645A; /* secondary */
73
+ --baht-rose-600: #8E4F46;
74
+ --baht-rose-700: #75403A;
75
+ --baht-rose-800: #5A312C;
76
+ --baht-rose-900: #3A1E17; /* content on rose-300 */
77
+
78
+ /* Accent — foil gold */
79
+ --baht-gold-50: #FAF1DA;
80
+ --baht-gold-300: #E4D9A6; /* dark-mode warning ink */
81
+ --baht-gold-400: #D9B97A; /* dark-mode accent */
82
+ --baht-gold-500: #C9A55C; /* foil gold */
52
83
  --baht-gold-600: #A78640;
53
- --baht-gold-700: #7A6230; /* AA text on gold-50 (5.2:1) */
54
-
55
- --baht-red-50: #F9E5E1;
56
- --baht-red-400: #D86B5D;
57
- --baht-red-500: #C44536; /* temple red */
58
- --baht-red-600: #A33627;
59
-
84
+ --baht-gold-700: #7A5A12; /* warning ink on the light tint */
85
+ --baht-gold-900: #2E2306; /* content on gold-400 */
86
+
87
+ /* Warning — olive-yellow (reads as caution next to olive, unlike gold) */
88
+ --baht-lime-400: #CFCF7A; /* dark-mode warning */
89
+ --baht-lime-500: #B8B85E; /* warning */
90
+ --baht-lime-900: #2E2E0C; /* content on lime */
91
+
92
+ /* Error — burnt terracotta */
93
+ --baht-red-50: #F8E7E3;
94
+ --baht-red-300: #E08878; /* dark-mode error */
95
+ --baht-red-400: #C9503E;
96
+ --baht-red-500: #B03A2B; /* error */
97
+ --baht-red-600: #8E3020; /* error ink on the light tint */
98
+ --baht-red-700: #6E2517;
99
+ --baht-red-900: #2A0C08; /* content on red-300 */
100
+
101
+ /* Info — steel blue */
60
102
  --baht-slate-50: #E6ECF0;
103
+ --baht-slate-300: #8FB0C4; /* dark-mode info */
61
104
  --baht-slate-500: #3B5A6E; /* info */
105
+ --baht-slate-900: #0F2028; /* content on slate-300 */
62
106
 
63
107
  /* ---------- Theme tier (daisyUI-style knobs — THE flexible theming API) ----------
64
108
  Override any of these on :root (or a wrapper, or inline style) and every
65
109
  semantic token below derives from them. Hover/active/tint shades are
66
- computed with color-mix, so one --baht-primary swap rethemes everything. */
67
- --baht-base-100: #FFFFFF; /* surfaces: cards, inputs, modals */
110
+ computed with color-mix, so one --baht-primary swap rethemes everything.
111
+
112
+ Distribution rule (the point of the retone): olive is a strong hue and may
113
+ not carry large surfaces. Data sits on base-100 (white), the page behind it
114
+ is base-200 (note paper), and olive appears in three places only — table
115
+ header, primary button, active nav. */
116
+ --baht-base-100: #FFFFFF; /* surfaces: cards, tables, inputs, modals */
68
117
  --baht-base-200: var(--baht-cream-100); /* page background */
69
- --baht-base-300: var(--baht-cream-200); /* sunken wells, code chips */
118
+ --baht-base-300: var(--baht-cream-200); /* sunken wells, rails, code chips */
70
119
  --baht-base-content: var(--baht-gray-900);
120
+ --baht-row-alt: var(--baht-cream-100); /* zebra rows: a 2% step off the surface, not 10% */
71
121
 
72
122
  --baht-primary: var(--baht-green-600);
73
123
  --baht-primary-content: #FFFFFF;
74
- --baht-secondary: var(--baht-slate-500);
124
+ --baht-secondary: var(--baht-rose-500);
75
125
  --baht-secondary-content: #FFFFFF;
76
126
  --baht-accent: var(--baht-gold-500);
77
- --baht-accent-content: var(--baht-gray-900);
78
- --baht-neutral: var(--baht-gray-900); /* ink: inverse blocks, code panels */
79
- --baht-neutral-content: var(--baht-cream-50);
127
+ --baht-accent-content: #33280A;
128
+ --baht-neutral: var(--baht-green-800); /* deep olive: table header, inverse blocks */
129
+ --baht-neutral-content: #F2F0DC;
80
130
 
81
131
  --baht-info: var(--baht-slate-500);
82
132
  --baht-info-content: #FFFFFF;
83
133
  --baht-success: var(--baht-green-600);
84
134
  --baht-success-content: #FFFFFF;
85
- --baht-warning: var(--baht-gold-500);
86
- --baht-warning-content: var(--baht-gray-900);
135
+ --baht-warning: var(--baht-lime-500);
136
+ --baht-warning-content: var(--baht-lime-900);
87
137
  --baht-error: var(--baht-red-500);
88
138
  --baht-error-content: #FFFFFF;
89
139
 
140
+ /* Status tints — the pill pairs used for scanning a table column.
141
+ ~12% tint with its own dark ink; the dot carries the saturated hue. */
142
+ --baht-success-tint: var(--baht-green-50);
143
+ --baht-success-ink: var(--baht-green-750);
144
+ --baht-success-dot: var(--baht-green-600);
145
+ --baht-warning-tint: var(--baht-gold-50);
146
+ --baht-warning-ink: var(--baht-gold-700);
147
+ --baht-warning-dot: var(--baht-gold-500);
148
+ --baht-error-tint: var(--baht-red-50);
149
+ --baht-error-ink: var(--baht-red-600);
150
+ --baht-error-dot: var(--baht-rose-500);
151
+ --baht-info-tint: var(--baht-slate-50);
152
+ --baht-info-ink: var(--baht-slate-500);
153
+ --baht-info-dot: var(--baht-slate-500);
154
+
90
155
  /* ---------- Semantic colors (stable names components consume) ---------- */
91
156
  --baht-color-bg: var(--baht-base-200);
92
157
  --baht-color-bg-elev: var(--baht-base-100);
@@ -94,7 +159,8 @@
94
159
  --baht-color-bg-inverse: var(--baht-neutral);
95
160
 
96
161
  --baht-color-surface: var(--baht-base-100);
97
- --baht-color-surface-alt: var(--baht-cream-50);
162
+ --baht-color-surface-alt: var(--baht-base-200);
163
+ --baht-color-row-alt: var(--baht-row-alt);
98
164
 
99
165
  --baht-color-text: var(--baht-base-content);
100
166
  --baht-color-text-muted: var(--baht-gray-600);
@@ -104,6 +170,7 @@
104
170
  --baht-color-border: var(--baht-cream-300);
105
171
  --baht-color-border-cool: var(--baht-gray-200);
106
172
  --baht-color-border-strong: var(--baht-gray-300);
173
+ --baht-color-divider: var(--baht-gray-100);
107
174
 
108
175
  --baht-color-primary: var(--baht-primary);
109
176
  --baht-color-primary-hover: color-mix(in oklab, var(--baht-primary) 84%, black);
@@ -115,6 +182,11 @@
115
182
  --baht-color-primary-wash-active: color-mix(in oklab, var(--baht-primary) 10%, transparent);
116
183
  --baht-color-primary-contrast: var(--baht-primary-content);
117
184
 
185
+ --baht-color-secondary: var(--baht-secondary);
186
+ --baht-color-secondary-contrast: var(--baht-secondary-content);
187
+ --baht-color-accent: var(--baht-accent);
188
+ --baht-color-accent-contrast: var(--baht-accent-content);
189
+
118
190
  --baht-color-success: var(--baht-success);
119
191
  --baht-color-warning: var(--baht-warning);
120
192
  --baht-color-danger: var(--baht-error);
@@ -125,6 +197,8 @@
125
197
  --baht-color-link: color-mix(in oklab, var(--baht-primary) 90%, black);
126
198
  --baht-color-focus: var(--baht-primary);
127
199
 
200
+ /* ink used by shadows and scrims — follows the theme, not a fixed black */
201
+ --baht-color-shadow-ink: 34, 51, 26;
128
202
  /* ---------- Typography ---------- */
129
203
  --baht-font-display: "Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif;
130
204
  --baht-font-family: "Geist", ui-sans-serif, system-ui, sans-serif;
@@ -179,8 +253,8 @@
179
253
  --baht-noise: 0; /* reserved: paper-grain overlay opacity */
180
254
 
181
255
  /* ---------- Shadows (two elevations only, never inner) ---------- */
182
- --baht-shadow-lift: 0 1px 2px rgba(14, 31, 23, 0.06), 0 4px 12px -2px rgba(14, 31, 23, 0.08);
183
- --baht-shadow-float: 0 4px 16px rgba(14, 31, 23, 0.08), 0 24px 48px -8px rgba(14, 31, 23, 0.12);
256
+ --baht-shadow-lift: 0 1px 2px rgba(var(--baht-color-shadow-ink), 0.06), 0 4px 12px -2px rgba(var(--baht-color-shadow-ink), 0.08);
257
+ --baht-shadow-float: 0 4px 16px rgba(var(--baht-color-shadow-ink), 0.08), 0 24px 48px -8px rgba(var(--baht-color-shadow-ink), 0.12);
184
258
 
185
259
  /* ---------- Motion ("paper" ease — quick start, gentle settle) ---------- */
186
260
  --baht-ease: cubic-bezier(0.2, 0.7, 0.1, 1);
@@ -196,6 +270,209 @@
196
270
  --baht-field-gap: var(--baht-space-4);
197
271
  }
198
272
 
273
+ /* ============================================================
274
+ Dark theme — "20baht-dark". Opt in with [data-baht-theme="dark"] (or the
275
+ .baht-dark class) on <html> or any wrapper; with neither attribute set,
276
+ the OS preference decides. Force light with [data-baht-theme="light"].
277
+ ============================================================ */
278
+
279
+ [data-baht-theme='dark'],
280
+ .baht-dark {
281
+ /* The ramps re-anchor for a near-black canvas; every semantic token above
282
+ derives from them, so only the values that genuinely invert are listed. */
283
+ --baht-green-50: #1F2A16; /* success tint */
284
+ --baht-green-100: #24301A;
285
+ --baht-green-200: #2F4020;
286
+ --baht-green-300: #A9C598; /* success */
287
+ --baht-green-400: #9DB56A;
288
+ --baht-green-500: #94AE60;
289
+ --baht-green-600: #8FA85A; /* primary — brightens so the button still leads */
290
+ --baht-green-700: #A9C598;
291
+ --baht-green-750: #B7D096; /* success ink on the dark tint */
292
+ --baht-green-800: #2F4020; /* neutral */
293
+ --baht-green-900: #24301A;
294
+ --baht-green-950: #1B2A14;
295
+
296
+ --baht-cream-50: #E8E7D6; /* inverse ink */
297
+ --baht-cream-100: #121310;
298
+ --baht-cream-200: #1A1B16;
299
+ --baht-cream-300: #2A2C24;
300
+ --baht-cream-400: #3A3D33;
301
+
302
+ --baht-gray-50: #121310;
303
+ --baht-gray-100: #1A1B16;
304
+ --baht-gray-200: #2A2C24;
305
+ --baht-gray-300: #3A3D33;
306
+ --baht-gray-400: #6E7165;
307
+ --baht-gray-500: #8E9083;
308
+ --baht-gray-600: #C6C7BA;
309
+ --baht-gray-700: #D7D8CB;
310
+ --baht-gray-800: #E8E7D6;
311
+ --baht-gray-900: #F2F0DC;
312
+
313
+ --baht-rose-50: #33201B;
314
+ --baht-rose-100: #3A2620;
315
+ --baht-rose-200: #4A322B;
316
+ --baht-rose-300: #D9A398;
317
+ --baht-rose-400: #E4B6AC;
318
+ --baht-rose-500: #D9A398; /* secondary */
319
+ --baht-rose-600: #E4B6AC;
320
+ --baht-rose-700: #C58274;
321
+ --baht-rose-800: #75403A;
322
+
323
+ --baht-gold-50: #2C2717; /* warning tint */
324
+ --baht-gold-400: #E4D9A6;
325
+ --baht-gold-500: #D9B97A; /* accent */
326
+ --baht-gold-600: #C9A55C;
327
+ --baht-gold-700: #E4D9A6; /* warning ink on the dark tint */
328
+
329
+ --baht-lime-500: #CFCF7A; /* warning */
330
+
331
+ --baht-red-50: #33201B; /* error tint */
332
+ --baht-red-400: #F0B9AE;
333
+ --baht-red-500: #E08878; /* error */
334
+ --baht-red-600: #F0B9AE; /* error ink on the dark tint */
335
+ --baht-red-700: #C9705F;
336
+
337
+ --baht-slate-50: #1B262C; /* info tint */
338
+ --baht-slate-500: #8FB0C4; /* info */
339
+
340
+ /* Dark inverts one distribution rule: the card is *lighter* than the page
341
+ (surface base-100 over the base-200 app background). */
342
+ --baht-base-100: #1A1B16; /* surfaces: panels, tables, inputs, modals */
343
+ --baht-base-300: var(--baht-cream-300);
344
+ --baht-row-alt: #171813;
345
+
346
+ /* on a dark canvas every "content" colour flips from white to deep ink */
347
+ --baht-primary-content: var(--baht-green-950);
348
+ --baht-secondary-content: var(--baht-rose-900);
349
+ --baht-accent-content: var(--baht-gold-900);
350
+ --baht-neutral-content: #E8E7D6;
351
+ --baht-info-content: var(--baht-slate-900);
352
+ --baht-success: var(--baht-green-300);
353
+ --baht-success-content: var(--baht-green-950);
354
+ --baht-error-content: var(--baht-red-900);
355
+ --baht-error-dot: var(--baht-red-500);
356
+
357
+ --baht-color-surface-alt: #1F211A;
358
+ --baht-color-divider: #24261E;
359
+
360
+ /* the light-mode mixes lighten toward white and darken toward black; on a
361
+ dark canvas both directions flip, so re-derive them against the surface. */
362
+ --baht-color-primary-hover: color-mix(in oklab, var(--baht-primary) 88%, white);
363
+ --baht-color-primary-active: color-mix(in oklab, var(--baht-primary) 76%, white);
364
+ --baht-color-primary-tint: color-mix(in oklab, var(--baht-primary) 16%, var(--baht-base-100));
365
+ --baht-color-primary-wash: color-mix(in oklab, var(--baht-primary) 10%, transparent);
366
+ --baht-color-primary-wash-active: color-mix(in oklab, var(--baht-primary) 16%, transparent);
367
+ --baht-color-danger-hover: color-mix(in oklab, var(--baht-error) 88%, white);
368
+ --baht-color-link: var(--baht-green-300);
369
+
370
+ --baht-color-shadow-ink: 0, 0, 0;
371
+ --baht-shadow-lift: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px -2px rgba(0, 0, 0, 0.5);
372
+ --baht-shadow-float: 0 4px 16px rgba(0, 0, 0, 0.5), 0 24px 48px -8px rgba(0, 0, 0, 0.6);
373
+ }
374
+
375
+ @media (prefers-color-scheme: dark) {
376
+ :root:not([data-baht-theme='light']):not(.baht-light) {
377
+ /* The ramps re-anchor for a near-black canvas; every semantic token above
378
+ derives from them, so only the values that genuinely invert are listed. */
379
+ --baht-green-50: #1F2A16; /* success tint */
380
+ --baht-green-100: #24301A;
381
+ --baht-green-200: #2F4020;
382
+ --baht-green-300: #A9C598; /* success */
383
+ --baht-green-400: #9DB56A;
384
+ --baht-green-500: #94AE60;
385
+ --baht-green-600: #8FA85A; /* primary — brightens so the button still leads */
386
+ --baht-green-700: #A9C598;
387
+ --baht-green-750: #B7D096; /* success ink on the dark tint */
388
+ --baht-green-800: #2F4020; /* neutral */
389
+ --baht-green-900: #24301A;
390
+ --baht-green-950: #1B2A14;
391
+
392
+ --baht-cream-50: #E8E7D6; /* inverse ink */
393
+ --baht-cream-100: #121310;
394
+ --baht-cream-200: #1A1B16;
395
+ --baht-cream-300: #2A2C24;
396
+ --baht-cream-400: #3A3D33;
397
+
398
+ --baht-gray-50: #121310;
399
+ --baht-gray-100: #1A1B16;
400
+ --baht-gray-200: #2A2C24;
401
+ --baht-gray-300: #3A3D33;
402
+ --baht-gray-400: #6E7165;
403
+ --baht-gray-500: #8E9083;
404
+ --baht-gray-600: #C6C7BA;
405
+ --baht-gray-700: #D7D8CB;
406
+ --baht-gray-800: #E8E7D6;
407
+ --baht-gray-900: #F2F0DC;
408
+
409
+ --baht-rose-50: #33201B;
410
+ --baht-rose-100: #3A2620;
411
+ --baht-rose-200: #4A322B;
412
+ --baht-rose-300: #D9A398;
413
+ --baht-rose-400: #E4B6AC;
414
+ --baht-rose-500: #D9A398; /* secondary */
415
+ --baht-rose-600: #E4B6AC;
416
+ --baht-rose-700: #C58274;
417
+ --baht-rose-800: #75403A;
418
+
419
+ --baht-gold-50: #2C2717; /* warning tint */
420
+ --baht-gold-400: #E4D9A6;
421
+ --baht-gold-500: #D9B97A; /* accent */
422
+ --baht-gold-600: #C9A55C;
423
+ --baht-gold-700: #E4D9A6; /* warning ink on the dark tint */
424
+
425
+ --baht-lime-500: #CFCF7A; /* warning */
426
+
427
+ --baht-red-50: #33201B; /* error tint */
428
+ --baht-red-400: #F0B9AE;
429
+ --baht-red-500: #E08878; /* error */
430
+ --baht-red-600: #F0B9AE; /* error ink on the dark tint */
431
+ --baht-red-700: #C9705F;
432
+
433
+ --baht-slate-50: #1B262C; /* info tint */
434
+ --baht-slate-500: #8FB0C4; /* info */
435
+
436
+ /* Dark inverts one distribution rule: the card is *lighter* than the page
437
+ (surface base-100 over the base-200 app background). */
438
+ --baht-base-100: #1A1B16; /* surfaces: panels, tables, inputs, modals */
439
+ --baht-base-300: var(--baht-cream-300);
440
+ --baht-row-alt: #171813;
441
+
442
+ /* on a dark canvas every "content" colour flips from white to deep ink */
443
+ --baht-primary-content: var(--baht-green-950);
444
+ --baht-secondary-content: var(--baht-rose-900);
445
+ --baht-accent-content: var(--baht-gold-900);
446
+ --baht-neutral-content: #E8E7D6;
447
+ --baht-info-content: var(--baht-slate-900);
448
+ --baht-success: var(--baht-green-300);
449
+ --baht-success-content: var(--baht-green-950);
450
+ --baht-error-content: var(--baht-red-900);
451
+ --baht-error-dot: var(--baht-red-500);
452
+
453
+ --baht-color-surface-alt: #1F211A;
454
+ --baht-color-divider: #24261E;
455
+
456
+ /* the light-mode mixes lighten toward white and darken toward black; on a
457
+ dark canvas both directions flip, so re-derive them against the surface. */
458
+ --baht-color-primary-hover: color-mix(in oklab, var(--baht-primary) 88%, white);
459
+ --baht-color-primary-active: color-mix(in oklab, var(--baht-primary) 76%, white);
460
+ --baht-color-primary-tint: color-mix(in oklab, var(--baht-primary) 16%, var(--baht-base-100));
461
+ --baht-color-primary-wash: color-mix(in oklab, var(--baht-primary) 10%, transparent);
462
+ --baht-color-primary-wash-active: color-mix(in oklab, var(--baht-primary) 16%, transparent);
463
+ --baht-color-danger-hover: color-mix(in oklab, var(--baht-error) 88%, white);
464
+ --baht-color-link: var(--baht-green-300);
465
+
466
+ --baht-color-shadow-ink: 0, 0, 0;
467
+ --baht-shadow-lift: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px -2px rgba(0, 0, 0, 0.5);
468
+ --baht-shadow-float: 0 4px 16px rgba(0, 0, 0, 0.5), 0 24px 48px -8px rgba(0, 0, 0, 0.6);
469
+ }
470
+ }
471
+
472
+ /* the surrounding page follows the theme too, when the host opts in */
473
+ [data-baht-theme] { color-scheme: light; }
474
+ [data-baht-theme='dark'], .baht-dark { color-scheme: dark; }
475
+
199
476
  /* ============================================================
200
477
  Structural styles (light DOM — override freely per app)
201
478
  ============================================================ */
@@ -437,18 +714,18 @@
437
714
  }
438
715
  .baht-badge-dot { width: 6px; height: 6px; border-radius: var(--baht-radius-pill); background: var(--baht-gray-500); }
439
716
 
440
- .baht-badge--success { background: var(--baht-green-50); color: var(--baht-green-800); }
441
- .baht-badge--success .baht-badge-dot { background: var(--baht-green-600); }
442
- .baht-badge--danger { background: var(--baht-red-50); color: var(--baht-red-600); }
443
- .baht-badge--danger .baht-badge-dot { background: var(--baht-red-500); }
444
- .baht-badge--warning { background: var(--baht-gold-50); color: var(--baht-gold-700); }
445
- .baht-badge--warning .baht-badge-dot { background: var(--baht-gold-500); }
446
- .baht-badge--info { background: var(--baht-slate-50); color: var(--baht-slate-500); }
447
- .baht-badge--info .baht-badge-dot { background: var(--baht-slate-500); }
717
+ .baht-badge--success { background: var(--baht-success-tint); color: var(--baht-success-ink); font-weight: 600; }
718
+ .baht-badge--success .baht-badge-dot { background: var(--baht-success-dot); }
719
+ .baht-badge--danger { background: var(--baht-error-tint); color: var(--baht-error-ink); font-weight: 600; }
720
+ .baht-badge--danger .baht-badge-dot { background: var(--baht-error-dot); }
721
+ .baht-badge--warning { background: var(--baht-warning-tint); color: var(--baht-warning-ink); font-weight: 600; }
722
+ .baht-badge--warning .baht-badge-dot { background: var(--baht-warning-dot); }
723
+ .baht-badge--info { background: var(--baht-info-tint); color: var(--baht-info-ink); font-weight: 600; }
724
+ .baht-badge--info .baht-badge-dot { background: var(--baht-info-dot); }
448
725
 
449
726
  .baht-badge--outline { background: var(--baht-color-surface); border: 1px solid var(--baht-color-border-cool); color: var(--baht-color-text); padding: 4px 10px; }
450
727
  .baht-badge--solid { background: var(--baht-color-primary); color: var(--baht-color-primary-contrast); padding: 4px 10px; }
451
- .baht-badge--gold { background: var(--baht-gold-500); color: var(--baht-gray-900); padding: 4px 10px; } /* white on gold = 2.3:1 */
728
+ .baht-badge--gold { background: var(--baht-color-accent); color: var(--baht-color-accent-contrast); padding: 4px 10px; } /* white on gold = 2.3:1 */
452
729
  .baht-badge--inverse { background: var(--baht-color-bg-inverse); color: var(--baht-color-text-inverse); padding: 4px 10px; }
453
730
  .baht-badge--mono { font-family: var(--baht-font-mono); font-size: 0.6875rem; padding: 4px 8px; background: var(--baht-color-bg-sunken); color: var(--baht-gray-700); }
454
731
 
@@ -469,7 +746,7 @@ code.baht-code {
469
746
  .baht-code--block {
470
747
  display: block;
471
748
  background: var(--baht-color-bg-inverse);
472
- color: var(--baht-cream-50);
749
+ color: var(--baht-color-text-inverse);
473
750
  padding: var(--baht-space-4);
474
751
  border-radius: var(--baht-radius-md);
475
752
  font-size: var(--baht-text-xs);
@@ -530,7 +807,7 @@ code.baht-code {
530
807
  color: var(--baht-red-600);
531
808
  border-color: var(--baht-red-500);
532
809
  }
533
- .baht-button--reject:hover { background: var(--baht-red-50); }
810
+ .baht-button--reject:hover { background: var(--baht-error-tint); }
534
811
 
535
812
  /* ============================================================
536
813
  Data — table & list (server-side paging: host fetches per page)
@@ -556,9 +833,9 @@ code.baht-code {
556
833
  white-space: nowrap;
557
834
  }
558
835
  .baht-table th.baht-table-index { width: 56px; text-align: center; }
559
- .baht-table td { padding: 12px var(--baht-space-4); border-top: 1px solid var(--baht-color-border-cool); }
836
+ .baht-table td { padding: 12px var(--baht-space-4); border-top: 1px solid var(--baht-color-divider); }
560
837
  .baht-table td.baht-table-index { text-align: center; color: var(--baht-color-text-subtle); }
561
- .baht-table tbody tr:nth-child(even) { background: var(--baht-gray-50); }
838
+ .baht-table tbody tr:nth-child(even) { background: var(--baht-color-row-alt); }
562
839
  .baht-table tbody tr[tabindex]:hover { background: var(--baht-color-primary-tint); cursor: pointer; }
563
840
  .baht-table tbody tr[tabindex]:focus-visible { outline: 2px solid var(--baht-color-focus); outline-offset: -2px; }
564
841
  .baht-table-state { padding: var(--baht-space-8); text-align: center; color: var(--baht-color-text-muted); }
@@ -577,13 +854,13 @@ code.baht-code {
577
854
  font-family: var(--baht-font-family); font-size: var(--baht-text-sm);
578
855
  cursor: pointer;
579
856
  }
580
- .baht-table-picker-toggle:hover { background: var(--baht-gray-100); }
857
+ .baht-table-picker-toggle:hover { background: var(--baht-color-primary-wash); }
581
858
  .baht-table-picker-toggle[aria-expanded='true'] { border-color: var(--baht-color-primary); }
582
859
 
583
860
  /* Dual-list "Personalize List Columns" modal (Available/Selected + move buttons). */
584
861
  .baht-table-picker-scrim {
585
862
  position: fixed; inset: 0; z-index: 1000;
586
- background: rgba(14, 31, 23, 0.4);
863
+ background: rgba(var(--baht-color-shadow-ink), 0.4);
587
864
  display: flex; align-items: center; justify-content: center;
588
865
  padding: var(--baht-space-6);
589
866
  animation: baht-fade-in var(--baht-dur-base) var(--baht-ease);
@@ -633,7 +910,7 @@ code.baht-code {
633
910
  font-family: var(--baht-font-family); font-size: var(--baht-text-sm);
634
911
  cursor: pointer;
635
912
  }
636
- .baht-table-picker-btns button:hover:not(:disabled) { background: var(--baht-gray-100); }
913
+ .baht-table-picker-btns button:hover:not(:disabled) { background: var(--baht-color-primary-wash); }
637
914
  .baht-table-picker-btns button:disabled { opacity: 0.5; cursor: not-allowed; }
638
915
  .baht-table-picker-modal-foot {
639
916
  display: flex; align-items: center; gap: var(--baht-space-2);
@@ -648,7 +925,7 @@ code.baht-code {
648
925
  font-family: var(--baht-font-family); font-size: var(--baht-text-sm);
649
926
  cursor: pointer;
650
927
  }
651
- .baht-table-picker-modal-foot button:hover { background: var(--baht-gray-100); }
928
+ .baht-table-picker-modal-foot button:hover { background: var(--baht-color-primary-wash); }
652
929
  .baht-table-picker-ok {
653
930
  background: var(--baht-color-primary) !important; color: var(--baht-color-text-inverse) !important;
654
931
  border-color: var(--baht-color-primary) !important;
@@ -672,7 +949,7 @@ code.baht-code {
672
949
 
673
950
  .baht-skeleton {
674
951
  display: block;
675
- background: var(--baht-gray-100);
952
+ background: var(--baht-color-bg-sunken);
676
953
  border-radius: var(--baht-radius-sm);
677
954
  animation: baht-pulse 1.4s var(--baht-ease) infinite;
678
955
  }
@@ -719,7 +996,7 @@ code.baht-code {
719
996
 
720
997
  .baht-modal-scrim {
721
998
  position: fixed; inset: 0; z-index: 1000;
722
- background: rgba(14, 31, 23, 0.4);
999
+ background: rgba(var(--baht-color-shadow-ink), 0.4);
723
1000
  display: flex; align-items: center; justify-content: center;
724
1001
  padding: var(--baht-space-6);
725
1002
  animation: baht-fade-in var(--baht-dur-base) var(--baht-ease);
@@ -847,7 +1124,7 @@ code.baht-code {
847
1124
 
848
1125
  .baht-progress {
849
1126
  display: block; width: 100%; height: 8px;
850
- background: var(--baht-gray-100); border-radius: var(--baht-radius-pill);
1127
+ background: var(--baht-color-bg-sunken); border-radius: var(--baht-radius-pill);
851
1128
  overflow: hidden;
852
1129
  }
853
1130
  .baht-progress-bar {
@@ -1056,7 +1333,7 @@ code.baht-code {
1056
1333
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
1057
1334
  text-align: right; font-size: var(--baht-text-sm); color: var(--baht-color-text-muted);
1058
1335
  }
1059
- .baht-bar-chart-track { height: 20px; flex: 1; overflow: hidden; border-radius: var(--baht-radius-sm); background: var(--baht-gray-100); }
1336
+ .baht-bar-chart-track { height: 20px; flex: 1; overflow: hidden; border-radius: var(--baht-radius-sm); background: var(--baht-color-bg-sunken); }
1060
1337
  .baht-bar-chart-bar { height: 100%; border-radius: var(--baht-radius-sm); }
1061
1338
  .baht-bar-chart-count { width: 2.5rem; font-size: var(--baht-text-sm); font-weight: 600; font-variant-numeric: tabular-nums; }
1062
1339
 
@@ -1126,7 +1403,7 @@ code.baht-code {
1126
1403
  border: none; background: none; border-radius: var(--baht-radius-sm);
1127
1404
  color: var(--baht-color-text-subtle); cursor: pointer;
1128
1405
  }
1129
- .baht-refpicker-clear:hover { color: var(--baht-color-text); background: var(--baht-gray-100); }
1406
+ .baht-refpicker-clear:hover { color: var(--baht-color-text); background: var(--baht-color-primary-wash); }
1130
1407
  .baht-refpicker-lookup,
1131
1408
  .baht-refpicker-open {
1132
1409
  display: inline-flex; align-items: center; justify-content: center;
@@ -1136,7 +1413,7 @@ code.baht-code {
1136
1413
  color: var(--baht-color-text-muted);
1137
1414
  cursor: pointer;
1138
1415
  }
1139
- .baht-refpicker-lookup:hover, .baht-refpicker-open:hover { background: var(--baht-gray-100); color: var(--baht-color-text); }
1416
+ .baht-refpicker-lookup:hover, .baht-refpicker-open:hover { background: var(--baht-color-primary-wash); color: var(--baht-color-text); }
1140
1417
  .baht-refpicker-lookup:disabled { cursor: not-allowed; opacity: 0.5; }
1141
1418
  .baht-refpicker > :last-child:not(.baht-refpicker-list):not(.baht-refpicker-field) {
1142
1419
  border-top-right-radius: var(--baht-radius-field); border-bottom-right-radius: var(--baht-radius-field);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
3
3
  "name": "bank20baht-ui",
4
- "version": "0.1.9",
4
+ "version": "0.2.0",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bank20baht-ui",
3
- "version": "0.1.9",
3
+ "version": "0.2.0",
4
4
  "type": "module",
5
5
  "description": "JSON-driven form + workflow engine. Send JSON in, get an interactive form out.",
6
6
  "license": "MIT",