@easybits.cloud/html-tailwind-generator 0.2.140 → 0.2.142

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 (45) hide show
  1. package/dist/{ViewportToggle-Dszv1gsL.d.ts → ViewportToggle-Gns9NOvf.d.ts} +1 -1
  2. package/dist/buildHtmlV4.js +2 -2
  3. package/dist/{chunk-7XHJJBGN.js → chunk-7MGKYJTI.js} +2 -2
  4. package/dist/{chunk-VV5I53WR.js → chunk-DCAQAHSU.js} +39 -2
  5. package/dist/chunk-DCAQAHSU.js.map +1 -0
  6. package/dist/{chunk-YKZSLVPV.js → chunk-EIZRTLU6.js} +10 -8
  7. package/dist/chunk-EIZRTLU6.js.map +1 -0
  8. package/dist/{chunk-3I6UJ7UH.js → chunk-EP65R6DE.js} +3 -3
  9. package/dist/{chunk-KXOAEC33.js → chunk-ETWQS7IQ.js} +2 -2
  10. package/dist/{chunk-IOJ7W4ST.js → chunk-GL74S2H4.js} +52 -16
  11. package/dist/chunk-GL74S2H4.js.map +1 -0
  12. package/dist/{chunk-IDJWYC4U.js → chunk-H2YYYKUI.js} +108 -5
  13. package/dist/chunk-H2YYYKUI.js.map +1 -0
  14. package/dist/{chunk-6OJXDEL2.js → chunk-QFT3PN3L.js} +18 -10
  15. package/dist/chunk-QFT3PN3L.js.map +1 -0
  16. package/dist/{chunk-4I5FFYHG.js → chunk-SJJZEW5W.js} +2 -2
  17. package/dist/{chunk-OEYKRRM7.js → chunk-ULAQDD23.js} +10 -2
  18. package/dist/chunk-ULAQDD23.js.map +1 -0
  19. package/dist/components.d.ts +2 -2
  20. package/dist/components.js +3 -3
  21. package/dist/components4.js +1 -1
  22. package/dist/deploy.d.ts +1 -1
  23. package/dist/deploy.js +3 -3
  24. package/dist/directions.d.ts +8 -0
  25. package/dist/directions.js +2 -2
  26. package/dist/generate.d.ts +5 -3
  27. package/dist/generate.js +3 -3
  28. package/dist/generateDocument.js +3 -3
  29. package/dist/images.js +1 -1
  30. package/dist/index.d.ts +3 -3
  31. package/dist/index.js +10 -10
  32. package/dist/refine.d.ts +6 -3
  33. package/dist/refine.js +3 -3
  34. package/dist/{themes-DNTBHJUH.d.ts → themes-df34nq2_.d.ts} +6 -0
  35. package/package.json +1 -1
  36. package/dist/chunk-6OJXDEL2.js.map +0 -1
  37. package/dist/chunk-IDJWYC4U.js.map +0 -1
  38. package/dist/chunk-IOJ7W4ST.js.map +0 -1
  39. package/dist/chunk-OEYKRRM7.js.map +0 -1
  40. package/dist/chunk-VV5I53WR.js.map +0 -1
  41. package/dist/chunk-YKZSLVPV.js.map +0 -1
  42. /package/dist/{chunk-7XHJJBGN.js.map → chunk-7MGKYJTI.js.map} +0 -0
  43. /package/dist/{chunk-3I6UJ7UH.js.map → chunk-EP65R6DE.js.map} +0 -0
  44. /package/dist/{chunk-KXOAEC33.js.map → chunk-ETWQS7IQ.js.map} +0 -0
  45. /package/dist/{chunk-4I5FFYHG.js.map → chunk-SJJZEW5W.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import React__default from 'react';
2
2
  import { S as Section3, I as IframeMessage } from './types-BIpbpCJr.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
- import { C as CustomColors, a as LandingTheme } from './themes-DNTBHJUH.js';
4
+ import { C as CustomColors, a as LandingTheme } from './themes-df34nq2_.js';
5
5
 
6
6
  interface CanvasHandle {
7
7
  scrollToSection: (id: string) => void;
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  buildDeployHtmlV4
3
- } from "./chunk-KXOAEC33.js";
4
- import "./chunk-VV5I53WR.js";
3
+ } from "./chunk-ETWQS7IQ.js";
4
+ import "./chunk-DCAQAHSU.js";
5
5
  export {
6
6
  buildDeployHtmlV4
7
7
  };
@@ -2,7 +2,7 @@ import {
2
2
  buildCustomTheme,
3
3
  buildSingleThemeCss,
4
4
  buildThemeCss
5
- } from "./chunk-VV5I53WR.js";
5
+ } from "./chunk-DCAQAHSU.js";
6
6
 
7
7
  // src/iframeScript.ts
8
8
  function getIframeScript() {
@@ -633,4 +633,4 @@ export {
633
633
  buildPreviewHtml,
634
634
  buildDeployHtml
635
635
  };
636
- //# sourceMappingURL=chunk-7XHJJBGN.js.map
636
+ //# sourceMappingURL=chunk-7MGKYJTI.js.map
@@ -11,8 +11,10 @@ var LANDING_THEMES = [
11
11
  accent: "#2563eb",
12
12
  surface: "#ffffff",
13
13
  "surface-alt": "#f4f4f5",
14
+ "surface-deep": "#18181b",
14
15
  "on-surface": "#18181b",
15
16
  "on-surface-muted": "#71717a",
17
+ "on-surface-deep": "#fafafa",
16
18
  "on-primary": "#ffffff",
17
19
  "on-secondary": "#ffffff",
18
20
  "on-accent": "#ffffff"
@@ -29,8 +31,10 @@ var LANDING_THEMES = [
29
31
  accent: "#d97706",
30
32
  surface: "#fafaf9",
31
33
  "surface-alt": "#f5f5f4",
34
+ "surface-deep": "#1c1917",
32
35
  "on-surface": "#1c1917",
33
36
  "on-surface-muted": "#78716c",
37
+ "on-surface-deep": "#fafaf9",
34
38
  "on-primary": "#ffffff",
35
39
  "on-secondary": "#ffffff",
36
40
  "on-accent": "#111827"
@@ -47,8 +51,10 @@ var LANDING_THEMES = [
47
51
  accent: "#0d9488",
48
52
  surface: "#ffffff",
49
53
  "surface-alt": "#f0fdfa",
54
+ "surface-deep": "#0f172a",
50
55
  "on-surface": "#0f172a",
51
56
  "on-surface-muted": "#64748b",
57
+ "on-surface-deep": "#ffffff",
52
58
  "on-primary": "#ffffff",
53
59
  "on-secondary": "#ffffff",
54
60
  "on-accent": "#ffffff"
@@ -65,8 +71,10 @@ var LANDING_THEMES = [
65
71
  accent: "#f472b6",
66
72
  surface: "#111827",
67
73
  "surface-alt": "#1f2937",
74
+ "surface-deep": "#030712",
68
75
  "on-surface": "#f9fafb",
69
76
  "on-surface-muted": "#9ca3af",
77
+ "on-surface-deep": "#f9fafb",
70
78
  "on-primary": "#111827",
71
79
  "on-secondary": "#111827",
72
80
  "on-accent": "#111827"
@@ -83,8 +91,10 @@ var LANDING_THEMES = [
83
91
  accent: "#f59e0b",
84
92
  surface: "#0a0a0a",
85
93
  "surface-alt": "#171717",
94
+ "surface-deep": "#000000",
86
95
  "on-surface": "#fafafa",
87
96
  "on-surface-muted": "#a3a3a3",
97
+ "on-surface-deep": "#fafafa",
88
98
  "on-primary": "#ffffff",
89
99
  "on-secondary": "#111827",
90
100
  "on-accent": "#111827"
@@ -101,8 +111,10 @@ var LANDING_THEMES = [
101
111
  accent: "#8b5cf6",
102
112
  surface: "#ffffff",
103
113
  "surface-alt": "#fdf2f8",
114
+ "surface-deep": "#1f2937",
104
115
  "on-surface": "#1f2937",
105
116
  "on-surface-muted": "#6b7280",
117
+ "on-surface-deep": "#ffffff",
106
118
  "on-primary": "#ffffff",
107
119
  "on-secondary": "#ffffff",
108
120
  "on-accent": "#ffffff"
@@ -119,8 +131,10 @@ var LANDING_THEMES = [
119
131
  accent: "#ec4899",
120
132
  surface: "#faf5ff",
121
133
  "surface-alt": "#f3e8ff",
134
+ "surface-deep": "#1e1b4b",
122
135
  "on-surface": "#1e1b4b",
123
136
  "on-surface-muted": "#6b7280",
137
+ "on-surface-deep": "#ffffff",
124
138
  "on-primary": "#ffffff",
125
139
  "on-secondary": "#1e1b4b",
126
140
  "on-accent": "#ffffff"
@@ -137,8 +151,10 @@ var LANDING_THEMES = [
137
151
  accent: "#0ea5e9",
138
152
  surface: "#ffffff",
139
153
  "surface-alt": "#f1f5f9",
154
+ "surface-deep": "#0f172a",
140
155
  "on-surface": "#0f172a",
141
156
  "on-surface-muted": "#64748b",
157
+ "on-surface-deep": "#ffffff",
142
158
  "on-primary": "#ffffff",
143
159
  "on-secondary": "#ffffff",
144
160
  "on-accent": "#ffffff"
@@ -155,8 +171,10 @@ var LANDING_THEMES = [
155
171
  accent: "#f97316",
156
172
  surface: "#ffffff",
157
173
  "surface-alt": "#ecfdf5",
174
+ "surface-deep": "#064e3b",
158
175
  "on-surface": "#064e3b",
159
176
  "on-surface-muted": "#6b7280",
177
+ "on-surface-deep": "#ffffff",
160
178
  "on-primary": "#ffffff",
161
179
  "on-secondary": "#ffffff",
162
180
  "on-accent": "#ffffff"
@@ -173,8 +191,10 @@ var LANDING_THEMES = [
173
191
  accent: "#facc15",
174
192
  surface: "#0f172a",
175
193
  "surface-alt": "#1e293b",
194
+ "surface-deep": "#020617",
176
195
  "on-surface": "#f1f5f9",
177
196
  "on-surface-muted": "#94a3b8",
197
+ "on-surface-deep": "#f1f5f9",
178
198
  "on-primary": "#ffffff",
179
199
  "on-secondary": "#0f172a",
180
200
  "on-accent": "#0f172a"
@@ -193,7 +213,7 @@ var THEME_DESCRIPTIONS = {
193
213
  esmeralda: "Emerald green \u2014 fresh, trustworthy, white surfaces with warm orange accent",
194
214
  medianoche: "DARK blue theme \u2014 deep navy surfaces, bright blue primary, gold accent. Surfaces are dark, text is light."
195
215
  };
196
- function buildThemePromptContext(themeName) {
216
+ function buildThemePromptContext(themeName, customColors) {
197
217
  const desc = THEME_DESCRIPTIONS[themeName] || themeName;
198
218
  const lines = [];
199
219
  lines.push(`Active theme: "${themeName}" \u2014 ${desc}`);
@@ -205,6 +225,19 @@ function buildThemePromptContext(themeName) {
205
225
  lines.push(` - ${key}: ${hex}`);
206
226
  }
207
227
  lines.push("Use these values to understand the visual mood. Generate designs that COMPLEMENT these specific colors.");
228
+ return lines.join("\n");
229
+ }
230
+ if (customColors) {
231
+ const present = Object.entries(customColors).filter(
232
+ ([, v]) => typeof v === "string" && /^#[0-9a-fA-F]{3,8}$/.test(v)
233
+ );
234
+ if (present.length > 0) {
235
+ lines.push("Actual color values for this CUSTOM theme (user-picked):");
236
+ for (const [key, hex] of present) {
237
+ lines.push(` - ${key}: ${hex}`);
238
+ }
239
+ lines.push("These are the EXACT hex values that the semantic classes resolve to. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[" + present[0][1] + "]) \u2014 the class system handles the mapping.");
240
+ }
208
241
  }
209
242
  return lines.join("\n");
210
243
  }
@@ -248,8 +281,12 @@ function buildCustomTheme(colors) {
248
281
  accent,
249
282
  surface,
250
283
  "surface-alt": isDarkSurface ? lighten(surface, 20) : darken(surface, 5),
284
+ // surface-deep is the high-contrast dark surface, independent of brand.
285
+ // For light themes: a near-black neutral. For dark themes: even darker than surface.
286
+ "surface-deep": isDarkSurface ? darken(surface, 40) : "#18181b",
251
287
  "on-surface": isDarkSurface ? "#f1f5f9" : "#111827",
252
288
  "on-surface-muted": isDarkSurface ? "#94a3b8" : "#6b7280",
289
+ "on-surface-deep": isDarkSurface ? "#f1f5f9" : "#fafafa",
253
290
  "on-primary": onPrimary,
254
291
  "on-secondary": onSecondary,
255
292
  "on-accent": onAccent
@@ -305,4 +342,4 @@ export {
305
342
  buildThemeCss,
306
343
  buildSingleThemeCss
307
344
  };
308
- //# sourceMappingURL=chunk-VV5I53WR.js.map
345
+ //# sourceMappingURL=chunk-DCAQAHSU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/themes.ts"],"sourcesContent":["export interface LandingTheme {\n id: string;\n label: string;\n colors: {\n primary: string;\n \"primary-light\": string;\n \"primary-dark\": string;\n secondary: string;\n accent: string;\n surface: string;\n /** Slight tint of `surface` (almost-same lightness) — used for cards and\n * alternating row backgrounds on a light page. NOT a dark contrast surface. */\n \"surface-alt\": string;\n /** A high-contrast dark surface that's INDEPENDENT of brand colors. Use\n * for dark cards/footers/sidebars on light themes. Pairs with text-on-surface-deep. */\n \"surface-deep\": string;\n \"on-surface\": string;\n \"on-surface-muted\": string;\n \"on-surface-deep\": string;\n \"on-primary\": string;\n \"on-secondary\": string;\n \"on-accent\": string;\n };\n}\n\nexport const LANDING_THEMES: LandingTheme[] = [\n {\n id: \"minimal\",\n label: \"Minimal\",\n colors: {\n primary: \"#18181b\",\n \"primary-light\": \"#3f3f46\",\n \"primary-dark\": \"#09090b\",\n secondary: \"#71717a\",\n accent: \"#2563eb\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f4f4f5\",\n \"surface-deep\": \"#18181b\",\n \"on-surface\": \"#18181b\",\n \"on-surface-muted\": \"#71717a\",\n \"on-surface-deep\": \"#fafafa\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"calido\",\n label: \"Cálido\",\n colors: {\n primary: \"#9a3412\",\n \"primary-light\": \"#c2410c\",\n \"primary-dark\": \"#7c2d12\",\n secondary: \"#78716c\",\n accent: \"#d97706\",\n surface: \"#fafaf9\",\n \"surface-alt\": \"#f5f5f4\",\n \"surface-deep\": \"#1c1917\",\n \"on-surface\": \"#1c1917\",\n \"on-surface-muted\": \"#78716c\",\n \"on-surface-deep\": \"#fafaf9\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#111827\",\n },\n },\n {\n id: \"oceano\",\n label: \"Océano\",\n colors: {\n primary: \"#0f4c75\",\n \"primary-light\": \"#1a6fa0\",\n \"primary-dark\": \"#0a3555\",\n secondary: \"#6b7280\",\n accent: \"#0d9488\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f0fdfa\",\n \"surface-deep\": \"#0f172a\",\n \"on-surface\": \"#0f172a\",\n \"on-surface-muted\": \"#64748b\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"noche\",\n label: \"Noche\",\n colors: {\n primary: \"#a78bfa\",\n \"primary-light\": \"#c4b5fd\",\n \"primary-dark\": \"#7c3aed\",\n secondary: \"#9ca3af\",\n accent: \"#f472b6\",\n surface: \"#111827\",\n \"surface-alt\": \"#1f2937\",\n \"surface-deep\": \"#030712\",\n \"on-surface\": \"#f9fafb\",\n \"on-surface-muted\": \"#9ca3af\",\n \"on-surface-deep\": \"#f9fafb\",\n \"on-primary\": \"#111827\",\n \"on-secondary\": \"#111827\",\n \"on-accent\": \"#111827\",\n },\n },\n {\n id: \"bosque\",\n label: \"Bosque\",\n colors: {\n primary: \"#16a34a\",\n \"primary-light\": \"#22c55e\",\n \"primary-dark\": \"#15803d\",\n secondary: \"#a3a3a3\",\n accent: \"#f59e0b\",\n surface: \"#0a0a0a\",\n \"surface-alt\": \"#171717\",\n \"surface-deep\": \"#000000\",\n \"on-surface\": \"#fafafa\",\n \"on-surface-muted\": \"#a3a3a3\",\n \"on-surface-deep\": \"#fafafa\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#111827\",\n \"on-accent\": \"#111827\",\n },\n },\n {\n id: \"rosa\",\n label: \"Rosa\",\n colors: {\n primary: \"#be185d\",\n \"primary-light\": \"#db2777\",\n \"primary-dark\": \"#9d174d\",\n secondary: \"#6b7280\",\n accent: \"#8b5cf6\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#fdf2f8\",\n \"surface-deep\": \"#1f2937\",\n \"on-surface\": \"#1f2937\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"lavanda\",\n label: \"Lavanda\",\n colors: {\n primary: \"#7c3aed\",\n \"primary-light\": \"#8b5cf6\",\n \"primary-dark\": \"#6d28d9\",\n secondary: \"#a78bfa\",\n accent: \"#ec4899\",\n surface: \"#faf5ff\",\n \"surface-alt\": \"#f3e8ff\",\n \"surface-deep\": \"#1e1b4b\",\n \"on-surface\": \"#1e1b4b\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#1e1b4b\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"corporativo\",\n label: \"Corporativo\",\n colors: {\n primary: \"#1e3a5f\",\n \"primary-light\": \"#2d5986\",\n \"primary-dark\": \"#0f2440\",\n secondary: \"#64748b\",\n accent: \"#0ea5e9\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#f1f5f9\",\n \"surface-deep\": \"#0f172a\",\n \"on-surface\": \"#0f172a\",\n \"on-surface-muted\": \"#64748b\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"esmeralda\",\n label: \"Esmeralda\",\n colors: {\n primary: \"#059669\",\n \"primary-light\": \"#10b981\",\n \"primary-dark\": \"#047857\",\n secondary: \"#6b7280\",\n accent: \"#f97316\",\n surface: \"#ffffff\",\n \"surface-alt\": \"#ecfdf5\",\n \"surface-deep\": \"#064e3b\",\n \"on-surface\": \"#064e3b\",\n \"on-surface-muted\": \"#6b7280\",\n \"on-surface-deep\": \"#ffffff\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#ffffff\",\n \"on-accent\": \"#ffffff\",\n },\n },\n {\n id: \"medianoche\",\n label: \"Medianoche\",\n colors: {\n primary: \"#3b82f6\",\n \"primary-light\": \"#60a5fa\",\n \"primary-dark\": \"#2563eb\",\n secondary: \"#94a3b8\",\n accent: \"#facc15\",\n surface: \"#0f172a\",\n \"surface-alt\": \"#1e293b\",\n \"surface-deep\": \"#020617\",\n \"on-surface\": \"#f1f5f9\",\n \"on-surface-muted\": \"#94a3b8\",\n \"on-surface-deep\": \"#f1f5f9\",\n \"on-primary\": \"#ffffff\",\n \"on-secondary\": \"#0f172a\",\n \"on-accent\": \"#0f172a\",\n },\n },\n];\n\nexport const THEME_DESCRIPTIONS: Record<string, string> = {\n minimal: \"Clean, light, professional — white surfaces, subtle grays, minimal decoration\",\n calido: \"Warm tones — amber/orange primary, cream surfaces, cozy and inviting feel\",\n oceano: \"Cool blue tones — deep ocean blues, clean white surfaces, professional and fresh\",\n noche: \"DARK theme — very dark surfaces, purple/violet accents, moody and modern. Surfaces are dark, text is light.\",\n bosque: \"DARK nature theme — black surfaces, vibrant green primary, amber accents. Surfaces are dark, text is light.\",\n rosa: \"Soft pink/rose tones — delicate, feminine, elegant with light surfaces\",\n lavanda: \"Purple/violet tones — creative, dreamy, soft purple surfaces with pink accent\",\n corporativo: \"Navy blue professional — classic corporate feel, slate grays, sky blue accent\",\n esmeralda: \"Emerald green — fresh, trustworthy, white surfaces with warm orange accent\",\n medianoche: \"DARK blue theme — deep navy surfaces, bright blue primary, gold accent. Surfaces are dark, text is light.\",\n};\n\n/**\n * Build a prompt context string describing the active theme + its hex values.\n * Used by both generate and refine to give the AI concrete color awareness.\n *\n * For built-in themes (modern, brutalist, etc.) the palette is looked up in\n * LANDING_THEMES. For custom themes, pass customColors so the AI sees the\n * user-picked hex values — otherwise the AI generates \"blind\" against custom\n * palettes and tends to emit arbitrary `bg-[#hex]` classes.\n */\nexport function buildThemePromptContext(\n themeName: string,\n customColors?: Partial<CustomColors> | Record<string, string>\n): string {\n const desc = THEME_DESCRIPTIONS[themeName] || themeName;\n const lines: string[] = [];\n lines.push(`Active theme: \"${themeName}\" — ${desc}`);\n lines.push(\"The CSS variables for this theme are already loaded. Just use the semantic classes (bg-primary, text-on-surface, bg-accent, etc.). The theme handles the actual color values.\");\n\n const themeObj = LANDING_THEMES.find(t => t.id === themeName);\n if (themeObj) {\n lines.push(\"Actual color values for this theme:\");\n for (const [key, hex] of Object.entries(themeObj.colors)) {\n lines.push(` - ${key}: ${hex}`);\n }\n lines.push(\"Use these values to understand the visual mood. Generate designs that COMPLEMENT these specific colors.\");\n return lines.join(\"\\n\");\n }\n\n // Custom theme — emit user-picked hex values so the AI knows the actual palette.\n // Without this, the model has zero color context and routinely emits arbitrary\n // `bg-[#hex]` classes (which the sanitizer then has to scrub).\n if (customColors) {\n const present = Object.entries(customColors).filter(\n ([, v]) => typeof v === \"string\" && /^#[0-9a-fA-F]{3,8}$/.test(v as string)\n );\n if (present.length > 0) {\n lines.push(\"Actual color values for this CUSTOM theme (user-picked):\");\n for (const [key, hex] of present) {\n lines.push(` - ${key}: ${hex}`);\n }\n lines.push(\"These are the EXACT hex values that the semantic classes resolve to. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[\" + (present[0][1] as string) + \"]) — the class system handles the mapping.\");\n }\n }\n\n return lines.join(\"\\n\");\n}\n\nexport interface CustomColors {\n primary: string;\n secondary?: string;\n accent?: string;\n surface?: string;\n}\n\nfunction parseHex(hex: string) {\n return {\n r: parseInt(hex.slice(1, 3), 16),\n g: parseInt(hex.slice(3, 5), 16),\n b: parseInt(hex.slice(5, 7), 16),\n };\n}\n\nfunction toHex(r: number, g: number, b: number) {\n return `#${[r, g, b].map((c) => Math.max(0, Math.min(255, c)).toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nfunction luminance(hex: string) {\n const { r, g, b } = parseHex(hex);\n return (0.299 * r + 0.587 * g + 0.114 * b) / 255;\n}\n\nfunction lighten(hex: string, amount = 40) {\n const { r, g, b } = parseHex(hex);\n return toHex(r + amount, g + amount, b + amount);\n}\n\nfunction darken(hex: string, amount = 40) {\n const { r, g, b } = parseHex(hex);\n return toHex(r - amount, g - amount, b - amount);\n}\n\nexport function buildCustomTheme(colors: CustomColors): LandingTheme {\n const { primary, secondary = \"#f59e0b\", accent = \"#06b6d4\", surface = \"#ffffff\" } = colors;\n\n const onPrimary = luminance(primary) > 0.5 ? \"#111827\" : \"#ffffff\";\n const onSecondary = luminance(secondary) > 0.5 ? \"#111827\" : \"#ffffff\";\n const onAccent = luminance(accent) > 0.5 ? \"#111827\" : \"#ffffff\";\n const surfaceLum = luminance(surface);\n const isDarkSurface = surfaceLum < 0.5;\n\n return {\n id: \"custom\",\n label: \"Custom\",\n colors: {\n primary,\n \"primary-light\": lighten(primary),\n \"primary-dark\": darken(primary),\n secondary,\n accent,\n surface,\n \"surface-alt\": isDarkSurface ? lighten(surface, 20) : darken(surface, 5),\n // surface-deep is the high-contrast dark surface, independent of brand.\n // For light themes: a near-black neutral. For dark themes: even darker than surface.\n \"surface-deep\": isDarkSurface ? darken(surface, 40) : \"#18181b\",\n \"on-surface\": isDarkSurface ? \"#f1f5f9\" : \"#111827\",\n \"on-surface-muted\": isDarkSurface ? \"#94a3b8\" : \"#6b7280\",\n \"on-surface-deep\": isDarkSurface ? \"#f1f5f9\" : \"#fafafa\",\n \"on-primary\": onPrimary,\n \"on-secondary\": onSecondary,\n \"on-accent\": onAccent,\n },\n };\n}\n\nexport function buildCustomThemeCss(colors: CustomColors): string {\n const theme = buildCustomTheme(colors);\n return `[data-theme=\"custom\"] {\\n${buildCssVars(theme.colors)}\\n}`;\n}\n\n/** CSS custom properties for a theme */\nfunction buildCssVars(colors: LandingTheme[\"colors\"]): string {\n return Object.entries(colors)\n .map(([k, v]) => ` --color-${k}: ${v};`)\n .join(\"\\n\");\n}\n\n/** Build the tailwind.config JS object string for TW v3 CDN */\nfunction buildTailwindConfig(): string {\n const colorEntries = Object.keys(LANDING_THEMES[0].colors)\n .map((k) => ` '${k}': 'var(--color-${k})'`)\n .join(\",\\n\");\n\n return `{\n theme: {\n extend: {\n colors: {\n${colorEntries}\n }\n }\n }\n }`;\n}\n\nexport function buildThemeCss(): { css: string; tailwindConfig: string } {\n const defaultTheme = LANDING_THEMES[0];\n\n const overrides = LANDING_THEMES.slice(1)\n .map((t) => `[data-theme=\"${t.id}\"] {\\n${buildCssVars(t.colors)}\\n}`)\n .join(\"\\n\\n\");\n\n const css = `:root {\\n${buildCssVars(defaultTheme.colors)}\\n}\\n\\n${overrides}`;\n return { css, tailwindConfig: buildTailwindConfig() };\n}\n\nexport function buildSingleThemeCss(themeId: string): { css: string; tailwindConfig: string } {\n const theme = LANDING_THEMES.find((t) => t.id === themeId) || LANDING_THEMES[0];\n const css = `:root {\\n${buildCssVars(theme.colors)}\\n}`;\n return { css, tailwindConfig: buildTailwindConfig() };\n}\n"],"mappings":"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","names":[]}
@@ -3,10 +3,10 @@ import {
3
3
  enrichImages,
4
4
  resolveModel,
5
5
  sanitizeSemanticColors
6
- } from "./chunk-IDJWYC4U.js";
6
+ } from "./chunk-H2YYYKUI.js";
7
7
  import {
8
8
  buildThemePromptContext
9
- } from "./chunk-VV5I53WR.js";
9
+ } from "./chunk-DCAQAHSU.js";
10
10
 
11
11
  // src/refine.ts
12
12
  import { streamText } from "ai";
@@ -22,8 +22,10 @@ RULES:
22
22
  - Return raw HTML only \u2014 no markdown fences, no explanations
23
23
 
24
24
  COLOR SYSTEM \u2014 CRITICAL:
25
- - Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted, bg-secondary, text-secondary, bg-accent, text-accent
25
+ - Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent
26
+ - POLARITY (critical): bg-surface-alt = LIGHT TINT of surface (cards on light pages \u2014 pair with text-on-surface). bg-surface-deep = HIGH-CONTRAST DARK surface (dark cards/footers on light themes \u2014 pair with text-on-surface-deep). bg-secondary = the brand's secondary color. NEVER use bg-surface-alt + text-on-primary for "dark cards" \u2014 that produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary.
26
27
  - NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.
28
+ - NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color \u2014 use bg-primary, not bg-[#userhex].
27
29
  - The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.
28
30
  - ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary \u2014 invisible on primary backgrounds).
29
31
  - CONTRAST RULE: on bg-primary or bg-primary-dark \u2192 use ONLY text-on-primary. On bg-surface or bg-surface-alt \u2192 use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary \u2014 they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.
@@ -74,7 +76,7 @@ async function refineLanding(options) {
74
76
  onChunk,
75
77
  onDone,
76
78
  onError,
77
- themeColors: _themeColors,
79
+ themeColors,
78
80
  themeName,
79
81
  brandKit
80
82
  } = options;
@@ -112,11 +114,11 @@ Return the updated HTML.`
112
114
  });
113
115
  }
114
116
  let finalSystem = systemPrompt + currentDateLine();
115
- if (themeName && themeName !== "custom") {
117
+ if (themeName) {
116
118
  finalSystem += `
117
119
 
118
120
  ## Active Theme
119
- ${buildThemePromptContext(themeName)}`;
121
+ ${buildThemePromptContext(themeName, themeColors)}`;
120
122
  }
121
123
  if (brandKit) {
122
124
  const bkLines = [];
@@ -145,7 +147,7 @@ ${bkLines.join("\n")}`;
145
147
  if (html.startsWith("```")) {
146
148
  html = html.replace(/^```(?:html|xml)?\s*/, "").replace(/\s*```$/, "");
147
149
  }
148
- html = sanitizeSemanticColors(html);
150
+ html = sanitizeSemanticColors(html, themeColors);
149
151
  html = await enrichImages(html, { pexelsApiKey, openaiApiKey, persistImage });
150
152
  onDone?.(html);
151
153
  return html;
@@ -161,4 +163,4 @@ export {
161
163
  extractSectionDescription,
162
164
  refineLanding
163
165
  };
164
- //# sourceMappingURL=chunk-YKZSLVPV.js.map
166
+ //# sourceMappingURL=chunk-EIZRTLU6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/refine.ts"],"sourcesContent":["import { streamText } from \"ai\";\nimport { enrichImages } from \"./images/enrichImages\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\nimport { resolveModel, currentDateLine } from \"./streamCore\";\nimport { buildThemePromptContext } from \"./themes\";\n\nexport const REFINE_SYSTEM = `You are an expert HTML/Tailwind CSS developer. You receive the current HTML of a landing page section and a user instruction.\n\nRULES:\n- Return ONLY the modified HTML — no full page, no <html>/<head>/<body> tags\n- Use Tailwind CSS classes (CDN loaded)\n- You may use inline styles for specific adjustments\n- Images: use data-image-query=\"english search query\" for new images\n- Keep all text in its original language unless asked to translate\n- Be creative — don't just make minimal changes, improve the design\n- Return raw HTML only — no markdown fences, no explanations\n\nCOLOR SYSTEM — CRITICAL:\n- Use semantic color classes: bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary, bg-surface, bg-surface-alt, bg-surface-deep, text-on-surface, text-on-surface-muted, text-on-surface-deep, bg-secondary, text-secondary, bg-accent, text-accent\n- POLARITY (critical): bg-surface-alt = LIGHT TINT of surface (cards on light pages — pair with text-on-surface). bg-surface-deep = HIGH-CONTRAST DARK surface (dark cards/footers on light themes — pair with text-on-surface-deep). bg-secondary = the brand's secondary color. NEVER use bg-surface-alt + text-on-primary for \"dark cards\" — that produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary.\n- NEVER use hardcoded colors: NO bg-gray-*, bg-black, bg-white, text-gray-*, text-black, text-white, etc.\n- NEVER use Tailwind JIT arbitrary value syntax for colors: bg-[#abc123], text-[#fff], from-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are STRICTLY FORBIDDEN. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. The semantic class IS the brand color — use bg-primary, not bg-[#userhex].\n- The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.\n- ALL text MUST use: text-on-surface, text-on-surface-muted, text-on-primary, text-accent. Use text-primary ONLY on bg-surface/bg-surface-alt (it's the same hue as bg-primary — invisible on primary backgrounds).\n- CONTRAST RULE: on bg-primary or bg-primary-dark → use ONLY text-on-primary. On bg-surface or bg-surface-alt → use text-on-surface, text-on-surface-muted, or text-primary. NEVER use text-primary on bg-primary — they are the SAME COLOR. NEVER put text-on-surface on bg-primary or text-on-primary on bg-surface.\n- Use bg-accent, bg-secondary, text-accent, text-secondary for visual variety — not everything should be primary.\n\nIMAGE OVERLAYS:\n- When placing text over images, ALWAYS add a gradient overlay for readability\n- Pattern: <div class=\"relative\"><img .../><div class=\"absolute inset-0 bg-gradient-to-r from-primary/80 to-transparent\"></div><div class=\"relative z-10\">...text...</div></div>\n- NEVER place text directly on images without an overlay\n\nTAILWIND v3 NOTES:\n- Standard Tailwind v3 classes (shadow-sm, shadow-md, rounded-md, etc.)\n- Borders: border + border-gray-200 for visible borders`;\n\n/**\n * Extract a text description from HTML for variant generation.\n * Instead of sending full HTML to the model, we send a content summary\n * so the model generates a completely new layout rather than tweaking colors.\n */\nexport function extractSectionDescription(html: string, label?: string): { content: string; layoutHint: string } {\n // Extract headings\n const headings = [...html.matchAll(/<h[1-6][^>]*>([\\s\\S]*?)<\\/h[1-6]>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(Boolean);\n\n // Extract paragraphs\n const paragraphs = [...html.matchAll(/<p[^>]*>([\\s\\S]*?)<\\/p>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(Boolean);\n\n // Extract button/CTA text\n const buttons = [...html.matchAll(/<(?:button|a)[^>]*>([\\s\\S]*?)<\\/(?:button|a)>/gi)]\n .map(m => m[1].replace(/<[^>]+>/g, \"\").trim())\n .filter(t => t.length > 0 && t.length < 60);\n\n // Count items (cards, list items, grid children)\n const listItems = (html.match(/<li[\\s>]/gi) || []).length;\n const gridMatch = html.match(/grid-cols-(\\d)/);\n const gridCols = gridMatch ? parseInt(gridMatch[1]) : 0;\n\n // Detect layout patterns for negative prompt\n const layouts: string[] = [];\n if (html.includes(\"grid\")) layouts.push(\"grid\");\n if (html.includes(\"flex-col\")) layouts.push(\"vertical-stack\");\n if (html.includes(\"flex-row\") || html.includes(\"md:flex-row\")) layouts.push(\"horizontal-flex\");\n if (html.includes(\"text-center\") && !html.includes(\"text-left\")) layouts.push(\"centered\");\n if (gridCols) layouts.push(`${gridCols}-column-grid`);\n\n const content = [\n label ? `Section: ${label}` : \"\",\n headings.length ? `Headings: ${headings.join(\" | \")}` : \"\",\n paragraphs.length ? `Text: ${paragraphs.slice(0, 3).join(\" \")}` : \"\",\n buttons.length ? `CTAs: ${buttons.join(\", \")}` : \"\",\n listItems > 0 ? `${listItems} list/card items` : \"\",\n ].filter(Boolean).join(\"\\n\");\n\n return { content, layoutHint: layouts.join(\", \") };\n}\n\nexport interface RefineOptions {\n /** Anthropic API key. Falls back to ANTHROPIC_API_KEY env var */\n anthropicApiKey?: string;\n /** OpenAI API key. If provided, uses GPT-4o-mini instead of Claude */\n openaiApiKey?: string;\n /** Current HTML of the section being refined */\n currentHtml: string;\n /** User instruction for refinement */\n instruction: string;\n /** Reference image (base64 data URI) for vision-based refinement */\n referenceImage?: string;\n /** When true, generates a completely new layout variant instead of refining */\n isVariant?: boolean;\n /** Custom system prompt (overrides default REFINE_SYSTEM) */\n systemPrompt?: string;\n /** Model ID (default: gpt-4o-mini/gpt-4o for OpenAI, claude-haiku/claude-sonnet for Anthropic) */\n model?: string;\n /** Pexels API key for image enrichment. Falls back to PEXELS_API_KEY env var */\n pexelsApiKey?: string;\n /** Called with temp DALL-E URL + query, returns permanent URL. Use to persist to S3/etc. */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n /** Called with accumulated HTML as it streams */\n onChunk?: (html: string) => void;\n /** Called when refinement is complete with final enriched HTML */\n onDone?: (html: string) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n /** Custom-theme palette (hex map: primary, secondary, accent, surface).\n * Required when themeName === \"custom\"; optional otherwise (built-in themes\n * resolve their hex values via LANDING_THEMES). Used both for prompt context\n * AND for theme-aware sanitization of arbitrary `bg-[#hex]` classes. */\n themeColors?: Record<string, string>;\n /** Theme name (e.g. \"minimal\", \"noche\", \"custom\") — tells the AI the design mood */\n themeName?: string;\n /** Brand kit info for AI context */\n brandKit?: {\n fonts?: { heading?: string; body?: string };\n mood?: string;\n logoUrl?: string;\n };\n}\n\n/**\n * Refine a landing page section with streaming AI.\n * Returns the final enriched HTML.\n */\nexport async function refineLanding(options: RefineOptions): Promise<string> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n currentHtml,\n instruction,\n referenceImage,\n isVariant,\n systemPrompt = REFINE_SYSTEM,\n model: modelId,\n pexelsApiKey,\n persistImage,\n onChunk,\n onDone,\n onError,\n themeColors,\n themeName,\n brandKit,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n const useVision = !!referenceImage;\n const defaultOpenai = useVision ? \"gpt-4o\" : \"gpt-4o-mini\";\n const defaultAnthropic = useVision ? \"claude-sonnet-4-6\" : \"claude-haiku-4-5-20251001\";\n const model = await resolveModel({ openaiApiKey, anthropicApiKey, modelId, defaultOpenai, defaultAnthropic });\n\n // Build content (supports multimodal with reference image)\n const content: any[] = [];\n if (referenceImage) {\n content.push({ type: \"image\", image: referenceImage });\n }\n\n if (isVariant && !referenceImage) {\n // Variant mode: send description instead of HTML to force creative layout\n const { content: desc, layoutHint } = extractSectionDescription(currentHtml);\n content.push({\n type: \"text\",\n text: `Generate a COMPLETELY NEW section with the following content. Create an original, creative layout.\\n\\nContent:\\n${desc}\\n\\n${layoutHint ? `DO NOT use these layout patterns (the current design already uses them): ${layoutHint}. Choose a radically different structure.` : \"\"}\\n\\nReturn ONLY the <section>...</section> HTML with Tailwind classes.`,\n });\n } else {\n content.push({\n type: \"text\",\n text: `Current HTML:\\n${currentHtml}\\n\\nInstruction: ${instruction}\\n\\nReturn the updated HTML.`,\n });\n }\n\n // Inject theme + brand kit context\n let finalSystem = systemPrompt + currentDateLine();\n\n if (themeName) {\n // Custom themes get their palette from themeColors; built-in themes look it up by name.\n finalSystem += `\\n\\n## Active Theme\\n${buildThemePromptContext(themeName, themeColors)}`;\n }\n\n if (brandKit) {\n const bkLines: string[] = [];\n if (brandKit.fonts?.heading) bkLines.push(`- Heading font: use font-family: '${brandKit.fonts.heading}' via inline style on h1-h6`);\n if (brandKit.fonts?.body) bkLines.push(`- Body font: use font-family: '${brandKit.fonts.body}' via inline style on p, li, span`);\n if (brandKit.mood) bkLines.push(`- Design mood: ${brandKit.mood} — adapt spacing, imagery style, and visual weight to match`);\n if (brandKit.logoUrl) bkLines.push(`- Brand logo: include <img src=\"${brandKit.logoUrl}\" alt=\"Logo\" class=\"h-8 w-auto\" /> in the navbar/hero area`);\n if (bkLines.length) finalSystem += `\\n\\n## Brand Kit\\n${bkLines.join(\"\\n\")}`;\n }\n\n const result = streamText({\n model,\n system: finalSystem,\n messages: [{ role: \"user\", content }],\n ...(isVariant && !referenceImage ? { temperature: 1.2 } : {}),\n });\n\n try {\n let accumulated = \"\";\n\n for await (const chunk of result.textStream) {\n accumulated += chunk;\n onChunk?.(accumulated);\n }\n\n // Clean up markdown fences if present\n let html = accumulated.trim();\n if (html.startsWith(\"```\")) {\n html = html.replace(/^```(?:html|xml)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n\n // Sanitize hardcoded colors to semantic classes. themeColors lets the\n // sanitizer map arbitrary `bg-[#hex]` to the nearest semantic role using\n // RGB distance against the active palette (instead of HSL hue fallback).\n html = sanitizeSemanticColors(html, themeColors);\n\n // Enrich images (DALL-E if openaiApiKey, otherwise Pexels)\n html = await enrichImages(html, { pexelsApiKey, openaiApiKey, persistImage });\n\n onDone?.(html);\n return html;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Refine failed\");\n onError?.(error);\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  buildPreviewHtml
3
- } from "./chunk-7XHJJBGN.js";
3
+ } from "./chunk-7MGKYJTI.js";
4
4
  import {
5
5
  LANDING_THEMES
6
- } from "./chunk-VV5I53WR.js";
6
+ } from "./chunk-DCAQAHSU.js";
7
7
 
8
8
  // src/components/Canvas.tsx
9
9
  import { useRef, useEffect, useCallback, useState, forwardRef, useImperativeHandle } from "react";
@@ -1368,4 +1368,4 @@ export {
1368
1368
  ViewportToggle,
1369
1369
  useUndoStack
1370
1370
  };
1371
- //# sourceMappingURL=chunk-3I6UJ7UH.js.map
1371
+ //# sourceMappingURL=chunk-EP65R6DE.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  buildCustomTheme,
3
3
  buildSingleThemeCss
4
- } from "./chunk-VV5I53WR.js";
4
+ } from "./chunk-DCAQAHSU.js";
5
5
 
6
6
  // src/buildHtmlV4.ts
7
7
  function buildDeployHtmlV4(sections, opts) {
@@ -64,4 +64,4 @@ ${branding}
64
64
  export {
65
65
  buildDeployHtmlV4
66
66
  };
67
- //# sourceMappingURL=chunk-KXOAEC33.js.map
67
+ //# sourceMappingURL=chunk-ETWQS7IQ.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  GAMMA_LAYOUTS
3
- } from "./chunk-OEYKRRM7.js";
3
+ } from "./chunk-ULAQDD23.js";
4
4
  import {
5
5
  addLoadingPlaceholders,
6
6
  addSvgLoadingPlaceholders,
@@ -13,7 +13,7 @@ import {
13
13
  resolveModel,
14
14
  sanitizeSemanticColors,
15
15
  streamGenerate
16
- } from "./chunk-IDJWYC4U.js";
16
+ } from "./chunk-H2YYYKUI.js";
17
17
 
18
18
  // src/generateDocument.ts
19
19
  import { generateObject, streamText } from "ai";
@@ -23,6 +23,19 @@ function appendDirectionExtras(direction) {
23
23
  const lines = [];
24
24
  if (direction.audience) lines.push(`Audience: ${direction.audience}`);
25
25
  if (direction.voice) lines.push(`Voice / tone: ${direction.voice}`);
26
+ if (direction.typographyScale) {
27
+ const s = direction.typographyScale;
28
+ const parts = [];
29
+ if (s.h1) parts.push(`h1=${s.h1}`);
30
+ if (s.h2) parts.push(`h2=${s.h2}`);
31
+ if (s.h3) parts.push(`h3=${s.h3}`);
32
+ if (s.body) parts.push(`body=${s.body}`);
33
+ if (s.label) parts.push(`label=${s.label}`);
34
+ if (s.caption) parts.push(`caption=${s.caption}`);
35
+ if (parts.length > 0) {
36
+ lines.push(`TYPOGRAPHY SCALE (mandatory \u2014 use these EXACT sizes via inline style="font-size: Xpx", NO improvisation): ${parts.join(", ")}`);
37
+ }
38
+ }
26
39
  if (direction.density) lines.push(`Density: ${direction.density}`);
27
40
  if (direction.borderRadius) lines.push(`Border radius: ${direction.borderRadius}`);
28
41
  if (direction.shadows) lines.push(`Shadows: ${direction.shadows}`);
@@ -74,10 +87,17 @@ RULES:
74
87
  - Sections can have ANY background \u2014 full-bleed color, gradients, or white. Not limited to white paper.
75
88
 
76
89
  STRICT PROHIBITIONS:
90
+ 0. **NO ARBITRARY HEX COLORS** \u2014 Tailwind JIT arbitrary value syntax for colors is STRICTLY FORBIDDEN: bg-[#abc123], text-[#fff], from-[#hex], to-[#hex], via-[#hex], border-[#hex], ring-[#hex], shadow-[#hex] are ALL banned. Tailwind accepts them but they bypass the theme/brandkit system and break when the user swaps colors. Even if a hex value is mentioned in this prompt, NEVER write it as a class \u2014 use the semantic class (bg-primary, text-on-surface, etc.) which resolves to the right hex automatically.
77
91
  1. **NO EMOJI** \u2014 Never use emoji characters (\u{1F680}\u274C\u2705\u{1F4CA} etc.). Instead use inline SVG icons or colored divs. For bullet decorators use small colored circles (<span class="w-2 h-2 rounded-full bg-primary inline-block"></span>) or simple SVG.
78
92
  2. **NO Chart.js / NO JavaScript** \u2014 Never reference Chart.js, canvas, or any JS library. For data visualization use pure CSS: progress bars (div with percentage width + bg-primary), horizontal bars, styled tables with colored cells. Never use <canvas> or <script>.
79
93
  3. **NO buttons or CTAs** \u2014 This is a ${isWeb ? "document" : "print document"}, not a ${isWeb ? "landing page" : "web page"}. No "Contactar", "Ver m\xE1s", "Comprar" buttons. Use text with contact info instead.
80
- 4. **CONTRAST IS MANDATORY** \u2014 Dark/colored backgrounds (bg-primary, bg-primary-dark, bg-secondary, dark gradients) MUST use text-white or text-on-primary. Light backgrounds (white, bg-surface, bg-surface-alt) MUST use text-gray-900 or text-on-surface. NEVER use dark text on dark backgrounds or light text on light backgrounds.
94
+ 4. **CONTRAST IS MANDATORY** \u2014 Each bg has ONE valid text family:
95
+ \u2022 bg-primary / bg-primary-dark / dark gradients \u2192 text-on-primary
96
+ \u2022 bg-secondary \u2192 text-on-secondary
97
+ \u2022 bg-accent \u2192 text-on-accent
98
+ \u2022 bg-surface or bg-surface-alt \u2192 text-on-surface, text-on-surface-muted (DO NOT use text-on-primary here \u2014 surface-alt is a LIGHT TINT, not dark)
99
+ \u2022 bg-surface-deep \u2192 text-on-surface-deep (a HIGH-CONTRAST DARK surface; light text required)
100
+ Common mistake: pairing bg-surface-alt with text-on-primary thinking surface-alt is "the dark card variant" \u2014 it's a LIGHT tint and produces invisible white-on-white. For dark cards use bg-surface-deep, bg-primary, or bg-secondary. NEVER use dark text on dark backgrounds or light text on light backgrounds.
81
101
  5. **Max 2 font weights per page** \u2014 Pick 2 (e.g. font-semibold + font-normal, or font-bold + font-light). Don't mix 4-5 weights.
82
102
  6. **Generous whitespace** \u2014 Don't fill every centimeter. Leave breathing room. Use py-8, py-12, gap-6, gap-8 liberally. Less content per page = more professional.
83
103
 
@@ -129,8 +149,9 @@ CSS PROGRESS BARS \u2014 use this pattern for data visualization:
129
149
 
130
150
  COLOR SYSTEM \u2014 use semantic classes:
131
151
  - bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
132
- - bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted
133
- - bg-secondary, text-secondary, bg-accent, text-accent
152
+ - bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows \u2014 NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)
153
+ - text-on-surface, text-on-surface-muted, text-on-surface-deep (light text \u2014 for use on bg-surface-deep)
154
+ - bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent
134
155
  - Cover pages should use bold full-bleed backgrounds (bg-primary, gradients from-primary to-primary-dark)
135
156
  - CONTRAST: bg-primary/bg-primary-dark/bg-secondary \u2192 text-white or text-on-primary. White/bg-surface \u2192 text-gray-900 or text-on-surface
136
157
 
@@ -276,10 +297,11 @@ TYPOGRAPHY: Use these Google Fonts via <link href="${fontsUrl}" rel="stylesheet"
276
297
  - Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)
277
298
  COLORS \u2014 use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):
278
299
  - bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
279
- - bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted
280
- - bg-secondary, text-secondary, bg-accent, text-accent
281
- - NEVER use hardcoded hex colors like bg-[#xxx] or text-[#xxx] \u2014 always use semantic classes
282
- - The palette is: primary=${direction.colors.primary}, accent=${direction.colors.accent}, surface=${direction.colors.surface}
300
+ - bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows \u2014 NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)
301
+ - text-on-surface, text-on-surface-muted, text-on-surface-deep (light text \u2014 for use on bg-surface-deep)
302
+ - bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent
303
+ - NEVER use hardcoded hex colors like bg-[#xxx], text-[#xxx], from-[#xxx], border-[#xxx] \u2014 these are STRICTLY FORBIDDEN. Even when a hex value is mentioned below, NEVER write it as a class. Tailwind JIT accepts arbitrary values but they bypass the theme system and break on brandkit swaps.
304
+ - The active palette resolves bg-primary \u2192 ${direction.colors.primary}, bg-accent \u2192 ${direction.colors.accent}, bg-surface \u2192 ${direction.colors.surface}. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[${direction.colors.primary}]).
283
305
  Mood: ${direction.mood}
284
306
  Layout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}
285
307
  IMPORTANT: Apply inline style="font-family: '${direction.headingFont}'" on ALL heading elements and style="font-family: '${direction.bodyFont}'" on ALL body text elements. Include the Google Fonts <link> tag inside the FIRST <section> only.`;
@@ -307,10 +329,17 @@ Use this exact <img> tag with this exact src URL \u2014 do NOT invent a differen
307
329
  text: `Create a professional document for: ${safePrompt}${logoInstruction}${directionInstruction}${extra}${DOCUMENT_PROMPT_SUFFIX}`
308
330
  });
309
331
  }
332
+ const themeColors = direction ? {
333
+ primary: direction.colors.primary,
334
+ accent: direction.colors.accent,
335
+ surface: direction.colors.surface,
336
+ ...direction.colors
337
+ } : void 0;
310
338
  return streamGenerate({
311
339
  ...rest,
312
340
  systemPrompt: DOCUMENT_SYSTEM_PROMPT,
313
- userContent: content
341
+ userContent: content,
342
+ themeColors
314
343
  });
315
344
  }
316
345
  var DocumentOutlineSchema = z.object({
@@ -352,10 +381,11 @@ TYPOGRAPHY: Use these Google Fonts via <link href="${fontsUrl}" rel="stylesheet"
352
381
  - Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)
353
382
  COLORS \u2014 use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):
354
383
  - bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
355
- - bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted
356
- - bg-secondary, text-secondary, bg-accent, text-accent
357
- - NEVER use hardcoded hex colors like bg-[#xxx] or text-[#xxx] \u2014 always use semantic classes
358
- - The palette is: primary=${direction.colors.primary}, accent=${direction.colors.accent}, surface=${direction.colors.surface}
384
+ - bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows \u2014 NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)
385
+ - text-on-surface, text-on-surface-muted, text-on-surface-deep (light text \u2014 for use on bg-surface-deep)
386
+ - bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent
387
+ - NEVER use hardcoded hex colors like bg-[#xxx], text-[#xxx], from-[#xxx], border-[#xxx] \u2014 these are STRICTLY FORBIDDEN. Even when a hex value is mentioned below, NEVER write it as a class. Tailwind JIT accepts arbitrary values but they bypass the theme system and break on brandkit swaps.
388
+ - The active palette resolves bg-primary \u2192 ${direction.colors.primary}, bg-accent \u2192 ${direction.colors.accent}, bg-surface \u2192 ${direction.colors.surface}. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[${direction.colors.primary}]).
359
389
  Mood: ${direction.mood}
360
390
  Layout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}
361
391
  IMPORTANT: Apply inline style="font-family: '${direction.headingFont}'" on ALL heading elements and style="font-family: '${direction.bodyFont}'" on ALL body text elements. Include the Google Fonts <link> tag inside the FIRST <section> only.`;
@@ -521,10 +551,16 @@ OUTPUT: A single JSON object on ONE line, no markdown fences:
521
551
  const [objects] = extractJsonObjects(cleaned);
522
552
  const obj = objects[0];
523
553
  if (!obj?.html) throw new Error(`No valid HTML output for page ${page.pageNumber}`);
554
+ const themeColors = direction ? {
555
+ primary: direction.colors.primary,
556
+ accent: direction.colors.accent,
557
+ surface: direction.colors.surface,
558
+ ...direction.colors
559
+ } : void 0;
524
560
  const section = {
525
561
  id: nanoid(8),
526
562
  order: pageIdx,
527
- html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html))),
563
+ html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html)), themeColors),
528
564
  label: obj.label || page.label
529
565
  };
530
566
  onPageComplete?.(pageIdx, section);
@@ -594,4 +630,4 @@ export {
594
630
  generateDocument,
595
631
  generateDocumentParallel
596
632
  };
597
- //# sourceMappingURL=chunk-IOJ7W4ST.js.map
633
+ //# sourceMappingURL=chunk-GL74S2H4.js.map