@graineai/inapp-react-native 0.36.0 → 0.38.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/dist/theme.js ADDED
@@ -0,0 +1,2009 @@
1
+ export const DESIGN_SCHEMES = ["auto", "light", "dark"];
2
+ export const DESIGN_DENSITIES = ["compact", "comfortable", "spacious"];
3
+ export const DESIGN_SHADOWS = ["preset", "none", "soft", "medium", "strong", "hard"];
4
+ export const DESIGN_MOTIONS = ["preset", "none", "subtle", "lively"];
5
+ export const DESIGN_NEUTRALS = ["preset", "cool", "neutral", "warm"];
6
+ export const DESIGN_BUBBLES = ["filled", "outline", "minimal"];
7
+ export const LAUNCHER_SHAPES = ["circle", "squircle", "rounded-square", "square", "pill"];
8
+ export const ICON_STYLES = ["outline", "filled", "duotone", "sharp"];
9
+ const HEX6 = /^#?([0-9a-f]{6})$/i;
10
+ const HEX3 = /^#?([0-9a-f]{3})$/i;
11
+ export function normaliseHex(value) {
12
+ const s = String(value ?? "").trim();
13
+ const six = HEX6.exec(s);
14
+ if (six)
15
+ return `#${six[1].toUpperCase()}`;
16
+ const three = HEX3.exec(s);
17
+ if (three)
18
+ return `#${three[1].split("").map((c) => c + c).join("").toUpperCase()}`;
19
+ return null;
20
+ }
21
+ function rgb(hex) {
22
+ const n = parseInt((normaliseHex(hex) ?? "#000000").slice(1), 16);
23
+ return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
24
+ }
25
+ function toHex(r, g, b) {
26
+ const c = (v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0");
27
+ return `#${c(r)}${c(g)}${c(b)}`.toUpperCase();
28
+ }
29
+ export function mixHex(a, b, t) {
30
+ const [r1, g1, b1] = rgb(a);
31
+ const [r2, g2, b2] = rgb(b);
32
+ return toHex(r1 + (r2 - r1) * t, g1 + (g2 - g1) * t, b1 + (b2 - b1) * t);
33
+ }
34
+ export function luminanceOf(hex) {
35
+ const ch = (c) => {
36
+ const s = c / 255;
37
+ return s <= 0.03928 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
38
+ };
39
+ const [r, g, b] = rgb(hex);
40
+ return 0.2126 * ch(r) + 0.7152 * ch(g) + 0.0722 * ch(b);
41
+ }
42
+ export function contrastRatio(a, b) {
43
+ const la = luminanceOf(a);
44
+ const lb = luminanceOf(b);
45
+ return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
46
+ }
47
+ export function readableOn(bg, candidates = ["#FFFFFF", "#101318"]) {
48
+ let best = candidates[0];
49
+ for (const c of candidates)
50
+ if (contrastRatio(c, bg) > contrastRatio(best, bg))
51
+ best = c;
52
+ return best;
53
+ }
54
+ export function ensureContrast(fg, bg, min = 4.5) {
55
+ if (contrastRatio(fg, bg) >= min)
56
+ return fg;
57
+ const toward = luminanceOf(bg) > 0.5 ? "#000000" : "#FFFFFF";
58
+ for (let t = 0.1; t <= 1.0001; t += 0.1) {
59
+ const c = mixHex(fg, toward, t);
60
+ if (contrastRatio(c, bg) >= min)
61
+ return c;
62
+ }
63
+ return toward;
64
+ }
65
+ export const LAUNCHER_ICONS = [
66
+ { id: "waveform", label: "Waveform", stroke: true, path: "M2 13a2 2 0 0 0 2 -2V7a2 2 0 0 1 4 0v13a2 2 0 0 0 4 0V4a2 2 0 0 1 4 0v13a2 2 0 0 0 4 0v-4a2 2 0 0 1 2 -2" },
67
+ { id: "audio-lines", label: "Audio lines", stroke: true, path: "M2 10v3M6 6v11M10 3v18M14 8v7M18 5v13M22 10v3" },
68
+ { id: "sparkles", label: "Sparkles", stroke: true, path: "M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0 -1.594 1.594l-1.051 5.558a1 1 0 0 1 -1.966 0l-1.051 -5.558a2 2 0 0 0 -1.594 -1.594l-5.558 -1.051a1 1 0 0 1 0 -1.966l5.558 -1.051a2 2 0 0 0 1.594 -1.594zM20 2v4M22 4h-4M2 20a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z" },
69
+ { id: "microphone", label: "Microphone", stroke: true, path: "M12 19v3M19 10v2a7 7 0 0 1 -14 0v-2M12 2h0a3 3 0 0 1 3 3v7a3 3 0 0 1 -3 3h0a3 3 0 0 1 -3 -3v-7a3 3 0 0 1 3 -3z" },
70
+ { id: "message-circle", label: "Chat bubble", stroke: true, path: "M2.992 16.342a2 2 0 0 1 0.094 1.167l-1.065 3.29a1 1 0 0 0 1.236 1.168l3.413 -0.998a2 2 0 0 1 1.099 0.092a10 10 0 1 0 -4.777 -4.719" },
71
+ { id: "headset", label: "Headset", stroke: true, path: "M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2H5a2 2 0 0 1 -2 -2v-5Zm0 0a9 9 0 1 1 18 0m0 0v5a2 2 0 0 1 -2 2h-1a2 2 0 0 1 -2 -2v-3a2 2 0 0 1 2 -2h3ZM21 16v2a4 4 0 0 1 -4 4h-5" },
72
+ { id: "bot", label: "Bot", stroke: true, path: "M12 8V4H8M6 8h12a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-8a2 2 0 0 1 2 -2zM2 14h2M20 14h2M15 13v2M9 13v2" },
73
+ { id: "phone", label: "Phone", stroke: true, path: "M13.832 16.568a1 1 0 0 0 1.213 -0.303l0.355 -0.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2A18 18 0 0 1 2 4a2 2 0 0 1 2 -2h3a2 2 0 0 1 2 2v3a2 2 0 0 1 -0.8 1.6l-0.468 0.351a1 1 0 0 0 -0.292 1.233a14 14 0 0 0 6.392 6.384" },
74
+ { id: "zap", label: "Zap", stroke: true, path: "M15.914 4a1.5 1.5 0 0 0 -2.474 -1.561l-9 9A1.5 1.5 0 0 0 5.5 14h4.002a0.5 0.5 0 0 1 0.471 0.666L8.086 20a1.5 1.5 0 0 0 2.475 1.56l9 -9A1.5 1.5 0 0 0 18.5 10h-3.997a0.5 0.5 0 0 1 -0.472 -0.667z" },
75
+ { id: "star", label: "Star", stroke: true, path: "M11.525 2.295a0.53 0.53 0 0 1 0.95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166 0.756a0.53 0.53 0 0 1 0.294 0.904l-3.736 3.638a2.123 2.123 0 0 0 -0.611 1.878l0.882 5.14a0.53 0.53 0 0 1 -0.771 0.56l-4.618 -2.428a2.122 2.122 0 0 0 -1.973 0L6.396 21.01a0.53 0.53 0 0 1 -0.77 -0.56l0.881 -5.139a2.122 2.122 0 0 0 -0.611 -1.879L2.16 9.795a0.53 0.53 0 0 1 0.294 -0.906l5.165 -0.755a2.122 2.122 0 0 0 1.597 -1.16z" },
76
+ { id: "orbit", label: "Orbit", stroke: true, path: "M20.341 6.484A10 10 0 0 1 10.266 21.85M3.659 17.516A10 10 0 0 1 13.74 2.152M9 12a3 3 0 1 0 6 0a3 3 0 1 0 -6 0zM17 5a2 2 0 1 0 4 0a2 2 0 1 0 -4 0zM3 19a2 2 0 1 0 4 0a2 2 0 1 0 -4 0z" },
77
+ { id: "sparkle-filled", label: "Sparkle (filled)", stroke: false, path: "M19.5 13.5a1.479 1.479 0 0 1 -0.977 1.401L13.688 16.688l-1.781 4.839a1.492 1.492 0 0 1 -2.801 0L7.312 16.688l-4.839 -1.781a1.492 1.492 0 0 1 0 -2.801L7.312 10.312l1.781 -4.839a1.492 1.492 0 0 1 2.801 0L13.688 10.312l4.839 1.781A1.479 1.479 0 0 1 19.5 13.5ZM14.25 4.5h1.5V6a0.75 0.75 0 0 0 1.5 0V4.5h1.5a0.75 0.75 0 0 0 0 -1.5H17.25V1.5a0.75 0.75 0 0 0 -1.5 0V3H14.25a0.75 0.75 0 0 0 0 1.5Zm8.25 3h-0.75V6.75a0.75 0.75 0 0 0 -1.5 0v0.75h-0.75a0.75 0.75 0 0 0 0 1.5h0.75v0.75a0.75 0.75 0 0 0 1.5 0V9h0.75a0.75 0.75 0 0 0 0 -1.5Z" },
78
+ { id: "chat-dots-filled", label: "Chat dots (filled)", stroke: false, path: "M12 2.25A9.75 9.75 0 0 0 3.392 16.582L2.328 19.775a1.5 1.5 0 0 0 1.897 1.897l3.192 -1.064A9.75 9.75 0 1 0 12 2.25ZM7.875 13.125a1.125 1.125 0 1 1 1.125 -1.125A1.125 1.125 0 0 1 7.875 13.125Zm4.125 0a1.125 1.125 0 1 1 1.125 -1.125A1.125 1.125 0 0 1 12 13.125Zm4.125 0a1.125 1.125 0 1 1 1.125 -1.125A1.125 1.125 0 0 1 16.125 13.125Z" },
79
+ { id: "graphic-eq", label: "Voice equalizer (filled)", stroke: false, path: "M7 17v-10q0 -0.425 0.288 -0.713T8 6q0.425 0 0.713 0.288T9 7v10q0 0.425 -0.288 0.713T8 18q-0.425 0 -0.713 -0.288T7 17Zm4 4v-18q0 -0.425 0.288 -0.713T12 2q0.425 0 0.713 0.288T13 3v18q0 0.425 -0.288 0.713T12 22q-0.425 0 -0.713 -0.288T11 21ZM3 13v-2q0 -0.425 0.288 -0.713T4 10q0.425 0 0.713 0.288T5 11v2q0 0.425 -0.288 0.713T4 14q-0.425 0 -0.713 -0.288T3 13Zm12 4v-10q0 -0.425 0.288 -0.713T16 6q0.425 0 0.713 0.288T17 7v10q0 0.425 -0.288 0.713T16 18q-0.425 0 -0.713 -0.288T15 17Zm4 -4v-2q0 -0.425 0.288 -0.713T20 10q0.425 0 0.713 0.288T21 11v2q0 0.425 -0.288 0.713T20 14q-0.425 0 -0.713 -0.288T19 13Z" },
80
+ ];
81
+ export const SDK_ICONS = {
82
+ mic: { body: "M12 2.5a3.5 3.5 0 0 0-3.5 3.5v6a3.5 3.5 0 0 0 7 0V6A3.5 3.5 0 0 0 12 2.5z", lines: "M18.5 11.5a6.5 6.5 0 0 1-13 0M12 18v3.5" },
83
+ micOff: { body: "M12 2.5a3.5 3.5 0 0 0-3.5 3.5v6a3.5 3.5 0 0 0 7 0V6A3.5 3.5 0 0 0 12 2.5z", lines: "M18.5 11.5a6.5 6.5 0 0 1-13 0M12 18v3.5M4 4l16 16" },
84
+ end: { body: "M4.2 14.6c4.6-4.1 11-4.1 15.6 0 .6.5.6 1.4.1 2l-1.3 1.4c-.4.5-1.1.6-1.7.3l-2.2-1.2c-.5-.3-.8-.8-.7-1.4l.2-1.3a11 11 0 0 0-4.4 0l.2 1.3c.1.6-.2 1.1-.7 1.4l-2.2 1.2c-.6.3-1.3.2-1.7-.3L4.1 16.6c-.5-.6-.5-1.5.1-2z" },
85
+ send: { body: "M4 12 20 4l-4 16-4.5-6.5L4 12z", lines: "M11.5 13.5 20 4" },
86
+ chat: { body: "M20 12a8 8 0 0 1-11.6 7.1L4 20l1-4.2A8 8 0 1 1 20 12z" },
87
+ call: { lines: "M13.832 16.568a1 1 0 0 0 1.213 -0.303l0.355 -0.465A2 2 0 0 1 17 15h3a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2A18 18 0 0 1 2 4a2 2 0 0 1 2 -2h3a2 2 0 0 1 2 2v3a2 2 0 0 1 -0.8 1.6l-0.468 0.351a1 1 0 0 0 -0.292 1.233a14 14 0 0 0 6.392 6.384" },
88
+ chevron: { lines: "M6 15l6-6 6 6" },
89
+ close: { lines: "M6 6l12 12M18 6 6 18" },
90
+ };
91
+ export const DESIGN_FONTS = [
92
+ { family: "system", category: "sans", scripts: ["latin", "devanagari", "bengali", "tamil", "telugu", "kannada", "malayalam", "gujarati", "gurmukhi", "oriya"] },
93
+ { family: "Inter", category: "sans", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "greek", "greek-ext", "vietnamese"] },
94
+ { family: "Roboto", category: "sans", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "greek", "greek-ext", "vietnamese"] },
95
+ { family: "Geist", category: "sans", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "vietnamese"] },
96
+ { family: "IBM Plex Sans", category: "sans", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "greek", "vietnamese"] },
97
+ { family: "IBM Plex Sans Devanagari", category: "sans", scripts: ["devanagari", "latin", "latin-ext", "cyrillic-ext"] },
98
+ { family: "DM Sans", category: "sans", scripts: ["latin", "latin-ext"] },
99
+ { family: "Noto Sans", category: "sans", scripts: ["latin", "latin-ext", "devanagari", "cyrillic", "cyrillic-ext", "greek", "greek-ext", "vietnamese"] },
100
+ { family: "Noto Sans Devanagari", category: "sans", scripts: ["devanagari", "latin", "latin-ext"] },
101
+ { family: "Noto Sans Tamil", category: "sans", scripts: ["tamil", "latin", "latin-ext"] },
102
+ { family: "Mukta", category: "sans", scripts: ["devanagari", "latin", "latin-ext"] },
103
+ { family: "Hind", category: "sans", scripts: ["devanagari", "latin", "latin-ext"] },
104
+ { family: "Anek Devanagari", category: "sans", scripts: ["devanagari", "latin", "latin-ext"] },
105
+ { family: "Poppins", category: "sans", scripts: ["devanagari", "latin", "latin-ext"] },
106
+ { family: "Baloo 2", category: "display", scripts: ["devanagari", "latin", "latin-ext", "vietnamese"] },
107
+ { family: "Nunito", category: "sans", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "vietnamese"] },
108
+ { family: "Atkinson Hyperlegible Next", category: "sans", scripts: ["latin", "latin-ext"] },
109
+ { family: "Source Serif 4", category: "serif", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "greek", "vietnamese"] },
110
+ { family: "Newsreader", category: "serif", scripts: ["latin", "latin-ext", "vietnamese"] },
111
+ { family: "Fraunces", category: "serif", scripts: ["latin", "latin-ext", "vietnamese"] },
112
+ { family: "Playfair Display", category: "serif", scripts: ["latin", "latin-ext", "cyrillic", "vietnamese"] },
113
+ { family: "Tiro Devanagari Hindi", category: "serif", scripts: ["devanagari", "latin", "latin-ext"] },
114
+ { family: "Noto Serif Devanagari", category: "serif", scripts: ["devanagari", "latin", "latin-ext"] },
115
+ { family: "Martel", category: "serif", scripts: ["devanagari", "latin", "latin-ext"] },
116
+ { family: "JetBrains Mono", category: "mono", scripts: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "greek", "vietnamese"] },
117
+ ];
118
+ const GRAINE_CLASSIC = {
119
+ id: "graine-classic",
120
+ name: "Graine Classic",
121
+ tagline: "The look your widget has today",
122
+ family: "graine",
123
+ inspiredBy: ["Graine"],
124
+ font: {
125
+ body: "system", heading: "system",
126
+ scale: { caption: 12, body: 15, title: 17, display: 22 },
127
+ weights: { body: 400, strong: 600, title: 600 },
128
+ letterSpacing: { body: 0, title: -0.01 },
129
+ lineHeight: { body: 1.45, title: 1.25 },
130
+ },
131
+ shape: { radius: { sm: 8, md: 12, lg: 18, xl: 24 }, borderWidth: 1, launcher: "circle" },
132
+ spacing: { unit: 4, cardPadding: 14, gap: 10 },
133
+ elevation: {
134
+ card: { y: 2, blur: 8, spread: 0, opacity: 0.08, color: "#000000" },
135
+ floating: { y: 8, blur: 24, spread: 0, opacity: 0.16, color: "#000000" },
136
+ hardOffset: null,
137
+ },
138
+ motion: { durationMs: 200, easing: "standard", bounce: 0 },
139
+ icons: { style: "outline", stroke: 2, launcher: "waveform" },
140
+ glass: null,
141
+ bubbles: "filled",
142
+ colors: {
143
+ light: {
144
+ background: "#F7F7F5", surface: "#FFFFFF", surfaceRaised: "#FFFFFF", text: "#101318", textMuted: "#5F6672",
145
+ border: "#E5E4E0", accent: "#318CE7", onAccent: "#FFFFFF", success: "#16A34A", warning: "#B45309", danger: "#DC2626",
146
+ userBubble: "#318CE7", userBubbleText: "#FFFFFF", agentBubble: "#F1F1EF", agentBubbleText: "#101318", scrim: "#000000",
147
+ },
148
+ dark: {
149
+ background: "#0E0F11", surface: "#17181B", surfaceRaised: "#1F2024", text: "#F5F5F4", textMuted: "#A0A5AE",
150
+ border: "#2C2E33", accent: "#318CE7", onAccent: "#FFFFFF", success: "#22C55E", warning: "#F59E0B", danger: "#F87171",
151
+ userBubble: "#318CE7", userBubbleText: "#FFFFFF", agentBubble: "#23252A", agentBubbleText: "#F5F5F4", scrim: "#000000",
152
+ },
153
+ },
154
+ };
155
+ const P_CHAT_NEUTRAL = {
156
+ "id": "chat-neutral",
157
+ "name": "Chat Neutral",
158
+ "tagline": "Quiet greys and system type; your brand shows up only in the accent.",
159
+ "family": "native",
160
+ "inspiredBy": [
161
+ "OpenAI Apps SDK UI (openai/apps-sdk-ui)",
162
+ "OpenAI Apps SDK design guidelines"
163
+ ],
164
+ "font": {
165
+ "body": "system",
166
+ "heading": "system",
167
+ "scale": {
168
+ "caption": 12,
169
+ "body": 16,
170
+ "title": 18,
171
+ "display": 24
172
+ },
173
+ "weights": {
174
+ "body": 400,
175
+ "strong": 600,
176
+ "title": 600
177
+ },
178
+ "letterSpacing": {
179
+ "body": 0,
180
+ "title": 0
181
+ },
182
+ "lineHeight": {
183
+ "body": 1.5,
184
+ "title": 1.44
185
+ }
186
+ },
187
+ "shape": {
188
+ "radius": {
189
+ "sm": 6,
190
+ "md": 12,
191
+ "lg": 16,
192
+ "xl": 24
193
+ },
194
+ "borderWidth": 1,
195
+ "launcher": "circle"
196
+ },
197
+ "spacing": {
198
+ "unit": 4,
199
+ "cardPadding": 16,
200
+ "gap": 12
201
+ },
202
+ "elevation": {
203
+ "card": {
204
+ "y": 1,
205
+ "blur": 2,
206
+ "spread": -1,
207
+ "opacity": 0.08,
208
+ "color": "#000000"
209
+ },
210
+ "floating": {
211
+ "y": 8,
212
+ "blur": 16,
213
+ "spread": -4,
214
+ "opacity": 0.12,
215
+ "color": "#000000"
216
+ },
217
+ "hardOffset": null
218
+ },
219
+ "motion": {
220
+ "durationMs": 150,
221
+ "easing": "standard",
222
+ "bounce": 0
223
+ },
224
+ "icons": {
225
+ "style": "outline",
226
+ "stroke": 2,
227
+ "launcher": "sparkles"
228
+ },
229
+ "glass": null,
230
+ "bubbles": "minimal",
231
+ "colors": {
232
+ "light": {
233
+ "background": "#FFFFFF",
234
+ "surface": "#F9F9F9",
235
+ "surfaceRaised": "#FFFFFF",
236
+ "text": "#0D0D0D",
237
+ "textMuted": "#5D5D5D",
238
+ "border": "#E7E7E7",
239
+ "accent": "#181818",
240
+ "onAccent": "#FFFFFF",
241
+ "success": "#00692A",
242
+ "warning": "#923B0F",
243
+ "danger": "#911E1B",
244
+ "userBubble": "#EDEDED",
245
+ "userBubbleText": "#0D0D0D",
246
+ "agentBubble": "#FFFFFF",
247
+ "agentBubbleText": "#0D0D0D",
248
+ "scrim": "#000000"
249
+ },
250
+ "dark": {
251
+ "background": "#212121",
252
+ "surface": "#181818",
253
+ "surfaceRaised": "#303030",
254
+ "text": "#FFFFFF",
255
+ "textMuted": "#AFAFAF",
256
+ "border": "#3C3C3C",
257
+ "accent": "#F3F3F3",
258
+ "onAccent": "#0D0D0D",
259
+ "success": "#04B84C",
260
+ "warning": "#E25507",
261
+ "danger": "#E02E2A",
262
+ "userBubble": "#303030",
263
+ "userBubbleText": "#FFFFFF",
264
+ "agentBubble": "#212121",
265
+ "agentBubbleText": "#FFFFFF",
266
+ "scrim": "#000000"
267
+ }
268
+ }
269
+ };
270
+ const P_MATERIAL_3 = {
271
+ "id": "material-3",
272
+ "name": "Material You",
273
+ "tagline": "Google's Material 3: tonal surfaces, soft corners, springy motion.",
274
+ "family": "native",
275
+ "inspiredBy": [
276
+ "Material Design 3 (material-components/material-web tokens)"
277
+ ],
278
+ "font": {
279
+ "body": "Roboto",
280
+ "heading": "Roboto",
281
+ "scale": {
282
+ "caption": 12,
283
+ "body": 16,
284
+ "title": 22,
285
+ "display": 28
286
+ },
287
+ "weights": {
288
+ "body": 400,
289
+ "strong": 500,
290
+ "title": 400
291
+ },
292
+ "letterSpacing": {
293
+ "body": 0.0313,
294
+ "title": 0
295
+ },
296
+ "lineHeight": {
297
+ "body": 1.5,
298
+ "title": 1.27
299
+ }
300
+ },
301
+ "shape": {
302
+ "radius": {
303
+ "sm": 8,
304
+ "md": 12,
305
+ "lg": 16,
306
+ "xl": 28
307
+ },
308
+ "borderWidth": 1,
309
+ "launcher": "rounded-square"
310
+ },
311
+ "spacing": {
312
+ "unit": 4,
313
+ "cardPadding": 16,
314
+ "gap": 8
315
+ },
316
+ "elevation": {
317
+ "card": {
318
+ "y": 1,
319
+ "blur": 3,
320
+ "spread": 1,
321
+ "opacity": 0.15,
322
+ "color": "#000000"
323
+ },
324
+ "floating": {
325
+ "y": 4,
326
+ "blur": 8,
327
+ "spread": 3,
328
+ "opacity": 0.15,
329
+ "color": "#000000"
330
+ },
331
+ "hardOffset": null
332
+ },
333
+ "motion": {
334
+ "durationMs": 240,
335
+ "easing": "spring",
336
+ "bounce": 0.1
337
+ },
338
+ "icons": {
339
+ "style": "outline",
340
+ "stroke": 2,
341
+ "launcher": "graphic-eq"
342
+ },
343
+ "glass": null,
344
+ "bubbles": "filled",
345
+ "colors": {
346
+ "light": {
347
+ "background": "#FEF7FF",
348
+ "surface": "#F7F2FA",
349
+ "surfaceRaised": "#ECE6F0",
350
+ "text": "#1D1B20",
351
+ "textMuted": "#49454F",
352
+ "border": "#CAC4D0",
353
+ "accent": "#6750A4",
354
+ "onAccent": "#FFFFFF",
355
+ "success": "#287630",
356
+ "warning": "#8A5700",
357
+ "danger": "#B3261E",
358
+ "userBubble": "#EADDFF",
359
+ "userBubbleText": "#4F378B",
360
+ "agentBubble": "#E6E0E9",
361
+ "agentBubbleText": "#1D1B20",
362
+ "scrim": "#000000"
363
+ },
364
+ "dark": {
365
+ "background": "#141218",
366
+ "surface": "#1D1B20",
367
+ "surfaceRaised": "#2B2930",
368
+ "text": "#E6E0E9",
369
+ "textMuted": "#CAC4D0",
370
+ "border": "#49454F",
371
+ "accent": "#D0BCFF",
372
+ "onAccent": "#381E72",
373
+ "success": "#9BDC9C",
374
+ "warning": "#F3BE74",
375
+ "danger": "#F2B8B5",
376
+ "userBubble": "#4F378B",
377
+ "userBubbleText": "#EADDFF",
378
+ "agentBubble": "#36343B",
379
+ "agentBubbleText": "#E6E0E9",
380
+ "scrim": "#000000"
381
+ }
382
+ }
383
+ };
384
+ const P_IOS_NATIVE = {
385
+ "id": "ios-native",
386
+ "name": "iOS Native",
387
+ "tagline": "Feels like it shipped with the iPhone: SF type, system blue, grey bubbles.",
388
+ "family": "native",
389
+ "inspiredBy": [
390
+ "Apple Human Interface Guidelines (iOS system colors, Dynamic Type, SF Pro)"
391
+ ],
392
+ "font": {
393
+ "body": "system",
394
+ "heading": "system",
395
+ "scale": {
396
+ "caption": 12,
397
+ "body": 17,
398
+ "title": 20,
399
+ "display": 28
400
+ },
401
+ "weights": {
402
+ "body": 400,
403
+ "strong": 600,
404
+ "title": 600
405
+ },
406
+ "letterSpacing": {
407
+ "body": -0.026,
408
+ "title": -0.023
409
+ },
410
+ "lineHeight": {
411
+ "body": 1.29,
412
+ "title": 1.25
413
+ }
414
+ },
415
+ "shape": {
416
+ "radius": {
417
+ "sm": 8,
418
+ "md": 12,
419
+ "lg": 18,
420
+ "xl": 26
421
+ },
422
+ "borderWidth": 0.5,
423
+ "launcher": "circle"
424
+ },
425
+ "spacing": {
426
+ "unit": 4,
427
+ "cardPadding": 16,
428
+ "gap": 8
429
+ },
430
+ "elevation": {
431
+ "card": {
432
+ "y": 1,
433
+ "blur": 3,
434
+ "spread": 0,
435
+ "opacity": 0.06,
436
+ "color": "#000000"
437
+ },
438
+ "floating": {
439
+ "y": 8,
440
+ "blur": 24,
441
+ "spread": 0,
442
+ "opacity": 0.12,
443
+ "color": "#000000"
444
+ },
445
+ "hardOffset": null
446
+ },
447
+ "motion": {
448
+ "durationMs": 500,
449
+ "easing": "spring",
450
+ "bounce": 0
451
+ },
452
+ "icons": {
453
+ "style": "outline",
454
+ "stroke": 1.5,
455
+ "launcher": "waveform"
456
+ },
457
+ "glass": null,
458
+ "bubbles": "filled",
459
+ "colors": {
460
+ "light": {
461
+ "background": "#FFFFFF",
462
+ "surface": "#F2F2F7",
463
+ "surfaceRaised": "#FFFFFF",
464
+ "text": "#000000",
465
+ "textMuted": "#6C6C70",
466
+ "border": "#C6C6C8",
467
+ "accent": "#1E6EF4",
468
+ "onAccent": "#FFFFFF",
469
+ "success": "#008932",
470
+ "warning": "#C55300",
471
+ "danger": "#FF383C",
472
+ "userBubble": "#1E6EF4",
473
+ "userBubbleText": "#FFFFFF",
474
+ "agentBubble": "#E5E5EA",
475
+ "agentBubbleText": "#000000",
476
+ "scrim": "#000000"
477
+ },
478
+ "dark": {
479
+ "background": "#000000",
480
+ "surface": "#1C1C1E",
481
+ "surfaceRaised": "#2C2C2E",
482
+ "text": "#FFFFFF",
483
+ "textMuted": "#8D8D93",
484
+ "border": "#323235",
485
+ "accent": "#1E6EF4",
486
+ "onAccent": "#FFFFFF",
487
+ "success": "#30D158",
488
+ "warning": "#FF9230",
489
+ "danger": "#FF4245",
490
+ "userBubble": "#1E6EF4",
491
+ "userBubbleText": "#FFFFFF",
492
+ "agentBubble": "#2C2C2E",
493
+ "agentBubbleText": "#FFFFFF",
494
+ "scrim": "#000000"
495
+ }
496
+ }
497
+ };
498
+ const P_MINIMAL_MONO = {
499
+ "id": "minimal-mono",
500
+ "name": "Minimal Mono",
501
+ "tagline": "Black, white and one hairline border. Lets the words do the work.",
502
+ "family": "modern",
503
+ "inspiredBy": [
504
+ "shadcn/ui default theme (shadcn-ui/ui)",
505
+ "Vercel Geist typeface (vercel/geist-font)",
506
+ "Tailwind CSS palette"
507
+ ],
508
+ "font": {
509
+ "body": "Geist",
510
+ "heading": "Geist",
511
+ "scale": {
512
+ "caption": 12,
513
+ "body": 14,
514
+ "title": 16,
515
+ "display": 24
516
+ },
517
+ "weights": {
518
+ "body": 400,
519
+ "strong": 500,
520
+ "title": 600
521
+ },
522
+ "letterSpacing": {
523
+ "body": 0,
524
+ "title": -0.025
525
+ },
526
+ "lineHeight": {
527
+ "body": 1.43,
528
+ "title": 1.5
529
+ }
530
+ },
531
+ "shape": {
532
+ "radius": {
533
+ "sm": 6,
534
+ "md": 8,
535
+ "lg": 10,
536
+ "xl": 14
537
+ },
538
+ "borderWidth": 1,
539
+ "launcher": "rounded-square"
540
+ },
541
+ "spacing": {
542
+ "unit": 4,
543
+ "cardPadding": 24,
544
+ "gap": 24
545
+ },
546
+ "elevation": {
547
+ "card": {
548
+ "y": 1,
549
+ "blur": 3,
550
+ "spread": 0,
551
+ "opacity": 0.1,
552
+ "color": "#000000"
553
+ },
554
+ "floating": {
555
+ "y": 10,
556
+ "blur": 15,
557
+ "spread": -3,
558
+ "opacity": 0.1,
559
+ "color": "#000000"
560
+ },
561
+ "hardOffset": null
562
+ },
563
+ "motion": {
564
+ "durationMs": 150,
565
+ "easing": "standard",
566
+ "bounce": 0
567
+ },
568
+ "icons": {
569
+ "style": "outline",
570
+ "stroke": 2,
571
+ "launcher": "audio-lines"
572
+ },
573
+ "glass": null,
574
+ "bubbles": "filled",
575
+ "colors": {
576
+ "light": {
577
+ "background": "#FFFFFF",
578
+ "surface": "#FFFFFF",
579
+ "surfaceRaised": "#FFFFFF",
580
+ "text": "#0A0A0A",
581
+ "textMuted": "#737373",
582
+ "border": "#E5E5E5",
583
+ "accent": "#171717",
584
+ "onAccent": "#FAFAFA",
585
+ "success": "#00813A",
586
+ "warning": "#B55200",
587
+ "danger": "#E40016",
588
+ "userBubble": "#171717",
589
+ "userBubbleText": "#FAFAFA",
590
+ "agentBubble": "#F5F5F5",
591
+ "agentBubbleText": "#171717",
592
+ "scrim": "#000000"
593
+ },
594
+ "dark": {
595
+ "background": "#0A0A0A",
596
+ "surface": "#171717",
597
+ "surfaceRaised": "#171717",
598
+ "text": "#FAFAFA",
599
+ "textMuted": "#A1A1A1",
600
+ "border": "#232323",
601
+ "accent": "#E5E5E5",
602
+ "onAccent": "#171717",
603
+ "success": "#05DF72",
604
+ "warning": "#FABC00",
605
+ "danger": "#FF6568",
606
+ "userBubble": "#E5E5E5",
607
+ "userBubbleText": "#171717",
608
+ "agentBubble": "#262626",
609
+ "agentBubbleText": "#FAFAFA",
610
+ "scrim": "#000000"
611
+ }
612
+ }
613
+ };
614
+ const P_FLUENT_2 = {
615
+ "id": "fluent-2",
616
+ "name": "Fluent",
617
+ "tagline": "Microsoft's calm, businesslike Fluent 2: familiar from Teams and Office.",
618
+ "family": "enterprise",
619
+ "inspiredBy": [
620
+ "Microsoft Fluent 2 (microsoft/fluentui @fluentui/tokens)"
621
+ ],
622
+ "font": {
623
+ "body": "system",
624
+ "heading": "system",
625
+ "scale": {
626
+ "caption": 12,
627
+ "body": 14,
628
+ "title": 20,
629
+ "display": 28
630
+ },
631
+ "weights": {
632
+ "body": 400,
633
+ "strong": 600,
634
+ "title": 600
635
+ },
636
+ "letterSpacing": {
637
+ "body": 0,
638
+ "title": 0
639
+ },
640
+ "lineHeight": {
641
+ "body": 1.43,
642
+ "title": 1.4
643
+ }
644
+ },
645
+ "shape": {
646
+ "radius": {
647
+ "sm": 2,
648
+ "md": 4,
649
+ "lg": 6,
650
+ "xl": 8
651
+ },
652
+ "borderWidth": 1,
653
+ "launcher": "circle"
654
+ },
655
+ "spacing": {
656
+ "unit": 4,
657
+ "cardPadding": 12,
658
+ "gap": 12
659
+ },
660
+ "elevation": {
661
+ "card": {
662
+ "y": 2,
663
+ "blur": 4,
664
+ "spread": 0,
665
+ "opacity": 0.14,
666
+ "color": "#000000"
667
+ },
668
+ "floating": {
669
+ "y": 8,
670
+ "blur": 16,
671
+ "spread": 0,
672
+ "opacity": 0.14,
673
+ "color": "#000000"
674
+ },
675
+ "hardOffset": null
676
+ },
677
+ "motion": {
678
+ "durationMs": 200,
679
+ "easing": "standard",
680
+ "bounce": 0
681
+ },
682
+ "icons": {
683
+ "style": "outline",
684
+ "stroke": 1.5,
685
+ "launcher": "message-circle"
686
+ },
687
+ "glass": null,
688
+ "bubbles": "filled",
689
+ "colors": {
690
+ "light": {
691
+ "background": "#FAFAFA",
692
+ "surface": "#FFFFFF",
693
+ "surfaceRaised": "#FFFFFF",
694
+ "text": "#242424",
695
+ "textMuted": "#616161",
696
+ "border": "#E0E0E0",
697
+ "accent": "#0F6CBD",
698
+ "onAccent": "#FFFFFF",
699
+ "success": "#0E700E",
700
+ "warning": "#BC4B09",
701
+ "danger": "#B10E1C",
702
+ "userBubble": "#EBF3FC",
703
+ "userBubbleText": "#242424",
704
+ "agentBubble": "#FFFFFF",
705
+ "agentBubbleText": "#242424",
706
+ "scrim": "#000000"
707
+ },
708
+ "dark": {
709
+ "background": "#1F1F1F",
710
+ "surface": "#292929",
711
+ "surfaceRaised": "#292929",
712
+ "text": "#FFFFFF",
713
+ "textMuted": "#ADADAD",
714
+ "border": "#525252",
715
+ "accent": "#115EA3",
716
+ "onAccent": "#FFFFFF",
717
+ "success": "#54B054",
718
+ "warning": "#FAA06B",
719
+ "danger": "#DC626D",
720
+ "userBubble": "#082338",
721
+ "userBubbleText": "#FFFFFF",
722
+ "agentBubble": "#292929",
723
+ "agentBubbleText": "#FFFFFF",
724
+ "scrim": "#000000"
725
+ }
726
+ }
727
+ };
728
+ const P_CARBON = {
729
+ "id": "carbon",
730
+ "name": "Enterprise Grid",
731
+ "tagline": "IBM Carbon: square, precise and serious, built for trust.",
732
+ "family": "enterprise",
733
+ "inspiredBy": [
734
+ "IBM Carbon Design System v11 (carbon-design-system/carbon)"
735
+ ],
736
+ "font": {
737
+ "body": "IBM Plex Sans",
738
+ "heading": "IBM Plex Sans",
739
+ "scale": {
740
+ "caption": 12,
741
+ "body": 14,
742
+ "title": 20,
743
+ "display": 28
744
+ },
745
+ "weights": {
746
+ "body": 400,
747
+ "strong": 600,
748
+ "title": 400
749
+ },
750
+ "letterSpacing": {
751
+ "body": 0.0114,
752
+ "title": 0
753
+ },
754
+ "lineHeight": {
755
+ "body": 1.43,
756
+ "title": 1.4
757
+ }
758
+ },
759
+ "shape": {
760
+ "radius": {
761
+ "sm": 0,
762
+ "md": 2,
763
+ "lg": 4,
764
+ "xl": 8
765
+ },
766
+ "borderWidth": 1,
767
+ "launcher": "square"
768
+ },
769
+ "spacing": {
770
+ "unit": 8,
771
+ "cardPadding": 16,
772
+ "gap": 8
773
+ },
774
+ "elevation": {
775
+ "card": {
776
+ "y": 0,
777
+ "blur": 0,
778
+ "spread": 0,
779
+ "opacity": 0,
780
+ "color": "#000000"
781
+ },
782
+ "floating": {
783
+ "y": 2,
784
+ "blur": 6,
785
+ "spread": 0,
786
+ "opacity": 0.3,
787
+ "color": "#000000"
788
+ },
789
+ "hardOffset": null
790
+ },
791
+ "motion": {
792
+ "durationMs": 150,
793
+ "easing": "standard",
794
+ "bounce": 0
795
+ },
796
+ "icons": {
797
+ "style": "sharp",
798
+ "stroke": 1.5,
799
+ "launcher": "headset"
800
+ },
801
+ "glass": null,
802
+ "bubbles": "filled",
803
+ "colors": {
804
+ "light": {
805
+ "background": "#FFFFFF",
806
+ "surface": "#F4F4F4",
807
+ "surfaceRaised": "#FFFFFF",
808
+ "text": "#161616",
809
+ "textMuted": "#525252",
810
+ "border": "#C6C6C6",
811
+ "accent": "#0F62FE",
812
+ "onAccent": "#FFFFFF",
813
+ "success": "#24A148",
814
+ "warning": "#AB8800",
815
+ "danger": "#DA1E28",
816
+ "userBubble": "#E0E0E0",
817
+ "userBubbleText": "#161616",
818
+ "agentBubble": "#FFFFFF",
819
+ "agentBubbleText": "#161616",
820
+ "scrim": "#000000"
821
+ },
822
+ "dark": {
823
+ "background": "#161616",
824
+ "surface": "#262626",
825
+ "surfaceRaised": "#393939",
826
+ "text": "#F4F4F4",
827
+ "textMuted": "#C6C6C6",
828
+ "border": "#525252",
829
+ "accent": "#0F62FE",
830
+ "onAccent": "#FFFFFF",
831
+ "success": "#42BE65",
832
+ "warning": "#F1C21B",
833
+ "danger": "#FA4D56",
834
+ "userBubble": "#393939",
835
+ "userBubbleText": "#F4F4F4",
836
+ "agentBubble": "#262626",
837
+ "agentBubbleText": "#F4F4F4",
838
+ "scrim": "#000000"
839
+ }
840
+ }
841
+ };
842
+ const P_LIQUID_GLASS = {
843
+ "id": "liquid-glass",
844
+ "name": "Liquid Glass",
845
+ "tagline": "Frosted, floating panels that let the page glow through.",
846
+ "family": "modern",
847
+ "inspiredBy": [
848
+ "Apple Liquid Glass & standard materials (HIG Materials)",
849
+ "css.glass glassmorphism generator"
850
+ ],
851
+ "font": {
852
+ "body": "system",
853
+ "heading": "system",
854
+ "scale": {
855
+ "caption": 12,
856
+ "body": 17,
857
+ "title": 20,
858
+ "display": 34
859
+ },
860
+ "weights": {
861
+ "body": 400,
862
+ "strong": 600,
863
+ "title": 600
864
+ },
865
+ "letterSpacing": {
866
+ "body": -0.026,
867
+ "title": -0.023
868
+ },
869
+ "lineHeight": {
870
+ "body": 1.29,
871
+ "title": 1.25
872
+ }
873
+ },
874
+ "shape": {
875
+ "radius": {
876
+ "sm": 12,
877
+ "md": 20,
878
+ "lg": 28,
879
+ "xl": 36
880
+ },
881
+ "borderWidth": 1,
882
+ "launcher": "pill"
883
+ },
884
+ "spacing": {
885
+ "unit": 4,
886
+ "cardPadding": 16,
887
+ "gap": 12
888
+ },
889
+ "elevation": {
890
+ "card": {
891
+ "y": 2,
892
+ "blur": 12,
893
+ "spread": 0,
894
+ "opacity": 0.08,
895
+ "color": "#000000"
896
+ },
897
+ "floating": {
898
+ "y": 4,
899
+ "blur": 30,
900
+ "spread": 0,
901
+ "opacity": 0.1,
902
+ "color": "#000000"
903
+ },
904
+ "hardOffset": null
905
+ },
906
+ "motion": {
907
+ "durationMs": 500,
908
+ "easing": "spring",
909
+ "bounce": 0.15
910
+ },
911
+ "icons": {
912
+ "style": "outline",
913
+ "stroke": 1.5,
914
+ "launcher": "sparkle-filled"
915
+ },
916
+ "glass": {
917
+ "blur": 20,
918
+ "surfaceOpacity": 0.72
919
+ },
920
+ "bubbles": "filled",
921
+ "colors": {
922
+ "light": {
923
+ "background": "#F2F2F7",
924
+ "surface": "#FFFFFF",
925
+ "surfaceRaised": "#FFFFFF",
926
+ "text": "#000000",
927
+ "textMuted": "#3C3C43",
928
+ "border": "#C6C6C8",
929
+ "accent": "#6155F5",
930
+ "onAccent": "#FFFFFF",
931
+ "success": "#008932",
932
+ "warning": "#C55300",
933
+ "danger": "#FF383C",
934
+ "userBubble": "#6155F5",
935
+ "userBubbleText": "#FFFFFF",
936
+ "agentBubble": "#FFFFFF",
937
+ "agentBubbleText": "#000000",
938
+ "scrim": "#000000"
939
+ },
940
+ "dark": {
941
+ "background": "#000000",
942
+ "surface": "#1C1C1E",
943
+ "surfaceRaised": "#2C2C2E",
944
+ "text": "#FFFFFF",
945
+ "textMuted": "#EBEBF5",
946
+ "border": "#38383A",
947
+ "accent": "#6155F5",
948
+ "onAccent": "#FFFFFF",
949
+ "success": "#30D158",
950
+ "warning": "#FF9230",
951
+ "danger": "#FF4245",
952
+ "userBubble": "#6155F5",
953
+ "userBubbleText": "#FFFFFF",
954
+ "agentBubble": "#2C2C2E",
955
+ "agentBubbleText": "#FFFFFF",
956
+ "scrim": "#000000"
957
+ }
958
+ }
959
+ };
960
+ const P_SOFT_PLAYFUL = {
961
+ "id": "soft-playful",
962
+ "name": "Soft & Playful",
963
+ "tagline": "Rounded, pastel and friendly, like a cupcake shop that answers the phone.",
964
+ "family": "modern",
965
+ "inspiredBy": [
966
+ "daisyUI \"cupcake\" theme (saadeghi/daisyui)"
967
+ ],
968
+ "font": {
969
+ "body": "Nunito",
970
+ "heading": "Baloo 2",
971
+ "scale": {
972
+ "caption": 12,
973
+ "body": 16,
974
+ "title": 20,
975
+ "display": 28
976
+ },
977
+ "weights": {
978
+ "body": 400,
979
+ "strong": 700,
980
+ "title": 700
981
+ },
982
+ "letterSpacing": {
983
+ "body": 0,
984
+ "title": 0
985
+ },
986
+ "lineHeight": {
987
+ "body": 1.5,
988
+ "title": 1.25
989
+ }
990
+ },
991
+ "shape": {
992
+ "radius": {
993
+ "sm": 16,
994
+ "md": 32,
995
+ "lg": 16,
996
+ "xl": 24
997
+ },
998
+ "borderWidth": 2,
999
+ "launcher": "circle"
1000
+ },
1001
+ "spacing": {
1002
+ "unit": 4,
1003
+ "cardPadding": 24,
1004
+ "gap": 8
1005
+ },
1006
+ "elevation": {
1007
+ "card": {
1008
+ "y": 1,
1009
+ "blur": 3,
1010
+ "spread": 0,
1011
+ "opacity": 0.1,
1012
+ "color": "#291334"
1013
+ },
1014
+ "floating": {
1015
+ "y": 10,
1016
+ "blur": 15,
1017
+ "spread": -3,
1018
+ "opacity": 0.12,
1019
+ "color": "#291334"
1020
+ },
1021
+ "hardOffset": null
1022
+ },
1023
+ "motion": {
1024
+ "durationMs": 400,
1025
+ "easing": "spring",
1026
+ "bounce": 0.3
1027
+ },
1028
+ "icons": {
1029
+ "style": "filled",
1030
+ "stroke": 1.5,
1031
+ "launcher": "chat-dots-filled"
1032
+ },
1033
+ "glass": null,
1034
+ "bubbles": "filled",
1035
+ "colors": {
1036
+ "light": {
1037
+ "background": "#FAF7F5",
1038
+ "surface": "#EFEAE6",
1039
+ "surfaceRaised": "#FAF7F5",
1040
+ "text": "#291334",
1041
+ "textMuted": "#64536A",
1042
+ "border": "#E7E2DF",
1043
+ "accent": "#44EBD3",
1044
+ "onAccent": "#005D58",
1045
+ "success": "#009768",
1046
+ "warning": "#A87F00",
1047
+ "danger": "#FE1C55",
1048
+ "userBubble": "#44EBD3",
1049
+ "userBubbleText": "#005D58",
1050
+ "agentBubble": "#E7E2DF",
1051
+ "agentBubbleText": "#291334",
1052
+ "scrim": "#262629"
1053
+ },
1054
+ "dark": {
1055
+ "background": "#262629",
1056
+ "surface": "#303033",
1057
+ "surfaceRaised": "#3A3A3E",
1058
+ "text": "#E4E4E7",
1059
+ "textMuted": "#ABABAE",
1060
+ "border": "#47474B",
1061
+ "accent": "#44EBD3",
1062
+ "onAccent": "#005D58",
1063
+ "success": "#00B77F",
1064
+ "warning": "#E8B100",
1065
+ "danger": "#FE1C55",
1066
+ "userBubble": "#44EBD3",
1067
+ "userBubbleText": "#005D58",
1068
+ "agentBubble": "#3A3A3E",
1069
+ "agentBubbleText": "#E4E4E7",
1070
+ "scrim": "#000000"
1071
+ }
1072
+ }
1073
+ };
1074
+ const P_NEO_BRUTALISM = {
1075
+ "id": "neo-brutalism",
1076
+ "name": "Neo-Brutalist",
1077
+ "tagline": "Thick black outlines, hard shadows, loud colour. Impossible to ignore.",
1078
+ "family": "expressive",
1079
+ "inspiredBy": [
1080
+ "neobrutalism.dev (ekmas/neobrutalism-components)"
1081
+ ],
1082
+ "font": {
1083
+ "body": "DM Sans",
1084
+ "heading": "DM Sans",
1085
+ "scale": {
1086
+ "caption": 12,
1087
+ "body": 16,
1088
+ "title": 20,
1089
+ "display": 32
1090
+ },
1091
+ "weights": {
1092
+ "body": 500,
1093
+ "strong": 700,
1094
+ "title": 700
1095
+ },
1096
+ "letterSpacing": {
1097
+ "body": 0,
1098
+ "title": 0
1099
+ },
1100
+ "lineHeight": {
1101
+ "body": 1.5,
1102
+ "title": 1.2
1103
+ }
1104
+ },
1105
+ "shape": {
1106
+ "radius": {
1107
+ "sm": 5,
1108
+ "md": 5,
1109
+ "lg": 5,
1110
+ "xl": 5
1111
+ },
1112
+ "borderWidth": 2,
1113
+ "launcher": "rounded-square"
1114
+ },
1115
+ "spacing": {
1116
+ "unit": 4,
1117
+ "cardPadding": 24,
1118
+ "gap": 24
1119
+ },
1120
+ "elevation": {
1121
+ "card": {
1122
+ "y": 0,
1123
+ "blur": 0,
1124
+ "spread": 0,
1125
+ "opacity": 0,
1126
+ "color": "#000000"
1127
+ },
1128
+ "floating": {
1129
+ "y": 0,
1130
+ "blur": 0,
1131
+ "spread": 0,
1132
+ "opacity": 0,
1133
+ "color": "#000000"
1134
+ },
1135
+ "hardOffset": {
1136
+ "x": 4,
1137
+ "y": 4
1138
+ }
1139
+ },
1140
+ "motion": {
1141
+ "durationMs": 150,
1142
+ "easing": "standard",
1143
+ "bounce": 0
1144
+ },
1145
+ "icons": {
1146
+ "style": "outline",
1147
+ "stroke": 2,
1148
+ "launcher": "zap"
1149
+ },
1150
+ "glass": null,
1151
+ "bubbles": "filled",
1152
+ "colors": {
1153
+ "light": {
1154
+ "background": "#DCEBFE",
1155
+ "surface": "#FFFFFF",
1156
+ "surfaceRaised": "#FFFFFF",
1157
+ "text": "#000000",
1158
+ "textMuted": "#383838",
1159
+ "border": "#000000",
1160
+ "accent": "#5294FF",
1161
+ "onAccent": "#000000",
1162
+ "success": "#009951",
1163
+ "warning": "#A08100",
1164
+ "danger": "#F24045",
1165
+ "userBubble": "#5294FF",
1166
+ "userBubbleText": "#000000",
1167
+ "agentBubble": "#FFFFFF",
1168
+ "agentBubbleText": "#000000",
1169
+ "scrim": "#000000"
1170
+ },
1171
+ "dark": {
1172
+ "background": "#20294B",
1173
+ "surface": "#1F1F1F",
1174
+ "surfaceRaised": "#1F1F1F",
1175
+ "text": "#E6E6E6",
1176
+ "textMuted": "#BABCC4",
1177
+ "border": "#000000",
1178
+ "accent": "#5294FF",
1179
+ "onAccent": "#000000",
1180
+ "success": "#05E17A",
1181
+ "warning": "#FACC00",
1182
+ "danger": "#FF4D50",
1183
+ "userBubble": "#5294FF",
1184
+ "userBubbleText": "#000000",
1185
+ "agentBubble": "#1F1F1F",
1186
+ "agentBubbleText": "#E6E6E6",
1187
+ "scrim": "#000000"
1188
+ }
1189
+ }
1190
+ };
1191
+ const P_EDITORIAL = {
1192
+ "id": "editorial",
1193
+ "name": "Editorial",
1194
+ "tagline": "Reads like a well-set magazine: serif type, warm paper, ink-red accents.",
1195
+ "family": "expressive",
1196
+ "inspiredBy": [
1197
+ "Radix Themes (radix-ui/themes)",
1198
+ "Radix Colors sand + ruby (radix-ui/colors)"
1199
+ ],
1200
+ "font": {
1201
+ "body": "Source Serif 4",
1202
+ "heading": "Newsreader",
1203
+ "scale": {
1204
+ "caption": 12,
1205
+ "body": 16,
1206
+ "title": 24,
1207
+ "display": 35
1208
+ },
1209
+ "weights": {
1210
+ "body": 400,
1211
+ "strong": 700,
1212
+ "title": 700
1213
+ },
1214
+ "letterSpacing": {
1215
+ "body": 0,
1216
+ "title": -0.00625
1217
+ },
1218
+ "lineHeight": {
1219
+ "body": 1.5,
1220
+ "title": 1.25
1221
+ }
1222
+ },
1223
+ "shape": {
1224
+ "radius": {
1225
+ "sm": 4,
1226
+ "md": 6,
1227
+ "lg": 8,
1228
+ "xl": 12
1229
+ },
1230
+ "borderWidth": 1,
1231
+ "launcher": "circle"
1232
+ },
1233
+ "spacing": {
1234
+ "unit": 4,
1235
+ "cardPadding": 24,
1236
+ "gap": 16
1237
+ },
1238
+ "elevation": {
1239
+ "card": {
1240
+ "y": 1,
1241
+ "blur": 3,
1242
+ "spread": 0,
1243
+ "opacity": 0.05,
1244
+ "color": "#000000"
1245
+ },
1246
+ "floating": {
1247
+ "y": 12,
1248
+ "blur": 60,
1249
+ "spread": 0,
1250
+ "opacity": 0.15,
1251
+ "color": "#000000"
1252
+ },
1253
+ "hardOffset": null
1254
+ },
1255
+ "motion": {
1256
+ "durationMs": 120,
1257
+ "easing": "standard",
1258
+ "bounce": 0
1259
+ },
1260
+ "icons": {
1261
+ "style": "outline",
1262
+ "stroke": 1.5,
1263
+ "launcher": "message-circle"
1264
+ },
1265
+ "glass": null,
1266
+ "bubbles": "minimal",
1267
+ "colors": {
1268
+ "light": {
1269
+ "background": "#FDFDFC",
1270
+ "surface": "#F9F9F8",
1271
+ "surfaceRaised": "#FFFFFF",
1272
+ "text": "#21201C",
1273
+ "textMuted": "#63635E",
1274
+ "border": "#DAD9D6",
1275
+ "accent": "#CA244D",
1276
+ "onAccent": "#FFFFFF",
1277
+ "success": "#2A7E3B",
1278
+ "warning": "#AB6400",
1279
+ "danger": "#CE2C31",
1280
+ "userBubble": "#FEEAED",
1281
+ "userBubbleText": "#64172B",
1282
+ "agentBubble": "#F1F0EF",
1283
+ "agentBubbleText": "#21201C",
1284
+ "scrim": "#000000"
1285
+ },
1286
+ "dark": {
1287
+ "background": "#111110",
1288
+ "surface": "#191918",
1289
+ "surfaceRaised": "#222221",
1290
+ "text": "#EEEEEC",
1291
+ "textMuted": "#B5B3AD",
1292
+ "border": "#3B3A37",
1293
+ "accent": "#CA244D",
1294
+ "onAccent": "#FFFFFF",
1295
+ "success": "#71D083",
1296
+ "warning": "#FFCA16",
1297
+ "danger": "#FF9592",
1298
+ "userBubble": "#3A141E",
1299
+ "userBubbleText": "#FED2E1",
1300
+ "agentBubble": "#222221",
1301
+ "agentBubbleText": "#EEEEEC",
1302
+ "scrim": "#000000"
1303
+ }
1304
+ }
1305
+ };
1306
+ const P_LUXURY = {
1307
+ "id": "luxury",
1308
+ "name": "Black & Gold",
1309
+ "tagline": "Gold on near-black with high-contrast serif titles. Quietly expensive.",
1310
+ "family": "expressive",
1311
+ "inspiredBy": [
1312
+ "daisyUI \"luxury\" theme (saadeghi/daisyui)"
1313
+ ],
1314
+ "font": {
1315
+ "body": "Poppins",
1316
+ "heading": "Playfair Display",
1317
+ "scale": {
1318
+ "caption": 12,
1319
+ "body": 15,
1320
+ "title": 22,
1321
+ "display": 32
1322
+ },
1323
+ "weights": {
1324
+ "body": 400,
1325
+ "strong": 500,
1326
+ "title": 600
1327
+ },
1328
+ "letterSpacing": {
1329
+ "body": 0.01,
1330
+ "title": 0
1331
+ },
1332
+ "lineHeight": {
1333
+ "body": 1.6,
1334
+ "title": 1.2
1335
+ }
1336
+ },
1337
+ "shape": {
1338
+ "radius": {
1339
+ "sm": 16,
1340
+ "md": 8,
1341
+ "lg": 16,
1342
+ "xl": 24
1343
+ },
1344
+ "borderWidth": 1,
1345
+ "launcher": "circle"
1346
+ },
1347
+ "spacing": {
1348
+ "unit": 4,
1349
+ "cardPadding": 24,
1350
+ "gap": 8
1351
+ },
1352
+ "elevation": {
1353
+ "card": {
1354
+ "y": 1,
1355
+ "blur": 3,
1356
+ "spread": 0,
1357
+ "opacity": 0.3,
1358
+ "color": "#000000"
1359
+ },
1360
+ "floating": {
1361
+ "y": 12,
1362
+ "blur": 32,
1363
+ "spread": -4,
1364
+ "opacity": 0.45,
1365
+ "color": "#000000"
1366
+ },
1367
+ "hardOffset": null
1368
+ },
1369
+ "motion": {
1370
+ "durationMs": 300,
1371
+ "easing": "emphasized",
1372
+ "bounce": 0
1373
+ },
1374
+ "icons": {
1375
+ "style": "outline",
1376
+ "stroke": 1.25,
1377
+ "launcher": "star"
1378
+ },
1379
+ "glass": null,
1380
+ "bubbles": "filled",
1381
+ "colors": {
1382
+ "light": {
1383
+ "background": "#FAF7EE",
1384
+ "surface": "#F3EEE0",
1385
+ "surfaceRaised": "#FFFFFF",
1386
+ "text": "#09090B",
1387
+ "textMuted": "#565554",
1388
+ "border": "#E2CEB1",
1389
+ "accent": "#DCA54D",
1390
+ "onAccent": "#09090B",
1391
+ "success": "#5A9700",
1392
+ "warning": "#968900",
1393
+ "danger": "#E6585A",
1394
+ "userBubble": "#DCA54D",
1395
+ "userBubbleText": "#09090B",
1396
+ "agentBubble": "#F3EEE0",
1397
+ "agentBubbleText": "#09090B",
1398
+ "scrim": "#000000"
1399
+ },
1400
+ "dark": {
1401
+ "background": "#09090B",
1402
+ "surface": "#171618",
1403
+ "surfaceRaised": "#1E1D1F",
1404
+ "text": "#FFE7A4",
1405
+ "textMuted": "#A2936A",
1406
+ "border": "#331800",
1407
+ "accent": "#DCA54D",
1408
+ "onAccent": "#09090B",
1409
+ "success": "#87D03A",
1410
+ "warning": "#E2D563",
1411
+ "danger": "#FF6F6F",
1412
+ "userBubble": "#DCA54D",
1413
+ "userBubbleText": "#09090B",
1414
+ "agentBubble": "#1E1D1F",
1415
+ "agentBubbleText": "#DCA54D",
1416
+ "scrim": "#000000"
1417
+ }
1418
+ }
1419
+ };
1420
+ const P_RETRO_TERMINAL = {
1421
+ "id": "retro-terminal",
1422
+ "name": "Retro Terminal",
1423
+ "tagline": "Green phosphor on black, monospace everything. For builders and tinkerers.",
1424
+ "family": "expressive",
1425
+ "inspiredBy": [
1426
+ "terminal.css (Gioni06/terminal.css)",
1427
+ "cool-retro-term profiles (Swordfish90/cool-retro-term)"
1428
+ ],
1429
+ "font": {
1430
+ "body": "JetBrains Mono",
1431
+ "heading": "JetBrains Mono",
1432
+ "scale": {
1433
+ "caption": 12,
1434
+ "body": 15,
1435
+ "title": 15,
1436
+ "display": 20
1437
+ },
1438
+ "weights": {
1439
+ "body": 400,
1440
+ "strong": 700,
1441
+ "title": 600
1442
+ },
1443
+ "letterSpacing": {
1444
+ "body": 0,
1445
+ "title": 0
1446
+ },
1447
+ "lineHeight": {
1448
+ "body": 1.4,
1449
+ "title": 1.4
1450
+ }
1451
+ },
1452
+ "shape": {
1453
+ "radius": {
1454
+ "sm": 0,
1455
+ "md": 0,
1456
+ "lg": 0,
1457
+ "xl": 0
1458
+ },
1459
+ "borderWidth": 1,
1460
+ "launcher": "square"
1461
+ },
1462
+ "spacing": {
1463
+ "unit": 10,
1464
+ "cardPadding": 10,
1465
+ "gap": 10
1466
+ },
1467
+ "elevation": {
1468
+ "card": {
1469
+ "y": 0,
1470
+ "blur": 0,
1471
+ "spread": 0,
1472
+ "opacity": 0,
1473
+ "color": "#000000"
1474
+ },
1475
+ "floating": {
1476
+ "y": 0,
1477
+ "blur": 0,
1478
+ "spread": 0,
1479
+ "opacity": 0,
1480
+ "color": "#000000"
1481
+ },
1482
+ "hardOffset": null
1483
+ },
1484
+ "motion": {
1485
+ "durationMs": 0,
1486
+ "easing": "none",
1487
+ "bounce": 0
1488
+ },
1489
+ "icons": {
1490
+ "style": "sharp",
1491
+ "stroke": 2,
1492
+ "launcher": "bot"
1493
+ },
1494
+ "glass": null,
1495
+ "bubbles": "outline",
1496
+ "colors": {
1497
+ "light": {
1498
+ "background": "#F2F2EC",
1499
+ "surface": "#E7E7E1",
1500
+ "surfaceRaised": "#F2F2EC",
1501
+ "text": "#101010",
1502
+ "textMuted": "#65686B",
1503
+ "border": "#727578",
1504
+ "accent": "#007E3D",
1505
+ "onAccent": "#F2F2EC",
1506
+ "success": "#00964A",
1507
+ "warning": "#CB6600",
1508
+ "danger": "#D20962",
1509
+ "userBubble": "#007E3D",
1510
+ "userBubbleText": "#F2F2EC",
1511
+ "agentBubble": "#F2F2EC",
1512
+ "agentBubbleText": "#101010",
1513
+ "scrim": "#000000"
1514
+ },
1515
+ "dark": {
1516
+ "background": "#000000",
1517
+ "surface": "#010C06",
1518
+ "surfaceRaised": "#01140A",
1519
+ "text": "#0CCC68",
1520
+ "textMuted": "#088B47",
1521
+ "border": "#055C2F",
1522
+ "accent": "#0CCC68",
1523
+ "onAccent": "#000000",
1524
+ "success": "#0CCC68",
1525
+ "warning": "#FF8100",
1526
+ "danger": "#FF3C74",
1527
+ "userBubble": "#0CCC68",
1528
+ "userBubbleText": "#000000",
1529
+ "agentBubble": "#000000",
1530
+ "agentBubbleText": "#0CCC68",
1531
+ "scrim": "#000000"
1532
+ }
1533
+ }
1534
+ };
1535
+ const P_WARM_EARTHY = {
1536
+ "id": "warm-earthy",
1537
+ "name": "Warm & Earthy",
1538
+ "tagline": "Caramel, cream and coffee tones with soft serif titles. Human and grounded.",
1539
+ "family": "expressive",
1540
+ "inspiredBy": [
1541
+ "daisyUI \"caramellatte\" (light) and \"coffee\" (dark) themes (saadeghi/daisyui)"
1542
+ ],
1543
+ "font": {
1544
+ "body": "Mukta",
1545
+ "heading": "Fraunces",
1546
+ "scale": {
1547
+ "caption": 12,
1548
+ "body": 16,
1549
+ "title": 22,
1550
+ "display": 30
1551
+ },
1552
+ "weights": {
1553
+ "body": 400,
1554
+ "strong": 600,
1555
+ "title": 600
1556
+ },
1557
+ "letterSpacing": {
1558
+ "body": 0,
1559
+ "title": -0.01
1560
+ },
1561
+ "lineHeight": {
1562
+ "body": 1.5,
1563
+ "title": 1.2
1564
+ }
1565
+ },
1566
+ "shape": {
1567
+ "radius": {
1568
+ "sm": 32,
1569
+ "md": 8,
1570
+ "lg": 16,
1571
+ "xl": 24
1572
+ },
1573
+ "borderWidth": 2,
1574
+ "launcher": "squircle"
1575
+ },
1576
+ "spacing": {
1577
+ "unit": 4,
1578
+ "cardPadding": 24,
1579
+ "gap": 8
1580
+ },
1581
+ "elevation": {
1582
+ "card": {
1583
+ "y": 1,
1584
+ "blur": 3,
1585
+ "spread": 0,
1586
+ "opacity": 0.12,
1587
+ "color": "#7C2808"
1588
+ },
1589
+ "floating": {
1590
+ "y": 12,
1591
+ "blur": 32,
1592
+ "spread": -8,
1593
+ "opacity": 0.2,
1594
+ "color": "#7C2808"
1595
+ },
1596
+ "hardOffset": null
1597
+ },
1598
+ "motion": {
1599
+ "durationMs": 200,
1600
+ "easing": "standard",
1601
+ "bounce": 0
1602
+ },
1603
+ "icons": {
1604
+ "style": "duotone",
1605
+ "stroke": 1.5,
1606
+ "launcher": "orbit"
1607
+ },
1608
+ "glass": null,
1609
+ "bubbles": "filled",
1610
+ "colors": {
1611
+ "light": {
1612
+ "background": "#FFF7ED",
1613
+ "surface": "#FEECD3",
1614
+ "surfaceRaised": "#FFF7ED",
1615
+ "text": "#7C2808",
1616
+ "textMuted": "#99563A",
1617
+ "border": "#FFD6A7",
1618
+ "accent": "#8C3F27",
1619
+ "onAccent": "#FFD6A7",
1620
+ "success": "#005F45",
1621
+ "warning": "#AD8100",
1622
+ "danger": "#ED5157",
1623
+ "userBubble": "#8C3F27",
1624
+ "userBubbleText": "#FFD6A7",
1625
+ "agentBubble": "#FFD6A7",
1626
+ "agentBubbleText": "#7C2808",
1627
+ "scrim": "#000000"
1628
+ },
1629
+ "dark": {
1630
+ "background": "#261B25",
1631
+ "surface": "#1E151D",
1632
+ "surfaceRaised": "#30252E",
1633
+ "text": "#C59F61",
1634
+ "textMuted": "#A58555",
1635
+ "border": "#433330",
1636
+ "accent": "#DB924C",
1637
+ "onAccent": "#110802",
1638
+ "success": "#9DB787",
1639
+ "warning": "#FFD260",
1640
+ "danger": "#FC9581",
1641
+ "userBubble": "#DB924C",
1642
+ "userBubbleText": "#110802",
1643
+ "agentBubble": "#120A11",
1644
+ "agentBubbleText": "#C59F61",
1645
+ "scrim": "#000000"
1646
+ }
1647
+ }
1648
+ };
1649
+ const P_HIGH_CONTRAST = {
1650
+ "id": "high-contrast",
1651
+ "name": "High Contrast",
1652
+ "tagline": "Big type, strong edges, no fades. Easy to read for everyone, everywhere.",
1653
+ "family": "enterprise",
1654
+ "inspiredBy": [
1655
+ "GitHub Primer light/dark high-contrast themes (primer/primitives)",
1656
+ "GOV.UK Design System (alphagov/govuk-frontend)"
1657
+ ],
1658
+ "font": {
1659
+ "body": "Atkinson Hyperlegible Next",
1660
+ "heading": "Atkinson Hyperlegible Next",
1661
+ "scale": {
1662
+ "caption": 16,
1663
+ "body": 19,
1664
+ "title": 24,
1665
+ "display": 36
1666
+ },
1667
+ "weights": {
1668
+ "body": 400,
1669
+ "strong": 700,
1670
+ "title": 700
1671
+ },
1672
+ "letterSpacing": {
1673
+ "body": 0,
1674
+ "title": 0
1675
+ },
1676
+ "lineHeight": {
1677
+ "body": 1.32,
1678
+ "title": 1.25
1679
+ }
1680
+ },
1681
+ "shape": {
1682
+ "radius": {
1683
+ "sm": 0,
1684
+ "md": 0,
1685
+ "lg": 0,
1686
+ "xl": 0
1687
+ },
1688
+ "borderWidth": 2,
1689
+ "launcher": "square"
1690
+ },
1691
+ "spacing": {
1692
+ "unit": 5,
1693
+ "cardPadding": 20,
1694
+ "gap": 15
1695
+ },
1696
+ "elevation": {
1697
+ "card": {
1698
+ "y": 1,
1699
+ "blur": 2,
1700
+ "spread": 0,
1701
+ "opacity": 0.03,
1702
+ "color": "#010409"
1703
+ },
1704
+ "floating": {
1705
+ "y": 6,
1706
+ "blur": 18,
1707
+ "spread": 0,
1708
+ "opacity": 0.12,
1709
+ "color": "#25292E"
1710
+ },
1711
+ "hardOffset": null
1712
+ },
1713
+ "motion": {
1714
+ "durationMs": 0,
1715
+ "easing": "none",
1716
+ "bounce": 0
1717
+ },
1718
+ "icons": {
1719
+ "style": "filled",
1720
+ "stroke": 2,
1721
+ "launcher": "microphone"
1722
+ },
1723
+ "glass": null,
1724
+ "bubbles": "filled",
1725
+ "colors": {
1726
+ "light": {
1727
+ "background": "#FFFFFF",
1728
+ "surface": "#E6EAEF",
1729
+ "surfaceRaised": "#FFFFFF",
1730
+ "text": "#010409",
1731
+ "textMuted": "#454C54",
1732
+ "border": "#454C54",
1733
+ "accent": "#0349B4",
1734
+ "onAccent": "#FFFFFF",
1735
+ "success": "#04591F",
1736
+ "warning": "#603700",
1737
+ "danger": "#960D1E",
1738
+ "userBubble": "#0349B4",
1739
+ "userBubbleText": "#FFFFFF",
1740
+ "agentBubble": "#E6EAEF",
1741
+ "agentBubbleText": "#010409",
1742
+ "scrim": "#393F46"
1743
+ },
1744
+ "dark": {
1745
+ "background": "#010409",
1746
+ "surface": "#151B23",
1747
+ "surfaceRaised": "#212830",
1748
+ "text": "#FFFFFF",
1749
+ "textMuted": "#B7BDC8",
1750
+ "border": "#B7BDC8",
1751
+ "accent": "#194FB1",
1752
+ "onAccent": "#FFFFFF",
1753
+ "success": "#2BD853",
1754
+ "warning": "#F0B72F",
1755
+ "danger": "#FF9492",
1756
+ "userBubble": "#194FB1",
1757
+ "userBubbleText": "#FFFFFF",
1758
+ "agentBubble": "#151B23",
1759
+ "agentBubbleText": "#FFFFFF",
1760
+ "scrim": "#D1D7E0"
1761
+ }
1762
+ }
1763
+ };
1764
+ export const DESIGN_PRESETS = [GRAINE_CLASSIC, P_CHAT_NEUTRAL, P_MATERIAL_3, P_IOS_NATIVE, P_MINIMAL_MONO, P_FLUENT_2, P_CARBON, P_LIQUID_GLASS, P_SOFT_PLAYFUL, P_NEO_BRUTALISM, P_EDITORIAL, P_LUXURY, P_RETRO_TERMINAL, P_WARM_EARTHY, P_HIGH_CONTRAST];
1765
+ export const DEFAULT_DESIGN_PRESET = "graine-classic";
1766
+ export function designPreset(id) {
1767
+ const want = String(id ?? "").trim().toLowerCase();
1768
+ return DESIGN_PRESETS.find((p) => p.id === want) ?? DESIGN_PRESETS[0];
1769
+ }
1770
+ function pick(v, allowed) {
1771
+ const s = String(v ?? "").trim().toLowerCase();
1772
+ return allowed.includes(s) ? s : undefined;
1773
+ }
1774
+ function fontFamily(v) {
1775
+ const s = String(v ?? "").trim();
1776
+ if (!s)
1777
+ return undefined;
1778
+ const hit = DESIGN_FONTS.find((f) => f.family.toLowerCase() === s.toLowerCase());
1779
+ return hit ? hit.family : undefined;
1780
+ }
1781
+ export function normaliseDesignConfig(raw) {
1782
+ const r = (raw && typeof raw === "object" ? raw : {});
1783
+ const out = { preset: designPreset(r.preset).id };
1784
+ const accent = normaliseHex(r.accent);
1785
+ if (accent)
1786
+ out.accent = accent;
1787
+ const scheme = pick(r.scheme, DESIGN_SCHEMES);
1788
+ if (scheme)
1789
+ out.scheme = scheme;
1790
+ if (typeof r.roundness === "number" && Number.isFinite(r.roundness)) {
1791
+ out.roundness = Math.round(Math.max(0, Math.min(2, r.roundness)) * 100) / 100;
1792
+ }
1793
+ const font = fontFamily(r.font);
1794
+ if (font)
1795
+ out.font = font;
1796
+ const heading = fontFamily(r.headingFont);
1797
+ if (heading)
1798
+ out.headingFont = heading;
1799
+ const density = pick(r.density, DESIGN_DENSITIES);
1800
+ if (density)
1801
+ out.density = density;
1802
+ const shadow = pick(r.shadow, DESIGN_SHADOWS);
1803
+ if (shadow)
1804
+ out.shadow = shadow;
1805
+ const motion = pick(r.motion, DESIGN_MOTIONS);
1806
+ if (motion)
1807
+ out.motion = motion;
1808
+ const neutral = pick(r.neutral, DESIGN_NEUTRALS);
1809
+ if (neutral)
1810
+ out.neutral = neutral;
1811
+ if (typeof r.glass === "boolean")
1812
+ out.glass = r.glass;
1813
+ const bubbles = pick(r.bubbles, DESIGN_BUBBLES);
1814
+ if (bubbles)
1815
+ out.bubbles = bubbles;
1816
+ const icon = String(r.launcherIcon ?? "").trim().toLowerCase();
1817
+ if (icon === "logo" || LAUNCHER_ICONS.some((i) => i.id === icon))
1818
+ out.launcherIcon = icon;
1819
+ const shape = pick(r.launcherShape, LAUNCHER_SHAPES);
1820
+ if (shape)
1821
+ out.launcherShape = shape;
1822
+ const iconStyle = pick(r.iconStyle, ICON_STYLES);
1823
+ if (iconStyle)
1824
+ out.iconStyle = iconStyle;
1825
+ return out;
1826
+ }
1827
+ export function designFromAppearance(appearance) {
1828
+ const a = (appearance && typeof appearance === "object" ? appearance : {});
1829
+ if (a.design && typeof a.design === "object")
1830
+ return normaliseDesignConfig(a.design);
1831
+ const legacy = { preset: DEFAULT_DESIGN_PRESET };
1832
+ if (normaliseHex(a.accent))
1833
+ legacy.accent = a.accent;
1834
+ const scheme = pick(a.theme, DESIGN_SCHEMES);
1835
+ if (scheme)
1836
+ legacy.scheme = scheme;
1837
+ const radius = typeof a.radius === "number" ? a.radius : Number(a.radius);
1838
+ if (Number.isFinite(radius) && radius >= 0)
1839
+ legacy.roundness = radius / GRAINE_CLASSIC.shape.radius.lg;
1840
+ return normaliseDesignConfig(legacy);
1841
+ }
1842
+ export function legacyAppearanceFor(config) {
1843
+ const tokens = resolveTokens(config, "light");
1844
+ return { accent: tokens.colors.accent, radius: tokens.shape.radius.lg, theme: config.scheme ?? "auto" };
1845
+ }
1846
+ const DENSITY_SCALE = { compact: 0.8, comfortable: 1, spacious: 1.25 };
1847
+ export const ON_ACCENT_MIN = 3;
1848
+ const SHADOWS = {
1849
+ none: { card: null, floating: null },
1850
+ soft: {
1851
+ card: { y: 1, blur: 4, spread: 0, opacity: 0.06, color: "#000000" },
1852
+ floating: { y: 6, blur: 18, spread: 0, opacity: 0.12, color: "#000000" },
1853
+ },
1854
+ medium: {
1855
+ card: { y: 2, blur: 10, spread: 0, opacity: 0.1, color: "#000000" },
1856
+ floating: { y: 10, blur: 28, spread: 0, opacity: 0.18, color: "#000000" },
1857
+ },
1858
+ strong: {
1859
+ card: { y: 4, blur: 16, spread: 0, opacity: 0.16, color: "#000000" },
1860
+ floating: { y: 16, blur: 40, spread: -4, opacity: 0.28, color: "#000000" },
1861
+ },
1862
+ };
1863
+ const MOTIONS = {
1864
+ none: { durationMs: 0, easing: "none", bounce: 0 },
1865
+ subtle: { durationMs: 150, easing: "standard", bounce: 0 },
1866
+ lively: { durationMs: 320, easing: "spring", bounce: 0.3 },
1867
+ };
1868
+ const NEUTRAL_TINT = {
1869
+ cool: "#3B6FD9",
1870
+ neutral: "#808080",
1871
+ warm: "#D9822B",
1872
+ };
1873
+ function tintNeutrals(c, neutral, scheme) {
1874
+ if (neutral === "preset")
1875
+ return c;
1876
+ const tint = NEUTRAL_TINT[neutral];
1877
+ const t = neutral === "neutral" ? 0.0 : scheme === "light" ? 0.05 : 0.07;
1878
+ const grey = (hex) => {
1879
+ if (neutral !== "neutral")
1880
+ return mixHex(hex, tint, t);
1881
+ const [r, g, b] = rgb(hex);
1882
+ const y = Math.round(0.2126 * r + 0.7152 * g + 0.0722 * b);
1883
+ return toHex(y, y, y);
1884
+ };
1885
+ return {
1886
+ ...c,
1887
+ background: grey(c.background),
1888
+ surface: grey(c.surface),
1889
+ surfaceRaised: grey(c.surfaceRaised),
1890
+ border: grey(c.border),
1891
+ agentBubble: grey(c.agentBubble),
1892
+ };
1893
+ }
1894
+ export function resolveTokens(configInput, scheme) {
1895
+ const config = normaliseDesignConfig(configInput);
1896
+ const p = designPreset(config.preset);
1897
+ const base = p.colors[scheme];
1898
+ let c = tintNeutrals({ ...base }, config.neutral ?? "preset", scheme);
1899
+ if (config.accent) {
1900
+ const followsAccent = base.userBubble.toUpperCase() === base.accent.toUpperCase();
1901
+ c = { ...c, accent: config.accent };
1902
+ if (followsAccent)
1903
+ c.userBubble = config.accent;
1904
+ }
1905
+ const bubbles = config.bubbles ?? p.bubbles;
1906
+ const colors = {
1907
+ ...c,
1908
+ text: ensureContrast(c.text, c.background),
1909
+ textMuted: ensureContrast(c.textMuted, c.surface, 4.5),
1910
+ onAccent: contrastRatio(c.onAccent, c.accent) >= ON_ACCENT_MIN ? c.onAccent : readableOn(c.accent, [c.onAccent, "#FFFFFF", "#101318"]),
1911
+ userBubbleText: contrastRatio(c.userBubbleText, c.userBubble) >= ON_ACCENT_MIN ? c.userBubbleText : readableOn(c.userBubble, [c.userBubbleText, "#FFFFFF", "#101318"]),
1912
+ agentBubbleText: ensureContrast(c.agentBubbleText, c.agentBubble),
1913
+ accentSoft: mixHex(c.surface, c.accent, scheme === "light" ? 0.12 : 0.22),
1914
+ };
1915
+ const k = config.roundness ?? 1;
1916
+ const r = (v) => Math.round(Math.min(48, v * k));
1917
+ const radius = { sm: r(p.shape.radius.sm), md: r(p.shape.radius.md), lg: r(p.shape.radius.lg), xl: r(p.shape.radius.xl) };
1918
+ const d = DENSITY_SCALE[config.density ?? "comfortable"];
1919
+ const spacing = {
1920
+ unit: p.spacing.unit,
1921
+ cardPadding: Math.round(p.spacing.cardPadding * d),
1922
+ gap: Math.round(p.spacing.gap * d),
1923
+ };
1924
+ const shadow = config.shadow ?? "preset";
1925
+ let elevation;
1926
+ let borderWidth = p.shape.borderWidth;
1927
+ if (shadow === "preset")
1928
+ elevation = p.elevation;
1929
+ else if (shadow === "hard") {
1930
+ elevation = { card: null, floating: null, hardOffset: { x: 4, y: 4 } };
1931
+ borderWidth = Math.max(2, borderWidth);
1932
+ }
1933
+ else
1934
+ elevation = { ...SHADOWS[shadow], hardOffset: null };
1935
+ if (scheme === "dark" && elevation.card)
1936
+ elevation = { ...elevation, card: { ...elevation.card, opacity: Math.min(0.5, elevation.card.opacity * 2) } };
1937
+ const motion = !config.motion || config.motion === "preset" ? p.motion : MOTIONS[config.motion];
1938
+ const glass = config.glass === false ? null : config.glass === true ? (p.glass ?? { blur: 20, surfaceOpacity: 0.72 }) : p.glass;
1939
+ const iconId = config.launcherIcon ?? p.icons.launcher;
1940
+ const glyph = iconId === "logo" ? null : LAUNCHER_ICONS.find((i) => i.id === iconId) ?? LAUNCHER_ICONS[0];
1941
+ return {
1942
+ v: 1,
1943
+ preset: p.id,
1944
+ scheme,
1945
+ colors,
1946
+ font: {
1947
+ ...p.font,
1948
+ body: config.font ?? p.font.body,
1949
+ heading: config.headingFont ?? config.font ?? p.font.heading,
1950
+ },
1951
+ shape: { radius, borderWidth, launcher: config.launcherShape ?? p.shape.launcher },
1952
+ spacing,
1953
+ elevation,
1954
+ motion,
1955
+ icons: {
1956
+ style: config.iconStyle ?? p.icons.style,
1957
+ stroke: p.icons.stroke,
1958
+ launcher: glyph ? { id: glyph.id, path: glyph.path, stroke: glyph.stroke } : null,
1959
+ },
1960
+ glass,
1961
+ bubbles,
1962
+ };
1963
+ }
1964
+ export function resolveDesign(configInput) {
1965
+ const config = normaliseDesignConfig(configInput);
1966
+ return { config, light: resolveTokens(config, "light"), dark: resolveTokens(config, "dark") };
1967
+ }
1968
+ export function pickTokens(design, deviceScheme) {
1969
+ const s = design.config.scheme ?? "auto";
1970
+ if (s === "light")
1971
+ return design.light;
1972
+ if (s === "dark")
1973
+ return design.dark;
1974
+ return deviceScheme === "dark" ? design.dark : design.light;
1975
+ }
1976
+ export const GLYPH_ASSET_VERSION = 2;
1977
+ export function glyphParams(raw) {
1978
+ const id = String(raw.id ?? "").trim().toLowerCase();
1979
+ const color = normaliseHex(raw.color) ?? "#FFFFFF";
1980
+ const size = Math.round(Math.max(16, Math.min(512, Number(raw.size) || 96)));
1981
+ const stroke = Math.max(0.5, Math.min(4, Number(raw.stroke) || 2));
1982
+ return { id, color, size, stroke: Math.round(stroke * 4) / 4 };
1983
+ }
1984
+ export function glyphUrl(origin, id, color, sizePx, stroke = 2) {
1985
+ const p = glyphParams({ id, color, size: sizePx, stroke });
1986
+ const base = String(origin || "https://www.graine.ai").replace(/\/+$/, "");
1987
+ return `${base}/api/embed/glyph?id=${encodeURIComponent(p.id)}&c=${p.color.slice(1)}&s=${p.size}&w=${p.stroke}&v=${GLYPH_ASSET_VERSION}`;
1988
+ }
1989
+ export function encodeDesignParam(config) {
1990
+ const json = JSON.stringify(normaliseDesignConfig(config));
1991
+ const b64 = typeof btoa === "function"
1992
+ ? btoa(unescape(encodeURIComponent(json)))
1993
+ : globalThis.Buffer.from(json, "utf8").toString("base64");
1994
+ return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1995
+ }
1996
+ export function decodeDesignParam(param) {
1997
+ if (!param)
1998
+ return null;
1999
+ try {
2000
+ const b64 = param.replace(/-/g, "+").replace(/_/g, "/");
2001
+ const json = typeof atob === "function"
2002
+ ? decodeURIComponent(escape(atob(b64)))
2003
+ : globalThis.Buffer.from(b64, "base64").toString("utf8");
2004
+ return normaliseDesignConfig(JSON.parse(json));
2005
+ }
2006
+ catch {
2007
+ return null;
2008
+ }
2009
+ }