@easybits.cloud/html-tailwind-generator 0.2.141 → 0.2.143

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 (43) 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-CDEB4EHT.js → chunk-4EYTBL6J.js} +39 -16
  4. package/dist/chunk-4EYTBL6J.js.map +1 -0
  5. package/dist/{chunk-7XHJJBGN.js → chunk-7MGKYJTI.js} +2 -2
  6. package/dist/{chunk-VV5I53WR.js → chunk-DCAQAHSU.js} +39 -2
  7. package/dist/chunk-DCAQAHSU.js.map +1 -0
  8. package/dist/{chunk-IDJWYC4U.js → chunk-DCLDOBYZ.js} +115 -5
  9. package/dist/chunk-DCLDOBYZ.js.map +1 -0
  10. package/dist/{chunk-6OJXDEL2.js → chunk-DJUYMGSU.js} +18 -10
  11. package/dist/chunk-DJUYMGSU.js.map +1 -0
  12. package/dist/{chunk-3I6UJ7UH.js → chunk-EP65R6DE.js} +3 -3
  13. package/dist/{chunk-KXOAEC33.js → chunk-ETWQS7IQ.js} +2 -2
  14. package/dist/{chunk-QHKJJI4K.js → chunk-JNSVHTFN.js} +2 -2
  15. package/dist/{chunk-4I5FFYHG.js → chunk-SJJZEW5W.js} +2 -2
  16. package/dist/{chunk-YKZSLVPV.js → chunk-UQ6THF6E.js} +10 -8
  17. package/dist/chunk-UQ6THF6E.js.map +1 -0
  18. package/dist/components.d.ts +2 -2
  19. package/dist/components.js +3 -3
  20. package/dist/components4.js +1 -1
  21. package/dist/deploy.d.ts +1 -1
  22. package/dist/deploy.js +3 -3
  23. package/dist/directions.js +2 -2
  24. package/dist/generate.d.ts +5 -3
  25. package/dist/generate.js +3 -3
  26. package/dist/generateDocument.js +3 -3
  27. package/dist/images.js +1 -1
  28. package/dist/index.d.ts +3 -3
  29. package/dist/index.js +10 -10
  30. package/dist/refine.d.ts +6 -3
  31. package/dist/refine.js +3 -3
  32. package/dist/{themes-DNTBHJUH.d.ts → themes-df34nq2_.d.ts} +6 -0
  33. package/package.json +1 -1
  34. package/dist/chunk-6OJXDEL2.js.map +0 -1
  35. package/dist/chunk-CDEB4EHT.js.map +0 -1
  36. package/dist/chunk-IDJWYC4U.js.map +0 -1
  37. package/dist/chunk-VV5I53WR.js.map +0 -1
  38. package/dist/chunk-YKZSLVPV.js.map +0 -1
  39. /package/dist/{chunk-7XHJJBGN.js.map → chunk-7MGKYJTI.js.map} +0 -0
  40. /package/dist/{chunk-3I6UJ7UH.js.map → chunk-EP65R6DE.js.map} +0 -0
  41. /package/dist/{chunk-KXOAEC33.js.map → chunk-ETWQS7IQ.js.map} +0 -0
  42. /package/dist/{chunk-QHKJJI4K.js.map → chunk-JNSVHTFN.js.map} +0 -0
  43. /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
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  GAMMA_LAYOUTS
3
- } from "./chunk-QHKJJI4K.js";
3
+ } from "./chunk-JNSVHTFN.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-DCLDOBYZ.js";
17
17
 
18
18
  // src/generateDocument.ts
19
19
  import { generateObject, streamText } from "ai";
@@ -87,10 +87,17 @@ RULES:
87
87
  - Sections can have ANY background \u2014 full-bleed color, gradients, or white. Not limited to white paper.
88
88
 
89
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.
90
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.
91
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>.
92
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.
93
- 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.
94
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.
95
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.
96
103
 
@@ -142,8 +149,9 @@ CSS PROGRESS BARS \u2014 use this pattern for data visualization:
142
149
 
143
150
  COLOR SYSTEM \u2014 use semantic classes:
144
151
  - bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
145
- - bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted
146
- - 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
147
155
  - Cover pages should use bold full-bleed backgrounds (bg-primary, gradients from-primary to-primary-dark)
148
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
149
157
 
@@ -289,10 +297,11 @@ TYPOGRAPHY: Use these Google Fonts via <link href="${fontsUrl}" rel="stylesheet"
289
297
  - Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)
290
298
  COLORS \u2014 use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):
291
299
  - bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
292
- - bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted
293
- - bg-secondary, text-secondary, bg-accent, text-accent
294
- - NEVER use hardcoded hex colors like bg-[#xxx] or text-[#xxx] \u2014 always use semantic classes
295
- - 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}]).
296
305
  Mood: ${direction.mood}
297
306
  Layout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}
298
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.`;
@@ -320,10 +329,17 @@ Use this exact <img> tag with this exact src URL \u2014 do NOT invent a differen
320
329
  text: `Create a professional document for: ${safePrompt}${logoInstruction}${directionInstruction}${extra}${DOCUMENT_PROMPT_SUFFIX}`
321
330
  });
322
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;
323
338
  return streamGenerate({
324
339
  ...rest,
325
340
  systemPrompt: DOCUMENT_SYSTEM_PROMPT,
326
- userContent: content
341
+ userContent: content,
342
+ themeColors
327
343
  });
328
344
  }
329
345
  var DocumentOutlineSchema = z.object({
@@ -365,10 +381,11 @@ TYPOGRAPHY: Use these Google Fonts via <link href="${fontsUrl}" rel="stylesheet"
365
381
  - Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)
366
382
  COLORS \u2014 use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):
367
383
  - bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary
368
- - bg-surface, bg-surface-alt, text-on-surface, text-on-surface-muted
369
- - bg-secondary, text-secondary, bg-accent, text-accent
370
- - NEVER use hardcoded hex colors like bg-[#xxx] or text-[#xxx] \u2014 always use semantic classes
371
- - 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}]).
372
389
  Mood: ${direction.mood}
373
390
  Layout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}
374
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.`;
@@ -534,10 +551,16 @@ OUTPUT: A single JSON object on ONE line, no markdown fences:
534
551
  const [objects] = extractJsonObjects(cleaned);
535
552
  const obj = objects[0];
536
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;
537
560
  const section = {
538
561
  id: nanoid(8),
539
562
  order: pageIdx,
540
- html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html))),
563
+ html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html)), themeColors),
541
564
  label: obj.label || page.label
542
565
  };
543
566
  onPageComplete?.(pageIdx, section);
@@ -607,4 +630,4 @@ export {
607
630
  generateDocument,
608
631
  generateDocumentParallel
609
632
  };
610
- //# sourceMappingURL=chunk-CDEB4EHT.js.map
633
+ //# sourceMappingURL=chunk-4EYTBL6J.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/generateDocument.ts"],"sourcesContent":["import { generateObject, streamText } from \"ai\";\nimport { z } from \"zod\";\nimport { nanoid } from \"nanoid\";\nimport {\n streamGenerate,\n dataUrlToImagePart,\n resolveModel,\n currentDateLine,\n extractJsonObjects,\n addLoadingPlaceholders,\n addSvgLoadingPlaceholders,\n enrichSectionImages,\n enrichSectionSvgCharts,\n enrichSectionIconSlots,\n} from \"./streamCore\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\nimport type { Section3 } from \"./types\";\nimport type { DesignDirection } from \"./directions\";\nimport { GAMMA_LAYOUTS } from \"./directions\";\n\n/**\n * Append optional direction fields (audience, voice, density, presets, etc.)\n * to a base direction-instruction block. Keeps backward-compatible with old\n * callers that only set name/fonts/colors/mood/layoutHint.\n */\nfunction appendDirectionExtras(direction: DesignDirection): string {\n const lines: string[] = [];\n if (direction.audience) lines.push(`Audience: ${direction.audience}`);\n if (direction.voice) lines.push(`Voice / tone: ${direction.voice}`);\n if (direction.typographyScale) {\n const s = direction.typographyScale;\n const parts: string[] = [];\n if (s.h1) parts.push(`h1=${s.h1}`);\n if (s.h2) parts.push(`h2=${s.h2}`);\n if (s.h3) parts.push(`h3=${s.h3}`);\n if (s.body) parts.push(`body=${s.body}`);\n if (s.label) parts.push(`label=${s.label}`);\n if (s.caption) parts.push(`caption=${s.caption}`);\n if (parts.length > 0) {\n lines.push(`TYPOGRAPHY SCALE (mandatory — use these EXACT sizes via inline style=\"font-size: Xpx\", NO improvisation): ${parts.join(\", \")}`);\n }\n }\n if (direction.density) lines.push(`Density: ${direction.density}`);\n if (direction.borderRadius) lines.push(`Border radius: ${direction.borderRadius}`);\n if (direction.shadows) lines.push(`Shadows: ${direction.shadows}`);\n if (direction.imageryStyle) lines.push(`Imagery style: ${direction.imageryStyle}`);\n if (direction.contentDiscipline) lines.push(`Content discipline: ${direction.contentDiscipline}`);\n if (direction.referenceBrands && direction.referenceBrands.length > 0)\n lines.push(`Reference brands (take design cues from): ${direction.referenceBrands.join(\", \")}`);\n if (direction.layoutPreset && GAMMA_LAYOUTS[direction.layoutPreset])\n lines.push(`Layout preset (FOLLOW THIS RECIPE EXACTLY): \"${direction.layoutPreset}\" — ${GAMMA_LAYOUTS[direction.layoutPreset]}`);\n if (direction.customInstructions) lines.push(`Custom instructions: ${direction.customInstructions}`);\n return lines.length > 0 ? \"\\n\" + lines.join(\"\\n\") : \"\";\n}\n\nexport type PageFormat = \"letter\" | \"web\";\n\nexport const PAGE_FORMAT_CONFIG = {\n letter: {\n container: \"w-[8.5in] h-[11in]\",\n bodyText: \"text-sm or text-base (10-11px)\",\n maxColumns: 2,\n heightMode: \"fixed at 11in\",\n description: 'letter-sized (8.5\" × 11\") document pages',\n },\n web: {\n container: \"w-[1280px] min-h-[800px]\",\n bodyText: \"text-base or text-lg (16-18px)\",\n maxColumns: 1,\n heightMode: \"flexible, no max height\",\n description: \"web-optimized document sections\",\n },\n} as const;\n\nexport function getDocumentSystemPrompt(format: PageFormat = \"letter\"): string {\n const cfg = PAGE_FORMAT_CONFIG[format];\n const isWeb = format === \"web\";\n\n return `You are a professional document designer who creates stunning ${cfg.description} using HTML + Tailwind CSS.\n\nRULES:\n- Each page is a <section> element${isWeb ? \" optimized for web viewing\" : \" sized for letter paper\"}\n- Page structure: <section class=\"${cfg.container} relative overflow-hidden flex flex-col\">\n- ${isWeb ? \"Each section has flexible height — content determines the height. Use min-h-[800px] but allow natural growth.\" : \"The section is EXACTLY 11in tall — content MUST fit, never exceed. Use flex flex-col so children can use flex-1.\"}\n- The section itself has NO padding — backgrounds, gradients, and decorative elements go edge-to-edge\n- Use slot layout: shrink-0 for header/footer bands, flex-1 overflow-hidden for main content area\n- For text content, use an inner wrapper: <div class=\"flex-1 overflow-hidden px-[0.75in] py-[0.5in]\">...content...</div>\n- Footer elements (page numbers, decorative bars, contact info) MUST be direct children of <section> with shrink-0 and w-full — NEVER inside the padded content wrapper. This ensures footer backgrounds extend edge-to-edge\n- Cover pages and decorative sections can use full-bleed backgrounds (bg-primary, gradients, images that fill the entire page)\n- Content MUST NOT overflow page boundaries — be conservative with spacing\n- Use Tailwind CDN classes ONLY (no custom CSS, no @apply, no @import)\n- NO JavaScript, only HTML+Tailwind\n- All text content in Spanish unless the prompt specifies otherwise\n- Use real content from the source material, not Lorem ipsum\n- NOT responsive — fixed ${isWeb ? \"width\" : \"letter size\"}, no breakpoints needed\n- Sections can have ANY background — full-bleed color, gradients, or white. Not limited to white paper.\n\nSTRICT PROHIBITIONS:\n0. **NO ARBITRARY HEX COLORS** — 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 — use the semantic class (bg-primary, text-on-surface, etc.) which resolves to the right hex automatically.\n1. **NO EMOJI** — Never use emoji characters (🚀❌✅📊 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.\n2. **NO Chart.js / NO JavaScript** — 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>.\n3. **NO buttons or CTAs** — This is a ${isWeb ? \"document\" : \"print document\"}, not a ${isWeb ? \"landing page\" : \"web page\"}. No \"Contactar\", \"Ver más\", \"Comprar\" buttons. Use text with contact info instead.\n4. **CONTRAST IS MANDATORY** — Each bg has ONE valid text family:\n • bg-primary / bg-primary-dark / dark gradients → text-on-primary\n • bg-secondary → text-on-secondary\n • bg-accent → text-on-accent\n • bg-surface or bg-surface-alt → text-on-surface, text-on-surface-muted (DO NOT use text-on-primary here — surface-alt is a LIGHT TINT, not dark)\n • bg-surface-deep → text-on-surface-deep (a HIGH-CONTRAST DARK surface; light text required)\n Common mistake: pairing bg-surface-alt with text-on-primary thinking surface-alt is \"the dark card variant\" — 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.\n5. **Max 2 font weights per page** — Pick 2 (e.g. font-semibold + font-normal, or font-bold + font-light). Don't mix 4-5 weights.\n6. **Generous whitespace** — Don't fill every centimeter. Leave breathing room. Use py-8, py-12, gap-6, gap-8 liberally. Less content per page = more professional.\n\nLAYOUT OVERFLOW PREVENTION — CRITICAL:\n- Max ${cfg.maxColumns} column${cfg.maxColumns === 1 ? \"\" : \"s\"} side by side${cfg.maxColumns === 2 ? \" — each with w-1/2\" : \"\"}. NEVER use ${cfg.maxColumns + 1}+ columns.\n- Decorative sidebars: max w-16 (4rem). NEVER use w-[2.5in] or wider sidebars — they steal too much space.\n- Stats/metric grids: max 3 items per row (grid-cols-3). Use gap-4 or gap-6.\n- Tables: max 4 columns, use text-xs or text-sm for cell text, px-3 py-2 cell padding.\n- Images: always w-full or max-w-[50%] — never fixed pixel widths.\n- Text: never use text-6xl or larger except for cover page title. Body text: ${cfg.bodyText}.\n- NEVER use absolute positioning that could overflow — prefer flex/grid layouts.\n- Decorative shapes with absolute positioning MUST stay fully inside the page. Use overflow-hidden on parent AND keep coordinates positive (no negative right/left values).\n- Large decorative text (text-[200px], text-[10rem] etc.) MUST have opacity-5 or lower AND overflow-hidden on its container. These giant texts frequently overflow — be extra careful.\n- NEVER place elements beyond the right edge — all content and decorations must fit within ${isWeb ? \"1280px\" : \"8.5in\"} width.\n\nDESIGN — ADAPT to the document type. Read the prompt carefully and match the visual style:\n\nGENERAL PRINCIPLES (apply to ALL documents):\n- First page is ALWAYS a stunning cover/title page with impactful design\n- Typography: strong hierarchy with just 2 weights, clear headings vs body\n- Each page visually distinct — different layouts, accent placements\n- Use the full page creatively — backgrounds, sidebars, geometric shapes\n- Professional and polished, never generic or template-looking\n- Icons: use simple inline SVG (12-20px) for visual accents. Keep SVGs minimal (single path, no complex illustrations)\n\nADAPT YOUR STYLE to what the user is creating:\n- Reports/Data: structured grids, tables with alternating rows (bg-surface-alt), progress bars, stat cards, clean data hierarchy\n- Brochures/Marketing: bold hero images, large headlines, feature grids, testimonial-style quotes, visual storytelling\n- Catalogs/Products: product cards with images, specs grids, price highlights, category headers with full-bleed color\n- Invitations/Events: centered dramatic typography, decorative borders, elegant spacing, date/location prominently styled\n- Proposals/Pitches: problem→solution flow, metric highlights, team/about sections, pricing tables\n- CVs/Resumes: clean sidebar layouts, skill bars, timeline for experience, contact info header\n- Creative/General: mix techniques — bento grids, full-bleed images, overlapping elements, bold color blocking\n\nVISUAL TECHNIQUES available to you:\n- Full-bleed colored pages (bg-primary, gradients)\n- Geometric accent shapes (CSS divs with clip-path or rotation)\n- Asymmetric layouts (grid with unequal columns)\n- Large stat numbers as visual anchors (text-5xl font-black)\n- Header/footer bands with contrasting color\n- Sidebar accents (thin, max w-16)\n- Image + text compositions\n- Bento-grid mixing content blocks of different sizes\n- Tables: alternating row colors, clean borders, generous cell padding (px-4 py-3)\n- For numerical data: CSS progress bars, styled tables with colored cells, large stat numbers — NEVER canvas/charts\n\nCSS PROGRESS BARS — use this pattern for data visualization:\n<div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-primary h-3 rounded-full\" style=\"width: 75%\"></div></div>\n\nCOLOR SYSTEM — use semantic classes:\n- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary\n- bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows — NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)\n- text-on-surface, text-on-surface-muted, text-on-surface-deep (light text — for use on bg-surface-deep)\n- bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent\n- Cover pages should use bold full-bleed backgrounds (bg-primary, gradients from-primary to-primary-dark)\n- CONTRAST: bg-primary/bg-primary-dark/bg-secondary → text-white or text-on-primary. White/bg-surface → text-gray-900 or text-on-surface\n\nIMAGES — USE GENEROUSLY:\n- EVERY image MUST use: <img data-image-query=\"english search query\" alt=\"description\" class=\"w-full h-auto object-cover rounded-xl\"/>\n- NEVER include a src attribute — the system auto-replaces data-image-query with a real image\n- For avatar-like elements, use colored divs with initials instead of img tags\n- Include at LEAST 3-5 images across the document — hero images, section illustrations, backgrounds, product photos\n- Each data-image-query should be a UNIQUE, specific search query in English (e.g. \"modern office workspace aerial view\", \"team brainstorming whiteboard\", \"abstract blue technology network\")\n- Use images to break up text-heavy pages and add visual interest\n\nICONS — use data-icon-query for professional icons:\n- <span data-icon-query=\"icon-name\" class=\"inline-block w-5 h-5 text-primary\"></span>\n- Use common Lucide icon names in English: star, check, arrow-right, heart, zap, shield, users, mail, phone, calendar, clock, map-pin, briefcase, trending-up, award, target, layers, globe, etc.\n- Use in: feature lists, stat cards, CTAs, list items, contact info, section headers\n- Sizes: w-4 h-4 (small), w-5 h-5 (default), w-8 h-8 (large). Color inherits from text-* class.\n- NEVER draw SVG paths manually — ALWAYS use data-icon-query instead\n- The system auto-replaces data-icon-query with real SVG icons from Iconify\n\nCHARTS & DATA VISUALIZATION (SVG):\n- For charts, diagrams, and decorative data graphics, use:\n <div data-svg-chart=\"bar chart showing Q1 revenue: Jan $45K, Feb $52K, Mar $61K\" class=\"w-full\"></div>\n- The system generates professional SVG charts with a specialized tool — NEVER draw SVGs yourself\n- Use descriptive prompts with data points: type of chart + what it shows + actual values\n- Examples: \"donut chart: 40% Marketing, 30% Sales, 20% R&D, 10% Admin\", \"line chart showing growth: Q1 $100K, Q2 $150K, Q3 $220K, Q4 $310K\"\n- For simple metrics, still prefer CSS progress bars (they render faster)\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\nEXAMPLE — Cover page (simple, no wide sidebars):\n<section class=\"${cfg.container} relative overflow-hidden flex flex-col bg-white\">\n <div class=\"absolute left-0 top-0 w-2 h-full bg-primary\"></div>\n <div class=\"flex-1 overflow-hidden flex flex-col justify-center px-[1in]\">\n <div class=\"text-sm font-normal text-primary mb-4\">Marzo 2026 · Versión 1.0</div>\n <h1 class=\"text-5xl font-bold text-gray-900 leading-tight\">Reporte<br/>Trimestral</h1>\n <div class=\"w-16 h-1 bg-primary mt-6 mb-4\"></div>\n <p class=\"text-lg font-normal text-gray-500\">Resultados y análisis del primer trimestre</p>\n </div>\n</section>\n\nEXAMPLE — Marketing/brochure page (bold, visual):\n<section class=\"${cfg.container} relative overflow-hidden flex flex-col bg-primary\">\n <div class=\"flex flex-1 overflow-hidden\">\n <div class=\"${isWeb ? \"flex-1\" : \"w-1/2\"} flex flex-col justify-center px-[0.75in]\">\n <span class=\"text-sm font-normal text-on-primary opacity-70 uppercase tracking-widest mb-3\">Solución Premium</span>\n <h2 class=\"text-4xl font-bold text-on-primary leading-tight mb-6\">Transforma tu negocio digital</h2>\n <p class=\"text-base font-normal text-on-primary opacity-80 mb-8\">Herramientas inteligentes que simplifican la gestión de tus activos digitales.</p>\n <div class=\"flex gap-6\">\n <div><div class=\"text-3xl font-bold text-accent\">98%</div><div class=\"text-xs text-on-primary opacity-70\">Satisfacción</div></div>\n <div><div class=\"text-3xl font-bold text-accent\">2.4K</div><div class=\"text-xs text-on-primary opacity-70\">Empresas</div></div>\n </div>\n </div>\n <div class=\"${isWeb ? \"flex-1\" : \"w-1/2\"} relative\">\n <img data-image-query=\"modern office team collaboration technology\" alt=\"Team working\" class=\"absolute inset-0 w-full h-full object-cover\" />\n </div>\n </div>\n</section>\n\nEXAMPLE — Catalog/product grid page:\n<section class=\"${cfg.container} relative overflow-hidden flex flex-col bg-surface\">\n <div class=\"shrink-0 h-1 bg-primary w-full\"></div>\n <div class=\"flex-1 overflow-hidden px-[0.75in] py-[0.5in]\">\n <div class=\"flex justify-between items-baseline mb-6\">\n <h2 class=\"text-2xl font-bold text-on-surface\">Colección Primavera</h2>\n <span class=\"text-xs font-normal text-on-surface-muted uppercase tracking-wider\">Página 3 de 8</span>\n </div>\n <div class=\"grid grid-cols-2 gap-6\">\n <div class=\"bg-surface-alt rounded-xl overflow-hidden\">\n <img data-image-query=\"minimalist product on white background\" alt=\"Product\" class=\"w-full h-48 object-cover\" />\n <div class=\"p-4\"><h3 class=\"font-bold text-on-surface text-sm\">Producto Alpha</h3><p class=\"text-xs text-on-surface-muted mt-1\">Diseño ergonómico premium</p><div class=\"text-lg font-bold text-primary mt-2\">$2,490</div></div>\n </div>\n <div class=\"bg-surface-alt rounded-xl overflow-hidden\">\n <img data-image-query=\"elegant product photography studio\" alt=\"Product\" class=\"w-full h-48 object-cover\" />\n <div class=\"p-4\"><h3 class=\"font-bold text-on-surface text-sm\">Producto Beta</h3><p class=\"text-xs text-on-surface-muted mt-1\">Tecnología de vanguardia</p><div class=\"text-lg font-bold text-primary mt-2\">$3,190</div></div>\n </div>\n </div>\n </div>\n <!-- Footer: direct child of section, shrink-0, full width -->\n <div class=\"shrink-0 w-full bg-surface-alt px-[0.75in] py-3 flex justify-between items-center\">\n <span class=\"text-xs text-on-surface-muted\">Colección Primavera 2026</span>\n <span class=\"text-xs text-on-surface-muted\">Página 3 de 8</span>\n </div>\n</section>\n\nEXAMPLE — Content page with table + progress bars:\n<section class=\"${cfg.container} relative overflow-hidden flex flex-col bg-white\">\n <div class=\"shrink-0 h-1.5 bg-primary w-full\"></div>\n <div class=\"flex-1 overflow-hidden px-[0.75in] py-[0.5in]\">\n <h2 class=\"text-2xl font-bold text-gray-900 mb-1\">Métricas de Rendimiento</h2>\n <p class=\"text-sm font-normal text-gray-500 mb-8\">Indicadores clave del periodo enero—marzo</p>\n <table class=\"w-full text-sm mb-10\">\n <thead><tr class=\"bg-primary text-white\"><th class=\"px-4 py-3 text-left font-semibold\">Indicador</th><th class=\"px-4 py-3 text-left font-semibold\">Valor</th><th class=\"px-4 py-3 text-left font-semibold\">Meta</th></tr></thead>\n <tbody>\n <tr class=\"bg-surface-alt\"><td class=\"px-4 py-3 text-gray-900\">Ingresos</td><td class=\"px-4 py-3 text-gray-900\">$1.2M</td><td class=\"px-4 py-3 text-gray-900\">$1.5M</td></tr>\n <tr><td class=\"px-4 py-3 text-gray-900\">Clientes nuevos</td><td class=\"px-4 py-3 text-gray-900\">340</td><td class=\"px-4 py-3 text-gray-900\">300</td></tr>\n <tr class=\"bg-surface-alt\"><td class=\"px-4 py-3 text-gray-900\">Retención</td><td class=\"px-4 py-3 text-gray-900\">92%</td><td class=\"px-4 py-3 text-gray-900\">${\"90%\"}</td></tr>\n </tbody>\n </table>\n <h3 class=\"text-lg font-bold text-gray-900 mb-4\">Progreso por Área</h3>\n <div class=\"space-y-4\">\n <div><div class=\"flex justify-between text-sm mb-1\"><span class=\"text-gray-900 font-semibold\">Ventas</span><span class=\"text-gray-500\">80%</span></div><div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-primary h-3 rounded-full\" style=\"width: 80%\"></div></div></div>\n <div><div class=\"flex justify-between text-sm mb-1\"><span class=\"text-gray-900 font-semibold\">Marketing</span><span class=\"text-gray-500\">65%</span></div><div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-secondary h-3 rounded-full\" style=\"width: 65%\"></div></div></div>\n <div><div class=\"flex justify-between text-sm mb-1\"><span class=\"text-gray-900 font-semibold\">Producto</span><span class=\"text-gray-500\">95%</span></div><div class=\"w-full bg-gray-200 rounded-full h-3\"><div class=\"bg-accent h-3 rounded-full\" style=\"width: 95%\"></div></div></div>\n </div>\n </div>\n</section>`;\n}\n\nexport const DOCUMENT_SYSTEM_PROMPT = getDocumentSystemPrompt(\"letter\");\n\nexport function getDocumentPromptSuffix(format: PageFormat = \"letter\"): string {\n const cfg = PAGE_FORMAT_CONFIG[format];\n const isWeb = format === \"web\";\n return `\n\nOUTPUT FORMAT: NDJSON — one JSON object per line, NO wrapper array, NO markdown fences.\nEach line: {\"label\": \"Page Title\", \"html\": \"<section class='${cfg.container} relative overflow-hidden flex flex-col'>...</section>\"}\n\nGenerate 3-8 pages depending on content length. First page = cover/title page.\n${isWeb ? \"Each section should have comfortable spacing for web reading.\" : \"Each page must fit within letter size (8.5\\\" × 11\\\"). Be conservative with spacing.\"}\nMake each page visually distinct — different layouts, different accent placements.\nIMPORTANT: Adapt your design style to match the type of document — not everything is a report. Brochures should feel bold and visual, catalogs should showcase products, invitations should feel elegant, etc.`;\n}\n\nexport const DOCUMENT_PROMPT_SUFFIX = getDocumentPromptSuffix(\"letter\");\n\nexport interface GenerateDocumentOptions {\n anthropicApiKey?: string;\n openaiApiKey?: string;\n prompt: string;\n logoUrl?: string;\n referenceImage?: string;\n extraInstructions?: string;\n model?: string | import(\"ai\").LanguageModel;\n pexelsApiKey?: string;\n /** Design direction — injects Google Fonts + hex colors into the prompt */\n direction?: DesignDirection;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n onSection?: (section: Section3) => void;\n onImageUpdate?: (sectionId: string, html: string) => void;\n onRawChunk?: (buffer: string, completedCount: number) => void;\n onDone?: (sections: Section3[]) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Generate a multi-page document with streaming AI + image enrichment.\n */\nexport async function generateDocument(options: GenerateDocumentOptions): Promise<Section3[]> {\n const {\n prompt,\n logoUrl,\n referenceImage,\n extraInstructions,\n direction,\n ...rest\n } = options;\n\n const extra = extraInstructions ? `\\nAdditional instructions: ${extraInstructions}` : \"\";\n\n // Build direction style instructions if provided\n let directionInstruction = \"\";\n if (direction) {\n const fontsUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(direction.headingFont).replace(/%20/g, \"+\")}:wght@400;700;900&family=${encodeURIComponent(direction.bodyFont).replace(/%20/g, \"+\")}:wght@400;500;600&display=swap`;\n directionInstruction = `\nDESIGN DIRECTION: \"${direction.name}\" — ${direction.tagline}\nTYPOGRAPHY: Use these Google Fonts via <link href=\"${fontsUrl}\" rel=\"stylesheet\"> on the first page.\n- Headings: font-family: '${direction.headingFont}', sans-serif (via inline style)\n- Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)\nCOLORS — use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):\n- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary\n- bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows — NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)\n- text-on-surface, text-on-surface-muted, text-on-surface-deep (light text — for use on bg-surface-deep)\n- bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent\n- NEVER use hardcoded hex colors like bg-[#xxx], text-[#xxx], from-[#xxx], border-[#xxx] — 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.\n- The active palette resolves bg-primary → ${direction.colors.primary}, bg-accent → ${direction.colors.accent}, bg-surface → ${direction.colors.surface}. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[${direction.colors.primary}]).\nMood: ${direction.mood}\nLayout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}\nIMPORTANT: 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.`;\n }\n // Truncate prompt to prevent token overflow (max ~15K chars ≈ 5K tokens)\n const safePrompt = prompt.length > 15_000 ? prompt.substring(0, 15_000) + \"\\n[...content truncated...]\" : prompt;\n const logoInstruction = logoUrl\n ? `\\nLOGO: Include this logo on the cover page and as a small header on other pages:\\n<img src=\"${logoUrl}\" alt=\"Logo\" class=\"h-12 object-contain\" />\\nUse this exact <img> tag with this exact src URL — do NOT invent a different URL or modify it.`\n : \"\";\n\n const content: any[] = [];\n\n if (referenceImage) {\n const converted = dataUrlToImagePart(referenceImage);\n if (converted) {\n content.push({ type: \"image\", ...converted });\n } else {\n content.push({ type: \"image\", image: referenceImage });\n }\n content.push({\n type: \"text\",\n text: `Create a professional document inspired by this reference image for: ${safePrompt}${logoInstruction}${directionInstruction}${extra}${DOCUMENT_PROMPT_SUFFIX}`,\n });\n } else {\n content.push({\n type: \"text\",\n text: `Create a professional document for: ${safePrompt}${logoInstruction}${directionInstruction}${extra}${DOCUMENT_PROMPT_SUFFIX}`,\n });\n }\n\n // Forward direction colors to the sanitizer so arbitrary `bg-[#hex]` classes\n // that slip through despite the prompt ban map to the correct semantic role\n // via RGB distance against the active palette.\n const themeColors = direction\n ? {\n primary: direction.colors.primary,\n accent: direction.colors.accent,\n surface: direction.colors.surface,\n ...(direction.colors as Record<string, string>),\n }\n : undefined;\n\n return streamGenerate({\n ...rest,\n systemPrompt: DOCUMENT_SYSTEM_PROMPT,\n userContent: content,\n themeColors,\n });\n}\n\n// ---------------------------------------------------------------------------\n// Parallel Document Generation\n// ---------------------------------------------------------------------------\n\nconst DocumentOutlineSchema = z.object({\n pages: z.array(z.object({\n pageNumber: z.number(),\n label: z.string().describe(\"Page title for sidebar\"),\n type: z.enum([\"cover\", \"content\", \"data\", \"visual\", \"closing\"]),\n layoutPreset: z.enum([\n \"cover\",\n \"section-divider\",\n \"agenda\",\n \"big-statement\",\n \"one-big-stat\",\n \"stat-grid\",\n \"two-column\",\n \"three-column\",\n \"image-full-bleed\",\n \"image-text-split\",\n \"bento-grid\",\n \"card-grid\",\n \"comparison-table\",\n \"timeline-vertical\",\n \"process-steps\",\n \"quote\",\n \"closing-cta\",\n ]).describe(\"Premium layout preset (Gamma-style recipe). Pick the BEST FIT for this page's content. The renderer will follow the recipe exactly.\"),\n contentBrief: z.string().describe(\"2-4 sentences describing exactly what goes on this page\"),\n keyElements: z.array(z.string()).describe(\"Specific elements: stats grid, table, hero image, timeline, etc.\"),\n backgroundStyle: z.enum([\"white\", \"primary\", \"gradient\", \"surface-alt\", \"image\"]),\n continuesFrom: z.string().optional().describe(\"How this page relates to the previous one\"),\n })),\n});\n\nexport type DocumentOutline = z.infer<typeof DocumentOutlineSchema>;\n\nexport interface GenerateDocumentParallelOptions {\n anthropicApiKey?: string;\n openaiApiKey?: string;\n prompt: string;\n logoUrl?: string;\n referenceImage?: string;\n /** Per-page reference images (e.g. rendered from PDF pages). Index matches page order. */\n referencePages?: string[];\n extraInstructions?: string;\n /** Model for page generation (quality model) */\n model?: string | import(\"ai\").LanguageModel;\n /** Model for outline generation (fast model) */\n outlineModel?: string | import(\"ai\").LanguageModel;\n pexelsApiKey?: string;\n direction?: DesignDirection;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n pageCount?: number;\n skipCover?: boolean;\n pageFormat?: PageFormat;\n onOutline?: (outline: DocumentOutline) => void;\n onPageChunk?: (pageIndex: number, partialHtml: string) => void;\n onPageComplete?: (pageIndex: number, section: Section3) => void;\n onImageUpdate?: (sectionId: string, html: string) => void;\n onDone?: (sections: Section3[]) => void;\n onError?: (error: Error) => void;\n /** Called with accumulated token usage from outline + all pages */\n onUsage?: (usage: { inputTokens: number; outputTokens: number }) => void;\n}\n\nfunction buildDirectionInstruction(direction: DesignDirection): string {\n const fontsUrl = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(direction.headingFont).replace(/%20/g, \"+\")}:wght@400;700;900&family=${encodeURIComponent(direction.bodyFont).replace(/%20/g, \"+\")}:wght@400;500;600&display=swap`;\n return `\nDESIGN DIRECTION: \"${direction.name}\" — ${direction.tagline}\nTYPOGRAPHY: Use these Google Fonts via <link href=\"${fontsUrl}\" rel=\"stylesheet\"> on the first page.\n- Headings: font-family: '${direction.headingFont}', sans-serif (via inline style)\n- Body: font-family: '${direction.bodyFont}', sans-serif (via inline style)\nCOLORS — use ONLY semantic Tailwind classes (the editor injects CSS variables that resolve these):\n- bg-primary, text-primary, bg-primary-light, bg-primary-dark, text-on-primary\n- bg-surface (page bg), bg-surface-alt (LIGHT TINT for cards/rows — NOT dark), bg-surface-deep (HIGH-CONTRAST DARK surface for dark cards on light themes)\n- text-on-surface, text-on-surface-muted, text-on-surface-deep (light text — for use on bg-surface-deep)\n- bg-secondary (brand's secondary color), text-secondary, bg-accent, text-accent\n- NEVER use hardcoded hex colors like bg-[#xxx], text-[#xxx], from-[#xxx], border-[#xxx] — 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.\n- The active palette resolves bg-primary → ${direction.colors.primary}, bg-accent → ${direction.colors.accent}, bg-surface → ${direction.colors.surface}. Use the SEMANTIC CLASS (bg-primary), NEVER the hex (bg-[${direction.colors.primary}]).\nMood: ${direction.mood}\nLayout approach: ${direction.layoutHint}${appendDirectionExtras(direction)}\nIMPORTANT: 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.`;\n}\n\n/** Extract partial HTML from a raw JSON buffer (same pattern as onRawChunk) */\nfunction extractPartialHtml(buffer: string): string | null {\n const htmlMatch = buffer.match(/\"html\"\\s*:\\s*\"([\\s\\S]*)/);\n if (!htmlMatch) return null;\n let partial = htmlMatch[1]\n .replace(/\\\\n/g, '\\n').replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, '\\\\');\n if (partial.endsWith('\\\\')) partial = partial.slice(0, -1);\n const lastQuote = partial.lastIndexOf('\"');\n if (lastQuote > 0) partial = partial.slice(0, lastQuote);\n if (/<section/i.test(partial) && !/<\\/section>/i.test(partial)) {\n partial += '</section>';\n }\n return partial.length > 20 ? partial : null;\n}\n\nexport async function generateDocumentParallel(options: GenerateDocumentParallelOptions): Promise<Section3[]> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n prompt,\n logoUrl,\n referenceImage,\n referencePages,\n extraInstructions,\n model: pageModelId,\n outlineModel: outlineModelId,\n pexelsApiKey,\n direction,\n persistImage,\n pageCount,\n skipCover,\n pageFormat = \"letter\",\n onOutline,\n onPageChunk,\n onPageComplete,\n onImageUpdate,\n onDone,\n onError,\n onUsage,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n\n try {\n // --- Phase 1: Generate outline ---\n const outlineModel = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId: outlineModelId,\n defaultOpenai: \"gpt-4.1-mini\",\n defaultAnthropic: \"claude-haiku-4-5-20251001\",\n });\n\n const safePrompt = prompt.length > 15_000 ? prompt.substring(0, 15_000) + \"\\n[...content truncated...]\" : prompt;\n const extra = extraInstructions ? `\\nAdditional instructions: ${extraInstructions}` : \"\";\n const pageCountHint = skipCover\n ? `Generate exactly ${Math.max(1, (pageCount || 5) - 1)} content pages (NO cover — it already exists).`\n : pageCount\n ? `Generate exactly ${pageCount} pages including a cover page.`\n : \"Generate 3-8 pages including a cover page.\";\n\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n\n const { object: rawOutline, usage: outlineUsage } = await generateObject({\n model: outlineModel,\n schema: DocumentOutlineSchema,\n prompt: `You are planning a professional document. Create a detailed page-by-page outline.\n\nDOCUMENT BRIEF: ${safePrompt}${extra}\n\nRULES:\n- ${pageCountHint}\n${skipCover ? \"- CRITICAL: Do NOT include a cover/title page. The cover already exists. Start with page type 'content', 'data', or 'visual'. NEVER use type 'cover'.\" : \"- First page is ALWAYS a stunning cover/title page.\"}\n- Distribute content EVENLY — no page should be overloaded\n- Each page must use a DISTINCT layoutPreset (do not repeat the same preset back-to-back). Pick the BEST FIT per page from the enum: cover (only if skipCover=false), section-divider, agenda, big-statement, one-big-stat, stat-grid, two-column, three-column, image-full-bleed, image-text-split, bento-grid, card-grid, comparison-table, timeline-vertical, process-steps, quote, closing-cta\n- A premium document varies rhythm: at least one stat-heavy preset, one image-led preset, one quote/big-statement break, one closing-cta or section-divider\n- Narrative flows naturally: ${skipCover ? \"introduction → detail → data → closing\" : \"cover → introduction → detail → data → closing\"}\n- contentBrief must be detailed enough that a separate AI can generate the page independently\n- keyElements must list specific visual elements (not vague descriptions)\n- Vary backgroundStyle across pages — not all white\n- If source content is provided, assign specific portions to each page in the contentBrief\n${direction ? `- Design mood: ${direction.mood}, layout approach: ${direction.layoutHint}` : \"\"}`,\n });\n\n totalInputTokens += outlineUsage?.inputTokens || 0;\n totalOutputTokens += outlineUsage?.outputTokens || 0;\n\n // Filter out any cover pages if skipCover (AI sometimes ignores instructions)\n const outline: DocumentOutline = skipCover\n ? { pages: rawOutline.pages.filter(p => p.type !== \"cover\").map((p, i) => ({ ...p, pageNumber: i + 1 })) }\n : rawOutline;\n\n onOutline?.(outline);\n\n // --- Phase 2: Generate pages in parallel ---\n const directionInstruction = direction ? buildDirectionInstruction(direction) : \"\";\n const logoInstruction = logoUrl\n ? `\\nLOGO: Include this logo on the cover page and as a small header on other pages:\\n<img src=\"${logoUrl}\" alt=\"Logo\" class=\"h-12 object-contain\" />\\nUse this exact <img> tag with this exact src URL.`\n : \"\";\n\n const outlineJson = JSON.stringify(outline.pages, null, 2);\n\n const pageModel = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId: pageModelId,\n defaultOpenai: \"gpt-4o\",\n defaultAnthropic: \"claude-sonnet-4-6\",\n });\n\n async function generateSinglePage(\n page: DocumentOutline[\"pages\"][number],\n retryCount = 0\n ): Promise<Section3> {\n const pageIdx = page.pageNumber - 1;\n const isCover = page.type === \"cover\";\n\n const userContent: any[] = [];\n\n // Per-page reference image from PDF (takes priority)\n const pageRef = referencePages?.[pageIdx];\n if (pageRef) {\n const converted = dataUrlToImagePart(pageRef);\n if (converted) {\n userContent.push({ type: \"image\", ...converted });\n } else {\n userContent.push({ type: \"image\", image: pageRef });\n }\n } else if (referenceImage && (isCover || page.type === \"visual\")) {\n // Fallback: single reference image for cover/visual pages\n const converted = dataUrlToImagePart(referenceImage);\n if (converted) {\n userContent.push({ type: \"image\", ...converted });\n } else {\n userContent.push({ type: \"image\", image: referenceImage });\n }\n }\n\n const hasRefImage = !!pageRef || !!(referenceImage && (isCover || page.type === \"visual\"));\n userContent.push({\n type: \"text\",\n text: `You are generating PAGE ${page.pageNumber} of ${outline.pages.length} for a professional document.\n${hasRefImage ? \"\\nREFERENCE IMAGE: The attached image shows the design to replicate. Match its layout, typography style, and visual structure as closely as possible while using the semantic color system and content from the brief.\" : \"\"}\n\nFULL DOCUMENT OUTLINE (for context — you are generating ONLY page ${page.pageNumber}):\n${outlineJson}\n\nYOUR PAGE ASSIGNMENT:\n- Label: ${page.label}\n- Type: ${page.type}\n- Layout preset (FOLLOW THIS RECIPE EXACTLY): \"${page.layoutPreset}\" — ${GAMMA_LAYOUTS[page.layoutPreset]}\n- Background: ${page.backgroundStyle}\n- Content: ${page.contentBrief}\n- Key elements: ${page.keyElements.join(\", \")}\n${page.continuesFrom ? `- Continues from: ${page.continuesFrom}` : \"\"}\n${isCover ? logoInstruction : logoUrl ? `\\nSmall logo header: <img src=\"${logoUrl}\" alt=\"Logo\" class=\"h-8 object-contain\" />` : \"\"}\n${directionInstruction}\n\nOUTPUT: A single JSON object on ONE line, no markdown fences:\n{\"label\": \"${page.label}\", \"html\": \"<section class='${PAGE_FORMAT_CONFIG[pageFormat].container} relative overflow-hidden flex flex-col'>...</section>\"}`,\n });\n\n try {\n const result = streamText({\n model: pageModel,\n system: getDocumentSystemPrompt(pageFormat || \"letter\") + currentDateLine(),\n messages: [{ role: \"user\", content: userContent }],\n });\n\n let buffer = \"\";\n let chunkCount = 0;\n for await (const chunk of result.textStream) {\n buffer += chunk;\n chunkCount++;\n if (chunkCount % 5 === 0) {\n const partial = extractPartialHtml(buffer);\n if (partial) onPageChunk?.(pageIdx, partial);\n }\n }\n\n // Accumulate token usage\n const pageUsage = await result.usage;\n totalInputTokens += pageUsage?.inputTokens || 0;\n totalOutputTokens += pageUsage?.outputTokens || 0;\n\n // Final partial before parse\n const finalPartial = extractPartialHtml(buffer);\n if (finalPartial) onPageChunk?.(pageIdx, finalPartial);\n\n // Parse the JSON object\n let cleaned = buffer.trim();\n if (cleaned.startsWith(\"```\")) {\n cleaned = cleaned.replace(/^```(?:json)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n const [objects] = extractJsonObjects(cleaned);\n const obj = objects[0];\n if (!obj?.html) throw new Error(`No valid HTML output for page ${page.pageNumber}`);\n\n // Theme-aware sanitization: maps any leaked `bg-[#hex]` to the nearest\n // semantic role using RGB distance against the active direction palette.\n const themeColors = direction\n ? {\n primary: direction.colors.primary,\n accent: direction.colors.accent,\n surface: direction.colors.surface,\n ...(direction.colors as Record<string, string>),\n }\n : undefined;\n\n const section: Section3 = {\n id: nanoid(8),\n order: pageIdx,\n html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html)), themeColors),\n label: obj.label || page.label,\n };\n\n onPageComplete?.(pageIdx, section);\n return section;\n } catch (err) {\n if (retryCount < 1) {\n console.warn(`Page ${page.pageNumber} failed, retrying:`, (err as Error).message);\n return generateSinglePage(page, retryCount + 1);\n }\n // Return error placeholder\n const section: Section3 = {\n id: nanoid(8),\n order: pageIdx,\n html: `<section class=\"w-[8.5in] h-[11in] relative overflow-hidden flex flex-col bg-gray-50 items-center justify-center\"><div class=\"text-center text-gray-400\"><p class=\"text-lg font-semibold\">Error generando página</p><p class=\"text-sm mt-2\">${(err as Error).message?.slice(0, 100) || \"Error desconocido\"}</p></div></section>`,\n label: page.label,\n };\n onPageComplete?.(pageIdx, section);\n return section;\n }\n }\n\n const results = await Promise.allSettled(\n outline.pages.map((page) => generateSinglePage(page))\n );\n\n const sections: Section3[] = results\n .map((r) => r.status === \"fulfilled\" ? r.value : null)\n .filter((s): s is Section3 => s !== null)\n .sort((a, b) => a.order - b.order);\n\n // --- Phase 3: Image enrichment (sequential to respect Pexels rate limits) ---\n for (const section of sections) {\n await enrichSectionImages(section, {\n pexelsApiKey,\n openaiApiKey,\n persistImage,\n onImageUpdate,\n });\n await enrichSectionSvgCharts(section, {\n anthropicApiKey,\n onImageUpdate,\n });\n await enrichSectionIconSlots(section, { onImageUpdate });\n }\n\n // Final fallback for images without src\n for (const section of sections) {\n const before = section.html;\n section.html = section.html.replace(\n /<img\\s(?![^>]*\\bsrc=)([^>]*?)>/gi,\n (_match, attrs) => {\n const altMatch = attrs.match(/alt=\"([^\"]*?)\"/);\n const query = altMatch?.[1] || \"image\";\n return `<img src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" ${attrs}>`;\n }\n );\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n }\n\n onUsage?.({ inputTokens: totalInputTokens, outputTokens: totalOutputTokens });\n onDone?.(sections);\n return sections;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Parallel generation failed\");\n onError?.(error);\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
@@ -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":[]}