panelui-native 0.41.0 → 0.43.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.
Files changed (58) hide show
  1. package/README.md +3 -2
  2. package/lib/module/components/color-picker/index.js +1395 -0
  3. package/lib/module/components/color-picker/index.js.map +1 -0
  4. package/lib/module/components/combobox/index.js +87 -19
  5. package/lib/module/components/combobox/index.js.map +1 -1
  6. package/lib/module/components/kpi-chart/index.js +648 -0
  7. package/lib/module/components/kpi-chart/index.js.map +1 -0
  8. package/lib/module/components/menu/index.js +40 -10
  9. package/lib/module/components/menu/index.js.map +1 -1
  10. package/lib/module/components/radar-chart/index.js +704 -0
  11. package/lib/module/components/radar-chart/index.js.map +1 -0
  12. package/lib/module/components/section-rail/index.js +32 -7
  13. package/lib/module/components/section-rail/index.js.map +1 -1
  14. package/lib/module/components/slider/index.js +240 -39
  15. package/lib/module/components/slider/index.js.map +1 -1
  16. package/lib/module/components/tabs/index.js +194 -10
  17. package/lib/module/components/tabs/index.js.map +1 -1
  18. package/lib/module/index.js +4 -0
  19. package/lib/module/index.js.map +1 -1
  20. package/lib/module/theme/use-theme.js +1 -1
  21. package/lib/module/utils/chart.js +44 -0
  22. package/lib/module/utils/chart.js.map +1 -1
  23. package/lib/module/utils/color.js +268 -0
  24. package/lib/module/utils/color.js.map +1 -0
  25. package/lib/typescript/src/components/color-picker/index.d.ts +258 -0
  26. package/lib/typescript/src/components/color-picker/index.d.ts.map +1 -0
  27. package/lib/typescript/src/components/combobox/index.d.ts.map +1 -1
  28. package/lib/typescript/src/components/kpi-chart/index.d.ts +490 -0
  29. package/lib/typescript/src/components/kpi-chart/index.d.ts.map +1 -0
  30. package/lib/typescript/src/components/menu/index.d.ts.map +1 -1
  31. package/lib/typescript/src/components/radar-chart/index.d.ts +214 -0
  32. package/lib/typescript/src/components/radar-chart/index.d.ts.map +1 -0
  33. package/lib/typescript/src/components/section-rail/index.d.ts +8 -1
  34. package/lib/typescript/src/components/section-rail/index.d.ts.map +1 -1
  35. package/lib/typescript/src/components/slider/index.d.ts +19 -0
  36. package/lib/typescript/src/components/slider/index.d.ts.map +1 -1
  37. package/lib/typescript/src/components/tabs/index.d.ts +11 -1
  38. package/lib/typescript/src/components/tabs/index.d.ts.map +1 -1
  39. package/lib/typescript/src/index.d.ts +4 -0
  40. package/lib/typescript/src/index.d.ts.map +1 -1
  41. package/lib/typescript/src/utils/chart.d.ts +21 -0
  42. package/lib/typescript/src/utils/chart.d.ts.map +1 -1
  43. package/lib/typescript/src/utils/color.d.ts +74 -0
  44. package/lib/typescript/src/utils/color.d.ts.map +1 -0
  45. package/package.json +2 -1
  46. package/src/components/color-picker/index.tsx +1618 -0
  47. package/src/components/combobox/index.tsx +89 -19
  48. package/src/components/kpi-chart/index.tsx +719 -0
  49. package/src/components/menu/index.tsx +51 -6
  50. package/src/components/radar-chart/index.tsx +910 -0
  51. package/src/components/section-rail/index.tsx +42 -8
  52. package/src/components/slider/index.tsx +283 -41
  53. package/src/components/tabs/index.tsx +263 -8
  54. package/src/index.ts +60 -0
  55. package/src/theme/use-theme.ts +1 -1
  56. package/src/utils/chart.ts +52 -0
  57. package/src/utils/color.ts +246 -0
  58. package/theme.css +125 -112
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Colour arithmetic, in the model a picker is shaped like.
3
+ *
4
+ * A picker's controls *are* HSV: a square of saturation against brightness
5
+ * under one hue, with the hue itself on a separate scale. Storing anything
6
+ * else means converting on every frame of a drag and, worse, losing the
7
+ * position of the thumb — a fully black colour is `#000` whatever its hue and
8
+ * saturation were, so a round trip through RGB throws away where the finger
9
+ * was. HSV is kept as the truth and everything here converts *out* of it.
10
+ *
11
+ * Every function is a worklet. The drag never leaves the UI thread, so the
12
+ * hue behind the square, the thumb fill and the preview swatch all need these
13
+ * on the same frame the finger moved, and a JS-only helper would put a bridge
14
+ * hop in the middle of that.
15
+ */
16
+
17
+ /** A colour in the model the picker stores: hue, saturation, value, alpha. */
18
+ export interface HsvaColor {
19
+ /** Hue in degrees, `0`–`360`. */
20
+ h: number;
21
+ /** Saturation, `0`–`1`. */
22
+ s: number;
23
+ /** Value — brightness — `0`–`1`. */
24
+ v: number;
25
+ /** Alpha, `0`–`1`. */
26
+ a: number;
27
+ }
28
+
29
+ /** How a colour is written when it leaves the picker. */
30
+ export type ColorFormat = 'hex' | 'rgb' | 'hsl';
31
+
32
+ function clamp01(n: number) {
33
+ 'worklet';
34
+ return n < 0 ? 0 : n > 1 ? 1 : n;
35
+ }
36
+
37
+ /** Hue wraps rather than clamps — 370° is 10°, and -10° is 350°. */
38
+ function wrapHue(h: number) {
39
+ 'worklet';
40
+ return ((h % 360) + 360) % 360;
41
+ }
42
+
43
+ /** HSV to 8-bit RGB. */
44
+ export function hsvToRgb(h: number, s: number, v: number) {
45
+ 'worklet';
46
+ const hue = wrapHue(h) / 60;
47
+ const sat = clamp01(s);
48
+ const val = clamp01(v);
49
+ const c = val * sat;
50
+ const x = c * (1 - Math.abs((hue % 2) - 1));
51
+ const m = val - c;
52
+
53
+ let r = 0;
54
+ let g = 0;
55
+ let b = 0;
56
+ if (hue < 1) {
57
+ r = c;
58
+ g = x;
59
+ } else if (hue < 2) {
60
+ r = x;
61
+ g = c;
62
+ } else if (hue < 3) {
63
+ g = c;
64
+ b = x;
65
+ } else if (hue < 4) {
66
+ g = x;
67
+ b = c;
68
+ } else if (hue < 5) {
69
+ r = x;
70
+ b = c;
71
+ } else {
72
+ r = c;
73
+ b = x;
74
+ }
75
+
76
+ return {
77
+ r: Math.round((r + m) * 255),
78
+ g: Math.round((g + m) * 255),
79
+ b: Math.round((b + m) * 255),
80
+ };
81
+ }
82
+
83
+ /** 8-bit RGB to HSV. Hue is undefined for a grey, and comes back as `0`. */
84
+ export function rgbToHsv(r: number, g: number, b: number) {
85
+ 'worklet';
86
+ const rr = clamp01(r / 255);
87
+ const gg = clamp01(g / 255);
88
+ const bb = clamp01(b / 255);
89
+ const max = Math.max(rr, gg, bb);
90
+ const min = Math.min(rr, gg, bb);
91
+ const d = max - min;
92
+
93
+ let h = 0;
94
+ if (d !== 0) {
95
+ if (max === rr) h = 60 * (((gg - bb) / d) % 6);
96
+ else if (max === gg) h = 60 * ((bb - rr) / d + 2);
97
+ else h = 60 * ((rr - gg) / d + 4);
98
+ }
99
+
100
+ return { h: wrapHue(h), s: max === 0 ? 0 : d / max, v: max };
101
+ }
102
+
103
+ /** HSV to HSL, for `format="hsl"`. Both are cylinders; only the axis differs. */
104
+ export function hsvToHsl(h: number, s: number, v: number) {
105
+ 'worklet';
106
+ const val = clamp01(v);
107
+ const sat = clamp01(s);
108
+ const l = val * (1 - sat / 2);
109
+ const denominator = Math.min(l, 1 - l);
110
+ return { h: wrapHue(h), s: denominator === 0 ? 0 : (val - l) / denominator, l };
111
+ }
112
+
113
+ /**
114
+ * An `rgba()` string, which is what a style wants. Used for every animated
115
+ * fill in the picker, so it stays cheap: no allocation beyond the string, and
116
+ * no branch on the alpha.
117
+ */
118
+ export function hsvToCss(h: number, s: number, v: number, a = 1) {
119
+ 'worklet';
120
+ const { r, g, b } = hsvToRgb(h, s, v);
121
+ return `rgba(${r}, ${g}, ${b}, ${clamp01(a)})`;
122
+ }
123
+
124
+ function toHexPair(n: number) {
125
+ 'worklet';
126
+ const clamped = n < 0 ? 0 : n > 255 ? 255 : Math.round(n);
127
+ return clamped < 16 ? `0${clamped.toString(16)}` : clamped.toString(16);
128
+ }
129
+
130
+ /**
131
+ * A `#rrggbb` string, gaining a `#rrggbbaa` alpha pair only when the colour is
132
+ * actually translucent — an opaque colour written with a trailing `ff` is the
133
+ * same colour spelled in a way half the CSS parsers in the world reject.
134
+ */
135
+ export function hsvToHex(h: number, s: number, v: number, a = 1) {
136
+ 'worklet';
137
+ const { r, g, b } = hsvToRgb(h, s, v);
138
+ const base = `#${toHexPair(r)}${toHexPair(g)}${toHexPair(b)}`;
139
+ return a >= 1 ? base : `${base}${toHexPair(clamp01(a) * 255)}`;
140
+ }
141
+
142
+ /** Writes a stored colour out in one of the three formats a consumer asks for. */
143
+ export function formatColor(color: HsvaColor, format: ColorFormat = 'hex') {
144
+ 'worklet';
145
+ const { h, s, v, a } = color;
146
+ const alpha = clamp01(a);
147
+
148
+ if (format === 'rgb') {
149
+ const { r, g, b } = hsvToRgb(h, s, v);
150
+ return alpha >= 1
151
+ ? `rgb(${r}, ${g}, ${b})`
152
+ : `rgba(${r}, ${g}, ${b}, ${Math.round(alpha * 100) / 100})`;
153
+ }
154
+
155
+ if (format === 'hsl') {
156
+ const hsl = hsvToHsl(h, s, v);
157
+ const sat = Math.round(hsl.s * 100);
158
+ const light = Math.round(hsl.l * 100);
159
+ const hue = Math.round(hsl.h);
160
+ return alpha >= 1
161
+ ? `hsl(${hue}, ${sat}%, ${light}%)`
162
+ : `hsla(${hue}, ${sat}%, ${light}%, ${Math.round(alpha * 100) / 100})`;
163
+ }
164
+
165
+ return hsvToHex(h, s, v, alpha);
166
+ }
167
+
168
+ function expandShorthand(hex: string) {
169
+ let out = '';
170
+ for (let i = 0; i < hex.length; i++) out += hex[i]! + hex[i]!;
171
+ return out;
172
+ }
173
+
174
+ /**
175
+ * Reads `#rgb`, `#rgba`, `#rrggbb`, `#rrggbbaa`, `rgb()`, `rgba()`, `hsl()`
176
+ * and `hsla()`, and returns `null` for anything else — including the named
177
+ * colours, which would mean shipping a lookup table of 148 words to parse a
178
+ * string a caller almost never writes.
179
+ *
180
+ * `null` rather than a thrown error or a silent black: a picker handed a value
181
+ * it cannot read should keep the one it has, and only a distinguishable "no"
182
+ * lets the caller do that.
183
+ */
184
+ export function parseColor(input: string): HsvaColor | null {
185
+ const value = input.trim().toLowerCase();
186
+
187
+ if (value.startsWith('#')) {
188
+ let body = value.slice(1);
189
+ if (body.length === 3 || body.length === 4) body = expandShorthand(body);
190
+ if ((body.length !== 6 && body.length !== 8) || /[^0-9a-f]/.test(body)) return null;
191
+
192
+ const r = parseInt(body.slice(0, 2), 16);
193
+ const g = parseInt(body.slice(2, 4), 16);
194
+ const b = parseInt(body.slice(4, 6), 16);
195
+ const a = body.length === 8 ? parseInt(body.slice(6, 8), 16) / 255 : 1;
196
+ const { h, s, v } = rgbToHsv(r, g, b);
197
+ return { h, s, v, a };
198
+ }
199
+
200
+ const fn = /^(rgba?|hsla?)\(([^)]+)\)$/.exec(value);
201
+ if (!fn) return null;
202
+
203
+ // Both the comma and the space syntaxes, and the `/` that separates alpha in
204
+ // the space one.
205
+ const parts = fn[2]!.split(/[\s,/]+/).filter(Boolean);
206
+ if (parts.length < 3) return null;
207
+
208
+ const num = (raw: string, scale: number) => {
209
+ const n = parseFloat(raw);
210
+ if (Number.isNaN(n)) return null;
211
+ return raw.endsWith('%') ? (n / 100) * scale : n;
212
+ };
213
+
214
+ const a = parts[3] === undefined ? 1 : num(parts[3], 1);
215
+ if (a === null) return null;
216
+
217
+ if (fn[1]!.startsWith('rgb')) {
218
+ const r = num(parts[0]!, 255);
219
+ const g = num(parts[1]!, 255);
220
+ const b = num(parts[2]!, 255);
221
+ if (r === null || g === null || b === null) return null;
222
+ const { h, s, v } = rgbToHsv(r, g, b);
223
+ return { h, s, v, a: clamp01(a) };
224
+ }
225
+
226
+ const h = num(parts[0]!, 360);
227
+ const sl = num(parts[1]!, 1);
228
+ const l = num(parts[2]!, 1);
229
+ if (h === null || sl === null || l === null) return null;
230
+
231
+ // HSL to HSV, so the picker only ever stores the one model.
232
+ const light = clamp01(l);
233
+ const sat = clamp01(parts[1]!.endsWith('%') ? sl : sl > 1 ? sl / 100 : sl);
234
+ const v = light + sat * Math.min(light, 1 - light);
235
+ return {
236
+ h: wrapHue(h),
237
+ s: v === 0 ? 0 : 2 * (1 - light / v),
238
+ v,
239
+ a: clamp01(a),
240
+ };
241
+ }
242
+
243
+ /** Whether `parseColor` can read this string. */
244
+ export function isValidColor(input: string) {
245
+ return parseColor(input) !== null;
246
+ }
package/theme.css CHANGED
@@ -389,172 +389,185 @@
389
389
  * "All themes must have the same variables" otherwise.
390
390
  */
391
391
 
392
- /* Moon — monochrome and high-contrast: pure black/white, electric blue accent,
393
- hairline borders, tight corners. */
392
+ /*
393
+ * Moon — a near-black canvas under a lavender-blue accent, with elevation
394
+ * carried by a ladder of barely-separated surfaces and 1px hairlines
395
+ * rather than by shadow. Corners are tight and the type contrast is high.
396
+ *
397
+ * The character of this family lives in the *distance between* the
398
+ * surfaces, not in any one of them: #0f1011, #141516, #18191a and #191a1b
399
+ * are within a few points of each other, so a card on a panel on the
400
+ * canvas reads as three planes without any of them looking lighter than
401
+ * the room. Flattening that ladder to two values is what makes a dark
402
+ * theme look like a screenshot with the brightness turned down.
403
+ */
394
404
  @variant moon {
395
405
  --color-background: #ffffff;
396
- --color-foreground: #171717;
406
+ --color-foreground: #08090a;
397
407
 
398
408
  --color-card: #ffffff;
399
- --color-card-foreground: #171717;
409
+ --color-card-foreground: #08090a;
400
410
 
401
411
  --color-popover: #ffffff;
402
- --color-popover-foreground: #171717;
412
+ --color-popover-foreground: #08090a;
403
413
 
404
414
  --color-overlay: #ffffff;
405
- --color-overlay-foreground: #171717;
415
+ --color-overlay-foreground: #08090a;
406
416
 
407
- --color-primary: #171717;
417
+ --color-primary: #5e6ad2;
408
418
  --color-primary-foreground: #ffffff;
409
419
 
410
420
  --color-secondary: rgba(0, 0, 0, 0.05);
411
- --color-secondary-foreground: #171717;
421
+ --color-secondary-foreground: #08090a;
412
422
 
413
423
  --color-muted: rgba(0, 0, 0, 0.05);
414
- --color-muted-foreground: #666666;
424
+ --color-muted-foreground: #6b6f76;
415
425
 
416
- --color-accent: rgba(0, 0, 0, 0.05);
417
- --color-accent-foreground: #171717;
426
+ --color-accent: rgba(0, 0, 0, 0.06);
427
+ --color-accent-foreground: #08090a;
418
428
 
419
- --color-destructive: #e5484d;
429
+ --color-destructive: #eb5757;
420
430
  --color-destructive-foreground: #c62b30;
421
431
 
422
- --color-info: #0070f3;
423
- --color-info-foreground: #0060d1;
432
+ --color-info: #4ea7fc;
433
+ --color-info-foreground: #0b6ec4;
424
434
 
425
- --color-success: #45a557;
426
- --color-success-foreground: #297c3b;
435
+ --color-success: #27a644;
436
+ --color-success-foreground: #1c7a32;
427
437
 
428
- --color-warning: #f5a623;
429
- --color-warning-foreground: #a35200;
438
+ --color-warning: #f2c94c;
439
+ --color-warning-foreground: #8a6d0b;
430
440
 
431
- --color-border: rgba(0, 0, 0, 0.09);
441
+ --color-border: rgba(0, 0, 0, 0.08);
432
442
  --color-input: rgba(0, 0, 0, 0.12);
433
- --color-ring: #171717;
434
-
435
- --color-surface: #fafafa;
436
- --color-surface-secondary: #f4f4f4;
437
- --color-surface-tertiary: #ededed;
438
- --color-skeleton: rgba(0, 0, 0, 0.08);
439
-
440
- --color-info-soft: rgba(0, 112, 243, 0.08);
441
- --color-info-subtle: rgba(0, 112, 243, 0.06);
442
- --color-success-soft: rgba(69, 165, 87, 0.1);
443
- --color-success-subtle: rgba(69, 165, 87, 0.08);
444
- --color-warning-soft: rgba(245, 166, 35, 0.1);
445
- --color-warning-subtle: rgba(245, 166, 35, 0.08);
446
- --color-destructive-soft: rgba(229, 72, 77, 0.1);
447
- --color-destructive-subtle: rgba(229, 72, 77, 0.08);
443
+ --color-ring: #5e6ad2;
444
+
445
+ --color-surface: #f5f6f6;
446
+ --color-surface-secondary: #f6f7f7;
447
+ --color-surface-tertiary: #eeeff1;
448
+ --color-skeleton: rgba(0, 0, 0, 0.07);
449
+
450
+ --color-info-soft: rgba(78, 167, 252, 0.1);
451
+ --color-info-subtle: rgba(78, 167, 252, 0.08);
452
+ --color-success-soft: rgba(39, 166, 68, 0.1);
453
+ --color-success-subtle: rgba(39, 166, 68, 0.08);
454
+ --color-warning-soft: rgba(242, 201, 76, 0.14);
455
+ --color-warning-subtle: rgba(242, 201, 76, 0.1);
456
+ --color-destructive-soft: rgba(235, 87, 87, 0.1);
457
+ --color-destructive-subtle: rgba(235, 87, 87, 0.08);
448
458
 
449
459
  /* syntax colours */
450
- --color-code-keyword: #8250df;
451
- --color-code-string: #0a7d55;
452
- --color-code-number: #0550ae;
453
- --color-code-comment: #8b949e;
460
+ --color-code-keyword: #5e6ad2;
461
+ --color-code-string: #1c7a32;
462
+ --color-code-number: #0b6ec4;
463
+ --color-code-comment: #8a8f98;
454
464
  --color-code-function: #6639ba;
455
465
  --color-code-property: #953800;
456
- --color-code-punctuation: #57606a;
457
- --color-code-inserted: #0a7d55;
466
+ --color-code-punctuation: #62666d;
467
+ --color-code-inserted: #1c7a32;
458
468
  --color-code-deleted: #cf222e;
459
469
 
460
470
  /* chart series, in order of prominence */
461
- --color-chart-1: #0070f3;
462
- --color-chart-2: #171717;
463
- --color-chart-3: #7928ca;
464
- --color-chart-4: #f5a623;
465
- --color-chart-5: #0a9396;
466
-
471
+ --color-chart-1: #5e6ad2;
472
+ --color-chart-2: #4ea7fc;
473
+ --color-chart-3: #27a644;
474
+ --color-chart-4: #f2c94c;
475
+ --color-chart-5: #7a7fad;
476
+
467
477
  /* Moon shape scale */
468
- --radius-xs: 2px;
469
- --radius-sm: 4px;
470
- --radius-md: 5px;
471
- --radius-lg: 6px;
472
- --radius-xl: 8px;
473
- --radius-2xl: 10px;
474
- --radius-3xl: 14px;
478
+ --radius-xs: 4px;
479
+ --radius-sm: 6px;
480
+ --radius-md: 8px;
481
+ --radius-lg: 12px;
482
+ --radius-xl: 16px;
483
+ --radius-2xl: 24px;
484
+ --radius-3xl: 32px;
475
485
  }
476
486
 
477
487
  @variant moon-dark {
478
- --color-background: #000000;
479
- --color-foreground: #ededed;
488
+ --color-background: #010102;
489
+ --color-foreground: #f7f8f8;
480
490
 
481
- --color-card: #0a0a0a;
482
- --color-card-foreground: #ededed;
491
+ --color-card: #0f1011;
492
+ --color-card-foreground: #f7f8f8;
483
493
 
484
- --color-popover: #101010;
485
- --color-popover-foreground: #ededed;
494
+ --color-popover: #141516;
495
+ --color-popover-foreground: #f7f8f8;
486
496
 
487
- --color-overlay: #191919;
488
- --color-overlay-foreground: #ededed;
497
+ --color-overlay: #18191a;
498
+ --color-overlay-foreground: #f7f8f8;
489
499
 
490
- --color-primary: #ededed;
491
- --color-primary-foreground: #0a0a0a;
500
+ --color-primary: #5e6ad2;
501
+ --color-primary-foreground: #ffffff;
492
502
 
493
- --color-secondary: rgba(255, 255, 255, 0.09);
494
- --color-secondary-foreground: #ededed;
503
+ --color-secondary: rgba(255, 255, 255, 0.06);
504
+ --color-secondary-foreground: #f7f8f8;
495
505
 
496
- --color-muted: rgba(255, 255, 255, 0.09);
497
- --color-muted-foreground: #a1a1a1;
506
+ --color-muted: rgba(255, 255, 255, 0.06);
507
+ --color-muted-foreground: #8a8f98;
498
508
 
499
- --color-accent: rgba(255, 255, 255, 0.09);
500
- --color-accent-foreground: #ededed;
509
+ --color-accent: rgba(255, 255, 255, 0.08);
510
+ --color-accent-foreground: #f7f8f8;
501
511
 
502
- --color-destructive: #e5484d;
503
- --color-destructive-foreground: #ff6369;
512
+ --color-destructive: #eb5757;
513
+ --color-destructive-foreground: #ff8a8a;
504
514
 
505
- --color-info: #0070f3;
506
- --color-info-foreground: #52a8ff;
515
+ --color-info: #4ea7fc;
516
+ --color-info-foreground: #8ec5ff;
507
517
 
508
- --color-success: #45a557;
509
- --color-success-foreground: #62c073;
518
+ --color-success: #27a644;
519
+ --color-success-foreground: #4cc061;
510
520
 
511
- --color-warning: #f5a623;
512
- --color-warning-foreground: #f1a10d;
521
+ --color-warning: #f2c94c;
522
+ --color-warning-foreground: #f5d97a;
513
523
 
514
- --color-border: rgba(255, 255, 255, 0.09);
515
- --color-input: rgba(255, 255, 255, 0.14);
516
- --color-ring: #ededed;
524
+ /* The hairlines are opaque, not translucent: the surface ladder is only
525
+ a few points wide, so a border mixed with whatever is under it would
526
+ read as a different line on each of them. */
527
+ --color-border: #23252a;
528
+ --color-input: #34343a;
529
+ --color-ring: #5e6ad2;
517
530
 
518
- --color-surface: #0f0f0f;
519
- --color-surface-secondary: #161616;
520
- --color-surface-tertiary: #1d1d1d;
521
- --color-skeleton: rgba(255, 255, 255, 0.11);
531
+ --color-surface: #0f1011;
532
+ --color-surface-secondary: #141516;
533
+ --color-surface-tertiary: #18191a;
534
+ --color-skeleton: rgba(255, 255, 255, 0.08);
522
535
 
523
- --color-info-soft: rgba(0, 112, 243, 0.12);
524
- --color-info-subtle: rgba(0, 112, 243, 0.18);
525
- --color-success-soft: rgba(69, 165, 87, 0.1);
526
- --color-success-subtle: rgba(69, 165, 87, 0.16);
527
- --color-warning-soft: rgba(245, 166, 35, 0.1);
528
- --color-warning-subtle: rgba(245, 166, 35, 0.16);
529
- --color-destructive-soft: rgba(229, 72, 77, 0.1);
530
- --color-destructive-subtle: rgba(229, 72, 77, 0.16);
536
+ --color-info-soft: rgba(78, 167, 252, 0.16);
537
+ --color-info-subtle: rgba(78, 167, 252, 0.1);
538
+ --color-success-soft: rgba(39, 166, 68, 0.18);
539
+ --color-success-subtle: rgba(39, 166, 68, 0.12);
540
+ --color-warning-soft: rgba(242, 201, 76, 0.16);
541
+ --color-warning-subtle: rgba(242, 201, 76, 0.1);
542
+ --color-destructive-soft: rgba(235, 87, 87, 0.16);
543
+ --color-destructive-subtle: rgba(235, 87, 87, 0.1);
531
544
 
532
545
  /* syntax colours */
533
- --color-code-keyword: #d2a8ff;
534
- --color-code-string: #7ee787;
535
- --color-code-number: #79c0ff;
536
- --color-code-comment: #8b949e;
546
+ --color-code-keyword: #828fff;
547
+ --color-code-string: #4cc061;
548
+ --color-code-number: #8ec5ff;
549
+ --color-code-comment: #62666d;
537
550
  --color-code-function: #d2a8ff;
538
551
  --color-code-property: #ffa657;
539
- --color-code-punctuation: #8b949e;
540
- --color-code-inserted: #7ee787;
541
- --color-code-deleted: #ff7b72;
552
+ --color-code-punctuation: #8a8f98;
553
+ --color-code-inserted: #4cc061;
554
+ --color-code-deleted: #ff8a8a;
542
555
 
543
556
  /* chart series, in order of prominence */
544
- --color-chart-1: #3291ff;
545
- --color-chart-2: #ededed;
546
- --color-chart-3: #a855f7;
547
- --color-chart-4: #fbbf24;
548
- --color-chart-5: #2dd4bf;
549
-
557
+ --color-chart-1: #5e6ad2;
558
+ --color-chart-2: #4ea7fc;
559
+ --color-chart-3: #27a644;
560
+ --color-chart-4: #f2c94c;
561
+ --color-chart-5: #7a7fad;
562
+
550
563
  /* Moon shape scale */
551
- --radius-xs: 2px;
552
- --radius-sm: 4px;
553
- --radius-md: 5px;
554
- --radius-lg: 6px;
555
- --radius-xl: 8px;
556
- --radius-2xl: 10px;
557
- --radius-3xl: 14px;
564
+ --radius-xs: 4px;
565
+ --radius-sm: 6px;
566
+ --radius-md: 8px;
567
+ --radius-lg: 12px;
568
+ --radius-xl: 16px;
569
+ --radius-2xl: 24px;
570
+ --radius-3xl: 32px;
558
571
  }
559
572
 
560
573
  /* Grass — green accent on warm-neutral greys, with soft generous corners. */