@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
@@ -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":[]}
@@ -265,6 +265,81 @@ function categorize(color) {
265
265
  if (new RegExp(`^(?:${ACCENT_COLORS})$`).test(color)) return "accent";
266
266
  return "primary";
267
267
  }
268
+ function parseHex(hex) {
269
+ let h = hex.trim().replace(/^#/, "");
270
+ if (h.length === 3 || h.length === 4) h = h.split("").map((c) => c + c).join("");
271
+ if (h.length === 8) h = h.slice(0, 6);
272
+ if (h.length !== 6 || !/^[0-9a-fA-F]{6}$/.test(h)) return null;
273
+ return {
274
+ r: parseInt(h.slice(0, 2), 16),
275
+ g: parseInt(h.slice(2, 4), 16),
276
+ b: parseInt(h.slice(4, 6), 16)
277
+ };
278
+ }
279
+ function rgbDist(a, b) {
280
+ const dr = a.r - b.r;
281
+ const dg = a.g - b.g;
282
+ const db = a.b - b.b;
283
+ return dr * dr + dg * dg + db * db;
284
+ }
285
+ function hueBucket(rgb) {
286
+ const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255;
287
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
288
+ const delta = max - min;
289
+ const lum = (max + min) / 2;
290
+ if (delta < 0.04) {
291
+ return "primary";
292
+ }
293
+ let h = 0;
294
+ if (max === r) h = (g - b) / delta % 6;
295
+ else if (max === g) h = (b - r) / delta + 2;
296
+ else h = (r - g) / delta + 4;
297
+ h *= 60;
298
+ if (h < 0) h += 360;
299
+ if (lum < 0.08 || lum > 0.96) return "primary";
300
+ if (h < 50 || h >= 285) return "primary";
301
+ if (h < 200) return "accent";
302
+ return "secondary";
303
+ }
304
+ function hexToRole(hex, themeColors) {
305
+ const target = parseHex(hex);
306
+ if (!target) return "primary";
307
+ if (themeColors) {
308
+ const candidates = [];
309
+ for (const role of ["primary", "secondary", "accent", "surface"]) {
310
+ const v = themeColors[role];
311
+ const rgb = v ? parseHex(v) : null;
312
+ if (rgb) candidates.push([role, rgb]);
313
+ }
314
+ if (candidates.length > 0) {
315
+ let best = candidates[0][0];
316
+ let bestDist = rgbDist(target, candidates[0][1]);
317
+ for (let i = 1; i < candidates.length; i++) {
318
+ const d = rgbDist(target, candidates[i][1]);
319
+ if (d < bestDist) {
320
+ bestDist = d;
321
+ best = candidates[i][0];
322
+ }
323
+ }
324
+ return best;
325
+ }
326
+ }
327
+ return hueBucket(target);
328
+ }
329
+ var BG_LIKE_UTILS = [
330
+ "bg",
331
+ "border",
332
+ "ring",
333
+ "from",
334
+ "to",
335
+ "via",
336
+ "shadow",
337
+ "decoration",
338
+ "outline",
339
+ "divide",
340
+ "accent",
341
+ "placeholder"
342
+ ];
268
343
  var NEUTRALS = "slate|gray|zinc|neutral|stone";
269
344
  var neutralReplacements = [
270
345
  // bg-white → bg-surface
@@ -362,6 +437,7 @@ function detectBgFamily(classStr) {
362
437
  if (/^bg-primary(?:-light|-dark)?(?:\/\d+)?$/.test(t)) found = "primary";
363
438
  else if (/^bg-secondary(?:\/\d+)?$/.test(t)) found = "secondary";
364
439
  else if (/^bg-accent(?:\/\d+)?$/.test(t)) found = "accent";
440
+ else if (/^bg-surface-deep(?:\/\d+)?$/.test(t)) found = "surface-deep";
365
441
  else if (/^bg-surface(?:-alt)?(?:\/\d+)?$/.test(t)) found = "surface";
366
442
  }
367
443
  if (found) return found;
@@ -384,7 +460,9 @@ function onClass(bg) {
384
460
  return `text-on-${bg}`;
385
461
  }
386
462
  function onMutedClass(bg) {
387
- return bg === "surface" ? "text-on-surface-muted" : `text-on-${bg}`;
463
+ if (bg === "surface") return "text-on-surface-muted";
464
+ if (bg === "surface-deep") return "text-on-surface-deep";
465
+ return `text-on-${bg}`;
388
466
  }
389
467
  function fixTextClassesForBg(classStr, bg) {
390
468
  let s = classStr;
@@ -408,6 +486,11 @@ function fixTextClassesForBg(classStr, bg) {
408
486
  s = s.replace(/\btext-on-primary\b/g, "text-on-accent");
409
487
  s = s.replace(/\btext-on-secondary\b/g, "text-on-accent");
410
488
  s = s.replace(/\btext-accent\b/g, "text-on-accent");
489
+ } else if (bg === "surface-deep") {
490
+ s = s.replace(/\btext-on-surface(?!-deep)(?:-muted)?\b/g, "text-on-surface-deep");
491
+ s = s.replace(/\btext-on-primary\b/g, "text-on-surface-deep");
492
+ s = s.replace(/\btext-on-secondary\b/g, "text-on-surface-deep");
493
+ s = s.replace(/\btext-on-accent\b/g, "text-on-surface-deep");
411
494
  } else {
412
495
  s = s.replace(/\btext-on-primary\b/g, "text-on-surface");
413
496
  s = s.replace(/\btext-on-secondary\b/g, "text-on-surface");
@@ -452,7 +535,25 @@ function ancestorAwareTextPass(html) {
452
535
  return html.replace(/\btext-on-surface-LIGHT\b/g, "text-on-surface").replace(/\btext-on-surface-DARK\b/g, "text-on-surface").replace(/\btext-on-surface-MUTED\b/g, "text-on-surface-muted");
453
536
  }
454
537
  }
455
- function sanitizeSemanticColors(html) {
538
+ function arbitraryValueReplacements(html, themeColors) {
539
+ let s = html;
540
+ const bgUtilGroup = BG_LIKE_UTILS.join("|");
541
+ const bgPattern = new RegExp(
542
+ `(?<![A-Za-z0-9_-])((?:[a-z-]+:)*)(${bgUtilGroup})-\\[#([0-9a-fA-F]{3,8})\\](\\/\\d{1,3})?(?![A-Za-z0-9_-])`,
543
+ "g"
544
+ );
545
+ s = s.replace(bgPattern, (_m, variants, util, hex, opacity) => {
546
+ const role = hexToRole(hex, themeColors);
547
+ const op = opacity || "";
548
+ return `${variants}${util}-${role}${op}`;
549
+ });
550
+ const textPattern = /(?<![A-Za-z0-9_-])((?:[a-z-]+:)*)text-\[#([0-9a-fA-F]{3,8})\](\/\d{1,3})?(?![A-Za-z0-9_-])/g;
551
+ s = s.replace(textPattern, (_m, variants) => {
552
+ return `${variants}text-on-surface-MUTED`;
553
+ });
554
+ return s;
555
+ }
556
+ function sanitizeSemanticColors(html, themeColors) {
456
557
  let result = html;
457
558
  for (const [pattern, replacement] of neutralReplacements) {
458
559
  result = result.replace(pattern, replacement);
@@ -460,6 +561,7 @@ function sanitizeSemanticColors(html) {
460
561
  for (const [pattern, replacement] of textSeedReplacements) {
461
562
  result = result.replace(pattern, replacement);
462
563
  }
564
+ result = arbitraryValueReplacements(result, themeColors);
463
565
  const hasSemanticClasses = /\b(?:bg-primary|bg-secondary|bg-accent|bg-surface)\b/.test(result);
464
566
  if (!hasSemanticClasses) {
465
567
  for (const [pattern, replacer] of chromaticReplacements) {
@@ -698,7 +800,8 @@ async function streamGenerate(options) {
698
800
  onImageUpdate,
699
801
  onRawChunk,
700
802
  onDone,
701
- onError
803
+ onError,
804
+ themeColors
702
805
  } = options;
703
806
  const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;
704
807
  const model = await resolveModel({
@@ -797,7 +900,7 @@ async function streamGenerate(options) {
797
900
  const section = {
798
901
  id: nanoid(8),
799
902
  order: sectionOrder++,
800
- html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html))),
903
+ html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html)), themeColors),
801
904
  label: obj.label
802
905
  };
803
906
  allSections.push(section);
@@ -946,4 +1049,4 @@ export {
946
1049
  enrichSectionIconSlots,
947
1050
  streamGenerate
948
1051
  };
949
- //# sourceMappingURL=chunk-IDJWYC4U.js.map
1052
+ //# sourceMappingURL=chunk-H2YYYKUI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/images/pexels.ts","../src/images/dalleImages.ts","../src/images/enrichImages.ts","../src/images/svgGenerator.ts","../src/streamCore.ts","../src/images/enrichIcons.ts","../src/sanitizeColors.ts"],"sourcesContent":["export interface PexelsResult {\n url: string;\n photographer: string;\n alt: string;\n}\n\nexport async function searchImage(query: string, apiKey?: string): Promise<PexelsResult | null> {\n const key = apiKey || process.env.PEXELS_API_KEY;\n if (!key) return null;\n try {\n const res = await fetch(\n `https://api.pexels.com/v1/search?query=${encodeURIComponent(query)}&per_page=5&orientation=landscape&locale=en-US`,\n { headers: { Authorization: key } }\n );\n if (!res.ok) {\n console.warn(`[pexels] ${res.status} for \"${query}\", trying unsplash fallback`);\n return searchUnsplash(query);\n }\n const data = await res.json();\n const photos = data.photos;\n if (!photos || photos.length === 0) {\n console.warn(`[pexels] 0 results for \"${query}\"`);\n return null;\n }\n const photo = photos[Math.floor(Math.random() * photos.length)];\n return {\n url: photo.src.large,\n photographer: photo.photographer,\n alt: photo.alt || query,\n };\n } catch {\n return searchUnsplash(query);\n }\n}\n\nasync function searchUnsplash(query: string): Promise<PexelsResult | null> {\n try {\n const res = await fetch(\n `https://unsplash.com/napi/search/photos?query=${encodeURIComponent(query)}&per_page=5&orientation=landscape`\n );\n if (!res.ok) return null;\n const data = await res.json();\n const results = data.results;\n if (!results || results.length === 0) return null;\n const photo = results[Math.floor(Math.random() * results.length)];\n return {\n url: photo.urls?.regular || photo.urls?.small,\n photographer: photo.user?.name || \"Unsplash\",\n alt: photo.alt_description || query,\n };\n } catch {\n return null;\n }\n}\n","/**\n * Generate an image using DALL-E 3 API.\n */\nexport async function generateImage(\n query: string,\n openaiApiKey: string\n): Promise<string> {\n const res = await fetch(\"https://api.openai.com/v1/images/generations\", {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${openaiApiKey}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n model: \"dall-e-3\",\n prompt: query,\n n: 1,\n size: \"1792x1024\",\n }),\n });\n\n if (!res.ok) {\n const err = await res.text().catch(() => \"Unknown error\");\n throw new Error(`DALL-E API error ${res.status}: ${err}`);\n }\n\n const data = await res.json();\n return data.data[0].url;\n}\n","import { searchImage } from \"./pexels\";\nimport { generateImage } from \"./dalleImages\";\n\ninterface ImageMatch {\n query: string;\n searchStr: string;\n replaceStr: string;\n}\n\nexport interface EnrichImagesOptions {\n pexelsApiKey?: string;\n openaiApiKey?: string;\n /** Called with temp URL + query, returns permanent URL. Use to persist DALL-E images to S3/etc. */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n}\n\nconst FAKE_DOMAINS = [\n \"images.unsplash.com\",\n \"unsplash.com\",\n \"via.placeholder.com\",\n \"placeholder.com\",\n \"placehold.co\",\n \"placehold.it\",\n \"placekitten.com\",\n \"picsum.photos\",\n \"loremflickr.com\",\n \"source.unsplash.com\",\n \"dummyimage.com\",\n \"fakeimg.pl\",\n \"example.com\",\n \"img.freepik.com\",\n \"cdn.pixabay.com\",\n];\n\n/**\n * Find all images in HTML that need Pexels enrichment.\n * Two strategies:\n * 1. data-image-query=\"...\" — AI followed instructions\n * 2. <img src=\"fake-url\" — detect fake domains, use alt/class/nearby text as query\n */\nexport function findImageSlots(html: string): ImageMatch[] {\n const matches: ImageMatch[] = [];\n const seen = new Set<string>();\n\n // 1. data-image-query=\"...\" or '...' — match the full <img> tag so we can replace src + data-image-query together\n const diqRegex = /<img\\s[^>]*data-image-query=[\"']([^\"']+)[\"'][^>]*>/gi;\n let m: RegExpExecArray | null;\n while ((m = diqRegex.exec(html)) !== null) {\n const fullTag = m[0];\n const query = m[1];\n if (seen.has(query)) continue;\n seen.add(query);\n // Build replacement tag: replace src (if any) and data-image-query with final src\n const cleanedTag = fullTag\n .replace(/\\ssrc=[\"'][^\"']*[\"']/, \"\")\n .replace(/\\sdata-image-query=[\"'][^\"']*[\"']/, \"\");\n // Insert src and data-enriched right after <img\n const replaceTag = cleanedTag.replace(\n /^<img/,\n `<img src=\"{url}\" data-enriched=\"true\"`\n );\n matches.push({\n query,\n searchStr: fullTag,\n replaceStr: replaceTag,\n });\n }\n\n // 2. <img with fake/non-existent src URLs\n const imgRegex = /<img\\s[^>]*src=\"(https?:\\/\\/[^\"]+)\"[^>]*>/gi;\n while ((m = imgRegex.exec(html)) !== null) {\n const fullTag = m[0];\n const srcUrl = m[1];\n\n if (fullTag.includes(\"data-enriched\")) continue;\n if (srcUrl.includes(\"pexels.com\")) continue;\n if (seen.has(srcUrl)) continue;\n\n // Check if domain is fake\n let isFake = false;\n try {\n const domain = new URL(srcUrl).hostname;\n isFake = FAKE_DOMAINS.some((d) => domain.includes(d));\n } catch {\n isFake = true;\n }\n if (!isFake) continue;\n\n // Extract query: try alt, then class context, then URL path words\n const altMatch = fullTag.match(/alt=\"([^\"]*?)\"/);\n let query = altMatch?.[1]?.trim() || \"\";\n\n if (!query) {\n // Try to extract meaningful words from the URL path\n try {\n const path = new URL(srcUrl).pathname;\n const words = path\n .replace(/[^a-zA-Z]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 2)\n .slice(0, 4)\n .join(\" \");\n if (words.length > 3) query = words;\n } catch { /* ignore */ }\n }\n\n if (!query) query = \"professional website hero image\";\n\n seen.add(srcUrl);\n matches.push({\n query,\n searchStr: `src=\"${srcUrl}\"`,\n replaceStr: `src=\"{url}\" data-enriched=\"true\"`,\n });\n }\n\n return matches;\n}\n\n/**\n * Enrich all images in an HTML string.\n * Strategy: Pexels (free) → DALL-E fallback (if openaiApiKey) → placeholder.\n * All images resolved in parallel. If persistImage callback provided, temp DALL-E URLs are persisted.\n */\nexport async function enrichImages(html: string, pexelsApiKeyOrOpts?: string | EnrichImagesOptions, openaiApiKey?: string): Promise<string> {\n // Support both legacy (string, string) and new (options object) signatures\n let opts: EnrichImagesOptions;\n if (typeof pexelsApiKeyOrOpts === \"object\" && pexelsApiKeyOrOpts !== null) {\n opts = pexelsApiKeyOrOpts;\n } else {\n opts = { pexelsApiKey: pexelsApiKeyOrOpts, openaiApiKey };\n }\n\n const slots = findImageSlots(html);\n if (slots.length === 0) return html;\n\n // Resolve all images in parallel\n const resolved = await Promise.allSettled(\n slots.map(async (slot) => {\n let url: string | null = null;\n\n // 1. Pexels first (free)\n if (opts.pexelsApiKey) {\n const img = await searchImage(slot.query, opts.pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n\n // 2. DALL-E fallback if Pexels found nothing\n if (!url && opts.openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, opts.openaiApiKey);\n url = opts.persistImage\n ? await opts.persistImage(tempUrl, slot.query)\n : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n\n // 3. Placeholder fallback\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n\n return { slot, url };\n })\n );\n\n let result = html;\n for (const r of resolved) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n result = result.replaceAll(slot.searchStr, replacement);\n }\n }\n\n // Catch any remaining <img> tags without src\n result = result.replace(/<img\\s(?![^>]*\\bsrc=)([^>]*?)>/gi, (_match, attrs) => {\n const altMatch = attrs.match(/alt=\"([^\"]*?)\"/);\n const query = altMatch?.[1] || \"professional image\";\n return `<img src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" ${attrs}>`;\n });\n\n return result;\n}\n","import { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { generateText } from \"ai\";\nimport { currentDateLine } from \"../streamCore\";\n\nconst SVG_SYSTEM_PROMPT = `You are a professional SVG designer. Generate clean, compact SVG graphics for documents.\n\nSTRICT SIZE RULES:\n- ALWAYS use viewBox=\"0 0 600 300\" (2:1 ratio) — no exceptions\n- ALWAYS set width=\"100%\" height=\"auto\" — NEVER use fixed pixel width/height\n- NO internal padding or margins — content fills the viewBox edge-to-edge (leave only 10-20px padding)\n- Keep SVGs under 2KB — simplicity is key\n\nSTYLE RULES:\n- Output ONLY the <svg>...</svg> tag — no markdown, no explanation\n- Flat design: solid fills, no drop shadows, minimal gradients (max 1-2)\n- Max 8-10 elements total — prefer fewer, larger shapes over many small ones\n- Color palette: use the provided theme colors, or defaults (#6366f1, #8b5cf6, #ec4899, #14b8a6, #f59e0b)\n- Text: font-family=\"system-ui, sans-serif\", font-size 12-16px, max 5 text labels\n- Self-contained: no external references, all styles inline\n\nCHART TYPES:\n- Bar charts (vertical/horizontal) — max 6 bars, rounded caps\n- Pie/donut charts — max 5 segments\n- Line charts — smooth paths, max 8 data points\n- Progress/gauge charts\n- Simple comparison charts\n- Stat cards with visual elements\n\nAVOID: complex illustrations, many small elements, decorative borders, nested groups deeper than 2 levels.`;\n\n\nexport async function generateSvg(\n prompt: string,\n anthropicApiKey?: string,\n options?: { width?: number; height?: number; themeColors?: string }\n): Promise<string> {\n const apiKey = anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n const anthropic = createAnthropic({ apiKey: apiKey || undefined });\n\n const sizeHint = options?.width && options?.height\n ? ` Target dimensions: ${options.width}x${options.height}px.`\n : \"\";\n const colorHint = options?.themeColors\n ? ` Use these theme colors: ${options.themeColors}.`\n : \"\";\n\n const result = await generateText({\n model: anthropic(\"claude-haiku-4-5-20251001\"),\n system: SVG_SYSTEM_PROMPT + currentDateLine(),\n messages: [\n {\n role: \"user\",\n content: `Generate an SVG for: ${prompt}${sizeHint}${colorHint}`,\n },\n ],\n maxOutputTokens: 2000,\n });\n\n // Extract just the SVG tag\n const svgMatch = result.text.match(/<svg[\\s\\S]*<\\/svg>/i);\n if (!svgMatch) {\n throw new Error(\"SVG generation failed — no <svg> tag in response\");\n }\n\n return svgMatch[0];\n}\n","import { streamText } from \"ai\";\nimport { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { nanoid } from \"nanoid\";\nimport { findImageSlots } from \"./images/enrichImages\";\nimport { searchImage } from \"./images/pexels\";\nimport { generateImage } from \"./images/dalleImages\";\nimport { generateSvg } from \"./images/svgGenerator\";\nimport { enrichSectionIcons } from \"./images/enrichIcons\";\nimport type { Section3 } from \"./types\";\nimport { sanitizeSemanticColors } from \"./sanitizeColors\";\n\nexport function currentDateLine(): string {\n return `\\nToday's date is ${new Date().toISOString().split(\"T\")[0]}. Use this for any date references.\\n`;\n}\n\n/**\n * Resolve AI model from available keys.\n * If modelId is already a LanguageModel object, return it directly.\n * Prefers Anthropic, falls back to OpenAI.\n */\nfunction isOpenAiModel(id: string): boolean {\n return /^(gpt-|o[1-9]|dall-e|tts-|whisper|chatgpt-)/.test(id);\n}\n\nfunction isLanguageModel(value: unknown): value is import(\"ai\").LanguageModel {\n return typeof value === \"object\" && value !== null && \"modelId\" in value && \"provider\" in value;\n}\n\nexport async function resolveModel(opts: {\n openaiApiKey?: string;\n anthropicApiKey?: string;\n modelId?: string | import(\"ai\").LanguageModel;\n defaultOpenai: string;\n defaultAnthropic: string;\n}) {\n // If modelId is already a model object, return it directly\n if (opts.modelId && isLanguageModel(opts.modelId)) {\n return opts.modelId;\n }\n\n const modelId = opts.modelId as string | undefined;\n\n if (modelId && isOpenAiModel(modelId)) {\n const openaiKey = opts.openaiApiKey || process.env.OPENAI_API_KEY;\n if (openaiKey) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: openaiKey })(modelId);\n }\n // OpenAI model requested but no key — fall through to Anthropic default\n } else if (modelId) {\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n return createAnthropic({ apiKey: anthropicKey })(modelId);\n }\n }\n // No explicit modelId — prefer Anthropic, fallback to OpenAI\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n if (anthropicKey) {\n return createAnthropic({ apiKey: anthropicKey })(opts.defaultAnthropic);\n }\n const openaiKey = opts.openaiApiKey || process.env.OPENAI_API_KEY;\n if (openaiKey) {\n const { createOpenAI } = await import(\"@ai-sdk/openai\");\n return createOpenAI({ apiKey: openaiKey })(opts.defaultOpenai);\n }\n return createAnthropic()(opts.defaultAnthropic);\n}\n\n/**\n * Convert data URL to Uint8Array for AI SDK vision.\n */\nexport function dataUrlToImagePart(dataUrl: string): { image: Uint8Array; mimeType: string } | null {\n const match = dataUrl.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) return null;\n return {\n image: new Uint8Array(Buffer.from(match[2], \"base64\")),\n mimeType: match[1],\n };\n}\n\n/**\n * Extract complete JSON objects from accumulated text using brace-depth tracking.\n */\nexport function extractJsonObjects(text: string): [any[], string] {\n const objects: any[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n remaining = remaining.trimStart();\n if (!remaining.startsWith(\"{\")) {\n const nextBrace = remaining.indexOf(\"{\");\n if (nextBrace === -1) break;\n remaining = remaining.slice(nextBrace);\n continue;\n }\n\n let depth = 0;\n let inString = false;\n let escape = false;\n let end = -1;\n\n for (let i = 0; i < remaining.length; i++) {\n const ch = remaining[i];\n if (escape) { escape = false; continue; }\n if (ch === \"\\\\\") { escape = true; continue; }\n if (ch === '\"') { inString = !inString; continue; }\n if (inString) continue;\n if (ch === \"{\") depth++;\n if (ch === \"}\") { depth--; if (depth === 0) { end = i; break; } }\n }\n\n if (end === -1) break;\n\n const candidate = remaining.slice(0, end + 1);\n remaining = remaining.slice(end + 1);\n\n try {\n objects.push(JSON.parse(candidate));\n } catch {\n // malformed, skip\n }\n }\n\n return [objects, remaining];\n}\n\n/** Inline shimmer SVG used as src for loading image placeholders */\nconst LOADING_PLACEHOLDER_SRC = `data:image/svg+xml,${encodeURIComponent('<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"800\" height=\"500\" viewBox=\"0 0 800 500\"><rect fill=\"#f3f4f6\" width=\"800\" height=\"500\" rx=\"12\"/><g opacity=\".4\"><rect x=\"320\" y=\"200\" width=\"160\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" repeatCount=\"indefinite\"/></rect><rect x=\"280\" y=\"215\" width=\"240\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" begin=\".3s\" repeatCount=\"indefinite\"/></rect><rect x=\"340\" y=\"230\" width=\"120\" height=\"4\" rx=\"2\" fill=\"#d1d5db\"><animate attributeName=\"opacity\" values=\".3;.8;.3\" dur=\"1.5s\" begin=\".6s\" repeatCount=\"indefinite\"/></rect></g><g transform=\"translate(376,150)\" opacity=\".3\"><path d=\"M0 28V4a4 4 0 014-4h40a4 4 0 014 4v24a4 4 0 01-4 4H4a4 4 0 01-4-4z\" fill=\"#d1d5db\"/><circle cx=\"14\" cy=\"12\" r=\"4\" fill=\"#9ca3af\"/><path d=\"M4 28l10-10 6 6 8-8 16 16H4z\" fill=\"#9ca3af\" opacity=\".5\"/></g></svg>')}`;\n\n/** Inline SVG placeholder for loading charts */\nconst SVG_LOADING_PLACEHOLDER = `<div class=\"w-full h-48 bg-gray-50 rounded-lg flex items-center justify-center animate-pulse\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"48\" height=\"48\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#9ca3af\" stroke-width=\"1.5\"><rect x=\"3\" y=\"12\" width=\"4\" height=\"9\" rx=\"1\"/><rect x=\"10\" y=\"7\" width=\"4\" height=\"14\" rx=\"1\"/><rect x=\"17\" y=\"3\" width=\"4\" height=\"18\" rx=\"1\"/></svg></div>`;\n\n/** Replace data-svg-chart divs with loading placeholders */\nexport function addSvgLoadingPlaceholders(html: string): string {\n return html.replace(\n /<div\\s([^>]*?)data-svg-chart=\"([^\"]+)\"([^>]*?)>[\\s\\S]*?<\\/div>/gi,\n (_match, before, chart, after) => {\n return `<div ${before}data-svg-chart=\"${chart}\"${after}>${SVG_LOADING_PLACEHOLDER}</div>`;\n }\n );\n}\n\n/** Replace data-image-query attrs with animated loading placeholders */\nexport function addLoadingPlaceholders(html: string): string {\n return html.replace(\n /(<img\\s[^>]*)data-image-query=\"([^\"]+)\"([^>]*?)(?:\\s*\\/?>)/gi,\n (_match, before, query, after) => {\n if (before.includes('src=') || after.includes('src=')) return _match;\n return `${before}src=\"${LOADING_PLACEHOLDER_SRC}\" data-image-query=\"${query}\" alt=\"${query}\"${after}>`;\n }\n );\n}\n\n/** Enrich a section's images (Pexels → DALL-E → placeholder fallback). Mutates section.html in place. */\nexport async function enrichSectionImages(\n section: Section3,\n opts: {\n pexelsApiKey?: string;\n openaiApiKey?: string;\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n onImageUpdate?: (sectionId: string, html: string) => void;\n }\n): Promise<void> {\n const slots = findImageSlots(section.html);\n if (slots.length === 0) return;\n const results = await Promise.allSettled(\n slots.map(async (slot) => {\n let url: string | null = null;\n if (opts.pexelsApiKey) {\n const img = await searchImage(slot.query, opts.pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n if (!url && opts.openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, opts.openaiApiKey);\n url = opts.persistImage ? await opts.persistImage(tempUrl, slot.query) : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n return { slot, url };\n })\n );\n let html = section.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n html = html.replaceAll(slot.searchStr, replacement);\n }\n }\n if (html !== section.html) {\n section.html = html;\n opts.onImageUpdate?.(section.id, html);\n }\n}\n\n/** Enrich a section's SVG chart placeholders. Mutates section.html in place. */\nexport async function enrichSectionSvgCharts(\n section: Section3,\n opts: {\n anthropicApiKey?: string;\n onImageUpdate?: (sectionId: string, html: string) => void;\n }\n): Promise<void> {\n const svgRegex = /<div\\s[^>]*data-svg-chart=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/div>/gi;\n const svgMatches: { fullMatch: string; prompt: string }[] = [];\n let svgM: RegExpExecArray | null;\n while ((svgM = svgRegex.exec(section.html)) !== null) {\n svgMatches.push({ fullMatch: svgM[0], prompt: svgM[1] });\n }\n if (svgMatches.length === 0) return;\n const anthropicKey = opts.anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n const results = await Promise.allSettled(\n svgMatches.map(async ({ fullMatch, prompt }) => {\n try {\n const svg = await generateSvg(prompt, anthropicKey);\n return { fullMatch, svg };\n } catch (e) {\n console.warn(`[svg] failed for \"${prompt}\":`, e);\n return { fullMatch, svg: `<div class=\"w-full h-48 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-sm\">${prompt}</div>` };\n }\n })\n );\n let html = section.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n html = html.replace(r.value.fullMatch, r.value.svg);\n }\n }\n if (html !== section.html) {\n section.html = html;\n opts.onImageUpdate?.(section.id, html);\n }\n}\n\n/** Enrich a section's icon placeholders (data-icon-query → Iconify SVGs). Mutates section.html in place. */\nexport async function enrichSectionIconSlots(\n section: Section3,\n opts?: { onImageUpdate?: (sectionId: string, html: string) => void }\n): Promise<void> {\n const before = section.html;\n section.html = await enrichSectionIcons(section.html);\n if (section.html !== before) {\n opts?.onImageUpdate?.(section.id, section.html);\n }\n}\n\nexport interface StreamGenerateOptions {\n /** Anthropic API key */\n anthropicApiKey?: string;\n /** OpenAI API key */\n openaiApiKey?: string;\n /** Model ID override or pre-built LanguageModel object */\n model?: string | import(\"ai\").LanguageModel;\n /** System prompt */\n systemPrompt: string;\n /** User message content (text or multimodal parts) */\n userContent: any[];\n /** Pexels API key for image enrichment */\n pexelsApiKey?: string;\n /** Persist DALL-E images to permanent storage */\n persistImage?: (tempUrl: string, query: string) => Promise<string>;\n /** Called when a new section is parsed */\n onSection?: (section: Section3) => void;\n /** Called when a section's images are enriched */\n onImageUpdate?: (sectionId: string, html: string) => void;\n /** Called with raw text buffer for real-time partial streaming */\n onRawChunk?: (buffer: string, completedCount: number) => void;\n /**\n * Called with the HTML of the section currently being streamed, BEFORE it's\n * fully parsed. Fires as characters arrive so consumers can render a live\n * preview of the section being built. The index is the 0-based position of\n * this section in the final output (equal to the number of already-completed\n * sections at the time of this call).\n *\n * Note: the partial HTML will contain unclosed tags while streaming — the\n * browser's parser handles this gracefully when injected via innerHTML.\n */\n onPartialSection?: (index: number, partialHtml: string) => void;\n /** Called when generation is complete */\n onDone?: (sections: Section3[]) => void;\n /** Called on error */\n onError?: (error: Error) => void;\n /** Active theme palette (hex map). Forwarded to sanitizeSemanticColors so\n * arbitrary `bg-[#hex]` classes that slip through map to the nearest\n * semantic role via RGB distance instead of HSL hue fallback. */\n themeColors?: Record<string, string>;\n}\n\n/**\n * Extract the HTML value of the in-progress section from the NDJSON buffer.\n * Returns null if no `\"html\"` key has started yet. Gracefully handles the\n * common streaming case where the value is mid-write with incomplete escape\n * sequences at the end.\n */\nfunction extractPartialHtml(buffer: string): string | null {\n const keyMatch = buffer.match(/\"html\"\\s*:\\s*\"/);\n if (!keyMatch || keyMatch.index === undefined) return null;\n const start = keyMatch.index + keyMatch[0].length;\n // Walk forward to find unescaped closing \" (or end of buffer if still streaming)\n let end = buffer.length;\n let i = start;\n while (i < buffer.length) {\n const ch = buffer[i];\n if (ch === \"\\\\\") {\n i += 2;\n continue;\n }\n if (ch === '\"') {\n end = i;\n break;\n }\n i++;\n }\n let raw = buffer.slice(start, end);\n // Drop a trailing lone backslash (incomplete escape)\n if (raw.endsWith(\"\\\\\") && !raw.endsWith(\"\\\\\\\\\")) raw = raw.slice(0, -1);\n try {\n return JSON.parse('\"' + raw + '\"');\n } catch {\n // Manual unescape as fallback\n return raw\n .replace(/\\\\n/g, \"\\n\")\n .replace(/\\\\r/g, \"\\r\")\n .replace(/\\\\t/g, \"\\t\")\n .replace(/\\\\\"/g, '\"')\n .replace(/\\\\\\\\/g, \"\\\\\")\n .replace(/\\\\\\//g, \"/\");\n }\n}\n\n/**\n * Core streaming generation: stream AI text → parse NDJSON → emit sections → enrich images.\n * Used by both generateLanding and generateDocument.\n */\nexport async function streamGenerate(options: StreamGenerateOptions): Promise<Section3[]> {\n const {\n anthropicApiKey,\n openaiApiKey: _openaiApiKey,\n model: modelId,\n systemPrompt,\n userContent,\n pexelsApiKey,\n persistImage,\n onSection,\n onImageUpdate,\n onRawChunk,\n onDone,\n onError,\n themeColors,\n } = options;\n\n const openaiApiKey = _openaiApiKey || process.env.OPENAI_API_KEY;\n const model = await resolveModel({\n openaiApiKey,\n anthropicApiKey,\n modelId,\n defaultOpenai: \"gpt-4o\",\n defaultAnthropic: \"claude-sonnet-4-6\",\n });\n\n const result = streamText({\n model,\n system: systemPrompt + currentDateLine(),\n messages: [{ role: \"user\", content: userContent }],\n });\n\n const allSections: Section3[] = [];\n const imagePromises: Promise<void>[] = [];\n let sectionOrder = 0;\n let buffer = \"\";\n\n function enrichSvgCharts(sectionRef: Section3) {\n const svgRegex = /<div\\s[^>]*data-svg-chart=\"([^\"]+)\"[^>]*>[\\s\\S]*?<\\/div>/gi;\n const svgMatches: { fullMatch: string; prompt: string }[] = [];\n let svgM: RegExpExecArray | null;\n while ((svgM = svgRegex.exec(sectionRef.html)) !== null) {\n svgMatches.push({ fullMatch: svgM[0], prompt: svgM[1] });\n }\n if (svgMatches.length === 0) return;\n\n const anthropicKey = anthropicApiKey || process.env.ANTHROPIC_API_KEY;\n imagePromises.push(\n (async () => {\n const results = await Promise.allSettled(\n svgMatches.map(async ({ fullMatch, prompt }) => {\n try {\n const svg = await generateSvg(prompt, anthropicKey);\n return { fullMatch, svg };\n } catch (e) {\n console.warn(`[svg] failed for \"${prompt}\":`, e);\n return { fullMatch, svg: `<div class=\"w-full h-48 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-sm\">${prompt}</div>` };\n }\n })\n );\n let html = sectionRef.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n html = html.replace(r.value.fullMatch, r.value.svg);\n }\n }\n if (html !== sectionRef.html) {\n sectionRef.html = html;\n onImageUpdate?.(sectionRef.id, html);\n }\n })()\n );\n }\n\n function enrichSection(sectionRef: Section3) {\n const slots = findImageSlots(sectionRef.html);\n if (slots.length === 0) return;\n const slotsSnapshot = slots.map((s) => ({ ...s }));\n imagePromises.push(\n (async () => {\n const results = await Promise.allSettled(\n slotsSnapshot.map(async (slot) => {\n let url: string | null = null;\n // 1. Pexels first (free, fast)\n if (pexelsApiKey) {\n const img = await searchImage(slot.query, pexelsApiKey).catch(() => null);\n url = img?.url || null;\n }\n // 2. DALL-E fallback\n if (!url && openaiApiKey) {\n try {\n const tempUrl = await generateImage(slot.query, openaiApiKey);\n url = persistImage ? await persistImage(tempUrl, slot.query) : tempUrl;\n } catch (e) {\n console.warn(`[dalle] failed for \"${slot.query}\":`, e);\n }\n }\n url ??= `https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(slot.query.slice(0, 30))}`;\n return { slot, url };\n })\n );\n let html = sectionRef.html;\n for (const r of results) {\n if (r.status === \"fulfilled\" && r.value) {\n const { slot, url } = r.value;\n const replacement = slot.replaceStr.replace(\"{url}\", url);\n html = html.replaceAll(slot.searchStr, replacement);\n }\n }\n if (html !== sectionRef.html) {\n sectionRef.html = html;\n onImageUpdate?.(sectionRef.id, html);\n }\n })()\n );\n }\n\n function processObject(obj: any) {\n if (!obj.html || !obj.label) return;\n const section: Section3 = {\n id: nanoid(8),\n order: sectionOrder++,\n html: sanitizeSemanticColors(addSvgLoadingPlaceholders(addLoadingPlaceholders(obj.html)), themeColors),\n label: obj.label,\n };\n allSections.push(section);\n onSection?.(section);\n enrichSection(section);\n enrichSvgCharts(section);\n // Enrich icons (data-icon-query → real SVGs from Iconify)\n imagePromises.push(\n (async () => {\n const before = section.html;\n section.html = await enrichSectionIcons(section.html);\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n })()\n );\n }\n\n const { onPartialSection } = options;\n let lastPartialHtml = \"\";\n\n try {\n let chunkCount = 0;\n for await (const chunk of result.textStream) {\n buffer += chunk;\n chunkCount++;\n\n const [objects, remaining] = extractJsonObjects(buffer);\n buffer = remaining;\n for (const obj of objects) {\n chunkCount = 0;\n processObject(obj);\n lastPartialHtml = \"\"; // reset so next section starts fresh\n }\n\n if (onRawChunk && chunkCount % 5 === 0 && buffer.length > 20) {\n onRawChunk(buffer, allSections.length);\n }\n\n // Emit partial HTML every ~3 chunks so consumers can render the section\n // being built in real time without flooding the main thread.\n if (onPartialSection && chunkCount % 3 === 0) {\n const partial = extractPartialHtml(buffer);\n if (partial && partial !== lastPartialHtml) {\n lastPartialHtml = partial;\n onPartialSection(allSections.length, partial);\n }\n }\n }\n\n // Parse remaining buffer\n if (buffer.trim()) {\n let cleaned = buffer.trim();\n if (cleaned.startsWith(\"```\")) {\n cleaned = cleaned.replace(/^```(?:json)?\\s*/, \"\").replace(/\\s*```$/, \"\");\n }\n const [lastObjects] = extractJsonObjects(cleaned);\n for (const obj of lastObjects) processObject(obj);\n }\n\n // Wait for image enrichment\n await Promise.allSettled(imagePromises);\n\n // Final fallback for images without src\n for (const section of allSections) {\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 section.html = section.html.replace(\n /data-image-query=\"([^\"]+)\"/g,\n (_match, query) => {\n return `src=\"https://placehold.co/800x500/1f2937/9ca3af?text=${encodeURIComponent(query.slice(0, 30))}\" data-enriched=\"placeholder\"`;\n }\n );\n if (section.html !== before) {\n onImageUpdate?.(section.id, section.html);\n }\n }\n\n onDone?.(allSections);\n return allSections;\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error(err?.message || \"Generation failed\");\n onError?.(error);\n throw error;\n }\n}\n","interface IconMatch {\n query: string;\n fullMatch: string;\n}\n\nconst ICON_PREFIXES = [\"lucide\", \"heroicons\", \"material-symbols\"] as const;\n\nconst iconCache = new Map<string, string | null>();\n\n/**\n * Find all `data-icon-query=\"name\"` spans in HTML.\n */\nexport function findIconSlots(html: string): IconMatch[] {\n const matches: IconMatch[] = [];\n const regex = /<span\\s[^>]*data-icon-query=\"([^\"]+)\"[^>]*><\\/span>/gi;\n let m: RegExpExecArray | null;\n while ((m = regex.exec(html)) !== null) {\n matches.push({ query: m[1], fullMatch: m[0] });\n }\n return matches;\n}\n\n/**\n * Fetch an SVG icon from Iconify API, trying multiple icon sets.\n */\nasync function fetchIcon(name: string): Promise<string | null> {\n if (iconCache.has(name)) return iconCache.get(name)!;\n\n for (const prefix of ICON_PREFIXES) {\n try {\n const url = `https://api.iconify.design/${prefix}/${name}.svg?height=1em&color=currentColor`;\n const res = await fetch(url);\n if (res.ok) {\n const svg = await res.text();\n if (svg.startsWith(\"<svg\")) {\n iconCache.set(name, svg);\n return svg;\n }\n }\n } catch {\n // try next prefix\n }\n }\n\n iconCache.set(name, null);\n return null;\n}\n\n/**\n * Replace all `data-icon-query` spans with real inline SVGs from Iconify.\n */\nexport async function enrichSectionIcons(html: string): Promise<string> {\n const slots = findIconSlots(html);\n if (slots.length === 0) return html;\n\n // Dedupe queries\n const uniqueQueries = [...new Set(slots.map((s) => s.query))];\n const resolved = await Promise.allSettled(\n uniqueQueries.map(async (query) => {\n const svg = await fetchIcon(query);\n return { query, svg };\n })\n );\n\n const svgMap = new Map<string, string>();\n for (const r of resolved) {\n if (r.status === \"fulfilled\" && r.value.svg) {\n svgMap.set(r.value.query, r.value.svg);\n }\n }\n\n let result = html;\n for (const slot of slots) {\n const svg = svgMap.get(slot.query);\n if (!svg) continue;\n\n // Extract classes from the original span to apply to the SVG\n const classMatch = slot.fullMatch.match(/class=\"([^\"]*)\"/);\n const classes = classMatch?.[1] || \"inline-block w-5 h-5\";\n\n // Add classes to the SVG element\n const svgWithClasses = svg.replace(\"<svg\", `<svg class=\"${classes}\"`);\n result = result.replace(slot.fullMatch, svgWithClasses);\n }\n\n return result;\n}\n","/**\n * Replace hardcoded Tailwind color classes with semantic color classes.\n *\n * Four layers:\n * 1. Neutral bg replacements: bg-white → bg-surface, bg-gray-900 → bg-primary-dark, etc.\n * 2. Chromatic replacements: bg-blue-500 → bg-secondary, bg-green-500 → bg-accent, etc.\n * (only if the AI didn't already use semantic classes)\n * 3. Arbitrary-value replacements: bg-[#9a99ea] → bg-primary (mapped by RGB\n * distance to the active theme palette, or HSL hue bucketing as fallback).\n * 4. Ancestor-aware text-color pass: walks the DOM with a stack of effective\n * background family (primary | secondary | accent | surface) and rewrites\n * every text-* that conflicts with its ancestor bg. This fixes \"black-on-black\"\n * and \"text-on-primary on bg-surface\" invisible-text bugs regardless of theme.\n */\n\nconst COLORS =\n \"red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose\";\n\nconst SECONDARY_COLORS = \"blue|indigo|violet\";\nconst ACCENT_COLORS = \"green|emerald|teal|cyan\";\n\nfunction categorize(color: string): \"primary\" | \"secondary\" | \"accent\" {\n if (new RegExp(`^(?:${SECONDARY_COLORS})$`).test(color)) return \"secondary\";\n if (new RegExp(`^(?:${ACCENT_COLORS})$`).test(color)) return \"accent\";\n return \"primary\";\n}\n\n// ── Arbitrary-value helpers (Tailwind JIT: text-[#hex], bg-[#hex], etc.) ──\n\ntype Role = \"primary\" | \"secondary\" | \"accent\" | \"surface\";\ntype Rgb = { r: number; g: number; b: number };\n\nfunction parseHex(hex: string): Rgb | null {\n let h = hex.trim().replace(/^#/, \"\");\n if (h.length === 3 || h.length === 4) h = h.split(\"\").map((c) => c + c).join(\"\");\n if (h.length === 8) h = h.slice(0, 6); // drop alpha\n if (h.length !== 6 || !/^[0-9a-fA-F]{6}$/.test(h)) return null;\n return {\n r: parseInt(h.slice(0, 2), 16),\n g: parseInt(h.slice(2, 4), 16),\n b: parseInt(h.slice(4, 6), 16),\n };\n}\n\nfunction rgbDist(a: Rgb, b: Rgb): number {\n const dr = a.r - b.r;\n const dg = a.g - b.g;\n const db = a.b - b.b;\n return dr * dr + dg * dg + db * db;\n}\n\n/** HSL hue bucketing fallback when no theme palette is available. */\nfunction hueBucket(rgb: Rgb): Exclude<Role, \"surface\"> {\n const r = rgb.r / 255, g = rgb.g / 255, b = rgb.b / 255;\n const max = Math.max(r, g, b), min = Math.min(r, g, b);\n const delta = max - min;\n const lum = (max + min) / 2;\n if (delta < 0.04) {\n // grayscale → treat as primary surface tone (caller decides bg vs surface elsewhere)\n return \"primary\";\n }\n let h = 0;\n if (max === r) h = ((g - b) / delta) % 6;\n else if (max === g) h = (b - r) / delta + 2;\n else h = (r - g) / delta + 4;\n h *= 60;\n if (h < 0) h += 360;\n // very dark or very light → primary fallback\n if (lum < 0.08 || lum > 0.96) return \"primary\";\n if (h < 50 || h >= 285) return \"primary\"; // red → amber, purple → rose\n if (h < 200) return \"accent\"; // yellow → cyan (greens, teals)\n return \"secondary\"; // sky → violet\n}\n\n/** Map an arbitrary hex to a semantic role using theme palette (RGB nearest)\n * or HSL hue bucketing fallback. Used to rewrite arbitrary-value classes. */\nfunction hexToRole(hex: string, themeColors?: Record<string, string>): Role {\n const target = parseHex(hex);\n if (!target) return \"primary\";\n\n if (themeColors) {\n const candidates: Array<[Role, Rgb]> = [];\n for (const role of [\"primary\", \"secondary\", \"accent\", \"surface\"] as Role[]) {\n const v = themeColors[role];\n const rgb = v ? parseHex(v) : null;\n if (rgb) candidates.push([role, rgb]);\n }\n if (candidates.length > 0) {\n let best: Role = candidates[0][0];\n let bestDist = rgbDist(target, candidates[0][1]);\n for (let i = 1; i < candidates.length; i++) {\n const d = rgbDist(target, candidates[i][1]);\n if (d < bestDist) { bestDist = d; best = candidates[i][0]; }\n }\n return best;\n }\n }\n return hueBucket(target);\n}\n\n/** All Tailwind utilities that accept a chromatic arbitrary value and that\n * we map to a *non-text* semantic class (the role itself, not text-on-X). */\nconst BG_LIKE_UTILS = [\n \"bg\", \"border\", \"ring\", \"from\", \"to\", \"via\",\n \"shadow\", \"decoration\", \"outline\", \"divide\", \"accent\", \"placeholder\",\n];\n\n// ── Neutral bg replacements (text rewrites moved to ancestor-aware walker) ──\nconst NEUTRALS = \"slate|gray|zinc|neutral|stone\";\n\nconst neutralReplacements: [RegExp, string][] = [\n // bg-white → bg-surface\n [/\\bbg-white\\b/g, \"bg-surface\"],\n // bg-black → bg-primary-dark\n [/\\bbg-black\\b/g, \"bg-primary-dark\"],\n\n // bg-gray-50/100 → bg-surface\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(50|100)\\\\b`, \"g\"), \"bg-surface\"],\n // bg-gray-200/300 → bg-surface-alt\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(200|300)\\\\b`, \"g\"), \"bg-surface-alt\"],\n // bg-gray-400-600 → bg-primary\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(400|500|600)\\\\b`, \"g\"), \"bg-primary\"],\n // bg-gray-700-950 → bg-primary-dark\n [new RegExp(`\\\\bbg-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"bg-primary-dark\"],\n\n // hover:bg neutrals\n [new RegExp(`\\\\bhover:bg-(${NEUTRALS})-(50|100|200|300)\\\\b`, \"g\"), \"hover:bg-surface-alt\"],\n [new RegExp(`\\\\bhover:bg-(${NEUTRALS})-(400|500|600|700|800|900|950)\\\\b`, \"g\"), \"hover:bg-primary-dark\"],\n];\n\n// Hardcoded text colors get a SEEDED rewrite to text-on-surface (the default fallback).\n// The ancestor-aware walker will then re-target them to the correct on-X variant.\nconst textSeedReplacements: [RegExp, string][] = [\n [/\\btext-white\\b/g, \"text-on-surface-LIGHT\"], // marker: \"was light text\"\n [/\\btext-black\\b/g, \"text-on-surface-DARK\"], // marker: \"was dark text\"\n [new RegExp(`\\\\btext-(${NEUTRALS})-(50|100|200)\\\\b`, \"g\"), \"text-on-surface-LIGHT\"],\n [new RegExp(`\\\\btext-(${NEUTRALS})-(300|400|500|600)\\\\b`, \"g\"), \"text-on-surface-MUTED\"],\n [new RegExp(`\\\\btext-(${NEUTRALS})-(700|800|900|950)\\\\b`, \"g\"), \"text-on-surface-DARK\"],\n [new RegExp(`\\\\bhover:text-(${NEUTRALS})-\\\\d{2,3}\\\\b`, \"g\"), \"hover:text-on-surface\"],\n];\n\n// ── Chromatic replacements ──\nfunction buildChromaticReplacements(): [RegExp, (match: string, color: string) => string][] {\n const re = (prefix: string, shades: string) =>\n new RegExp(`\\\\b${prefix}-(${COLORS})-(${shades})\\\\b`, \"g\");\n\n return [\n // Background\n [re(\"bg\", \"500|600|700\"), (_m, c) => `bg-${categorize(c)}`],\n [re(\"bg\", \"50|100\"), (_m, c) => `bg-${categorize(c)}-light`],\n [re(\"bg\", \"800|900|950\"), (_m, c) => `bg-${categorize(c)}-dark`],\n [re(\"bg\", \"200|300|400\"), (_m, c) => `bg-${categorize(c)}`],\n\n // Text\n [re(\"text\", \"500|600|700\"), (_m, c) => `text-${categorize(c)}`],\n [re(\"text\", \"800|900|950\"), (_m, c) => `text-${categorize(c)}-dark`],\n [re(\"text\", \"50|100|200|300\"), (_m, c) => `text-on-${categorize(c)}`],\n [re(\"text\", \"400\"), (_m, c) => `text-${categorize(c)}`],\n\n // Border\n [re(\"border\", \"\\\\d{2,3}\"), (_m, c) => `border-${categorize(c)}`],\n\n // Ring\n [re(\"ring\", \"\\\\d{2,3}\"), (_m, c) => `ring-${categorize(c)}`],\n\n // Gradients\n [re(\"from\", \"\\\\d{2,3}\"), (_m, c) => `from-${categorize(c)}`],\n [re(\"to\", \"\\\\d{2,3}\"), (_m, c) => `to-${categorize(c)}`],\n [re(\"via\", \"\\\\d{2,3}\"), (_m, c) => `via-${categorize(c)}`],\n\n // Hover/focus variants\n [new RegExp(`\\\\bhover:bg-(${COLORS})-(500|600|700|800|900|950)\\\\b`, \"g\"), (_m, c) => `hover:bg-${categorize(c)}-dark`],\n [new RegExp(`\\\\bhover:bg-(${COLORS})-(50|100|200|300|400)\\\\b`, \"g\"), (_m, c) => `hover:bg-${categorize(c)}-light`],\n [new RegExp(`\\\\bhover:text-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `hover:text-${categorize(c)}`],\n [new RegExp(`\\\\bfocus:ring-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `focus:ring-${categorize(c)}`],\n [new RegExp(`\\\\bfocus:border-(${COLORS})-\\\\d{2,3}\\\\b`, \"g\"), (_m, c) => `focus:border-${categorize(c)}`],\n\n // Divide\n [re(\"divide\", \"\\\\d{2,3}\"), (_m, c) => `divide-${categorize(c)}`],\n\n // Placeholder\n [re(\"placeholder\", \"\\\\d{2,3}\"), (_m, c) => `placeholder-${categorize(c)}`],\n\n // Outline\n [re(\"outline\", \"\\\\d{2,3}\"), (_m, c) => `outline-${categorize(c)}`],\n\n // Shadow colored\n [re(\"shadow\", \"\\\\d{2,3}\"), (_m, c) => `shadow-${categorize(c)}`],\n\n // Decoration\n [re(\"decoration\", \"\\\\d{2,3}\"), (_m, c) => `decoration-${categorize(c)}`],\n\n // Accent (form accent color)\n [re(\"accent\", \"\\\\d{2,3}\"), (_m, c) => `accent-${categorize(c)}`],\n ];\n}\n\nconst chromaticReplacements = buildChromaticReplacements();\n\n// ==================== ANCESTOR-AWARE WALKER ====================\n\ntype BgFamily = \"primary\" | \"secondary\" | \"accent\" | \"surface\" | \"surface-deep\" | null;\n\nconst VOID_TAGS = new Set([\n \"br\", \"hr\", \"img\", \"input\", \"meta\", \"link\", \"area\", \"base\", \"col\",\n \"embed\", \"source\", \"track\", \"wbr\",\n]);\n\n/** Parse a class string and determine the effective bg family (ignoring state variants like hover:).\n * Returns null for low-opacity tints (< 50%) — those are overlays that pass the ancestor bg through,\n * so the text color should be decided against the real ancestor, not the tint.\n */\nfunction detectBgFamily(classStr: string): BgFamily {\n const tokens = classStr.split(/\\s+/).filter((c) => c && !c.includes(\":\"));\n // Last-wins: if an element has multiple bg classes, the rightmost one should reflect intent.\n let found: BgFamily = null;\n for (const t of tokens) {\n // Extract opacity suffix if present (e.g. \"/10\", \"/50\") and ignore anything below 50 —\n // those look through to the ancestor bg and should NOT be treated as a solid background.\n const opMatch = t.match(/\\/(\\d{1,3})$/);\n if (opMatch) {\n const op = parseInt(opMatch[1], 10);\n if (op < 50) continue;\n }\n if (/^bg-primary(?:-light|-dark)?(?:\\/\\d+)?$/.test(t)) found = \"primary\";\n else if (/^bg-secondary(?:\\/\\d+)?$/.test(t)) found = \"secondary\";\n else if (/^bg-accent(?:\\/\\d+)?$/.test(t)) found = \"accent\";\n else if (/^bg-surface-deep(?:\\/\\d+)?$/.test(t)) found = \"surface-deep\";\n else if (/^bg-surface(?:-alt)?(?:\\/\\d+)?$/.test(t)) found = \"surface\";\n }\n if (found) return found;\n // Gradient: infer from from-X stop (only when bg-gradient is present)\n if (tokens.some((t) => /^bg-gradient-/.test(t))) {\n for (const t of tokens) {\n const m = t.match(/^from-(primary|secondary|accent|surface)(?:-light|-dark|-alt)?(?:\\/\\d+)?$/);\n if (m) return m[1] as BgFamily;\n }\n }\n return null;\n}\n\n/** Walk the stack bottom-to-top to find the nearest defined bg family; default to surface. */\nfunction effectiveBg(stack: BgFamily[]): Exclude<BgFamily, null> {\n for (let i = stack.length - 1; i >= 0; i--) {\n const v = stack[i];\n if (v !== null) return v;\n }\n return \"surface\";\n}\n\nfunction onClass(bg: Exclude<BgFamily, null>): string {\n return `text-on-${bg}`;\n}\n\nfunction onMutedClass(bg: Exclude<BgFamily, null>): string {\n if (bg === \"surface\") return \"text-on-surface-muted\";\n if (bg === \"surface-deep\") return \"text-on-surface-deep\";\n return `text-on-${bg}`;\n}\n\n/** Rewrite text-* classes inside a single element's class string based on its effective bg. */\nfunction fixTextClassesForBg(classStr: string, bg: Exclude<BgFamily, null>): string {\n let s = classStr;\n const on = onClass(bg);\n const onMuted = onMutedClass(bg);\n\n // Seeded markers from pass 1 → resolve to correct on-X for this ancestor\n s = s.replace(/\\btext-on-surface-LIGHT\\b/g, on);\n s = s.replace(/\\btext-on-surface-DARK\\b/g, on);\n s = s.replace(/\\btext-on-surface-MUTED\\b/g, onMuted);\n\n // Re-target mis-assigned on-X classes (e.g. text-on-primary inside bg-surface)\n if (bg === \"primary\") {\n s = s.replace(/\\btext-on-surface(?:-muted)?\\b/g, \"text-on-primary\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-primary\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-primary\");\n // text-primary on bg-primary is INVISIBLE (same hue) — rewrite to on-primary\n s = s.replace(/\\btext-primary(?!-(?:light|dark))\\b/g, \"text-on-primary\");\n } else if (bg === \"secondary\") {\n s = s.replace(/\\btext-on-surface(?:-muted)?\\b/g, \"text-on-secondary\");\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-secondary\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-secondary\");\n s = s.replace(/\\btext-secondary\\b/g, \"text-on-secondary\");\n } else if (bg === \"accent\") {\n s = s.replace(/\\btext-on-surface(?:-muted)?\\b/g, \"text-on-accent\");\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-accent\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-accent\");\n s = s.replace(/\\btext-accent\\b/g, \"text-on-accent\");\n } else if (bg === \"surface-deep\") {\n // bg-surface-deep is a dark contrast surface — text must be light.\n // text-on-surface (dark) on bg-surface-deep is invisible. Rewrite all\n // light-text variants → text-on-surface-deep.\n s = s.replace(/\\btext-on-surface(?!-deep)(?:-muted)?\\b/g, \"text-on-surface-deep\");\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-surface-deep\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-surface-deep\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-surface-deep\");\n } else {\n // bg === \"surface\" — text-on-primary/secondary/accent likely invisible on surface\n s = s.replace(/\\btext-on-primary\\b/g, \"text-on-surface\");\n s = s.replace(/\\btext-on-secondary\\b/g, \"text-on-surface\");\n s = s.replace(/\\btext-on-accent\\b/g, \"text-on-surface\");\n }\n\n return s;\n}\n\n/** Ancestor-aware pass: walk HTML, maintain bg stack, rewrite text-* per element. */\nfunction ancestorAwareTextPass(html: string): string {\n try {\n const tagRe = /<(\\/?)([a-zA-Z][a-zA-Z0-9]*)\\b([^>]*?)(\\/?)>/g;\n const stack: BgFamily[] = [];\n let out = \"\";\n let lastIdx = 0;\n let m: RegExpExecArray | null;\n\n while ((m = tagRe.exec(html)) !== null) {\n const [full, slash, tagName, attrs, selfCloseSlash] = m;\n out += html.slice(lastIdx, m.index);\n lastIdx = m.index + full.length;\n\n if (slash === \"/\") {\n // Closing tag\n stack.pop();\n out += full;\n continue;\n }\n\n // Opening (or self-closing) tag\n const classMatch = attrs.match(/\\bclass=\"([^\"]*)\"/);\n const ownBg = classMatch ? detectBgFamily(classMatch[1]) : null;\n const effective: Exclude<BgFamily, null> = ownBg ?? effectiveBg(stack);\n\n let newAttrs = attrs;\n if (classMatch) {\n const fixed = fixTextClassesForBg(classMatch[1], effective);\n if (fixed !== classMatch[1]) {\n newAttrs = attrs.replace(/\\bclass=\"[^\"]*\"/, `class=\"${fixed}\"`);\n }\n }\n out += `<${tagName}${newAttrs}${selfCloseSlash}>`;\n\n const isVoid = VOID_TAGS.has(tagName.toLowerCase()) || selfCloseSlash === \"/\";\n if (!isVoid) stack.push(ownBg);\n }\n out += html.slice(lastIdx);\n\n // Clean up any remaining markers that slipped through (e.g. in malformed fragments)\n out = out\n .replace(/\\btext-on-surface-LIGHT\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-DARK\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-MUTED\\b/g, \"text-on-surface-muted\");\n\n return out;\n } catch {\n // Defensive: if tokenizer trips on weird HTML, return input with markers stripped.\n return html\n .replace(/\\btext-on-surface-LIGHT\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-DARK\\b/g, \"text-on-surface\")\n .replace(/\\btext-on-surface-MUTED\\b/g, \"text-on-surface-muted\");\n }\n}\n\n/** Strip Tailwind JIT arbitrary-value chromatic classes (bg-[#hex], text-[#hex],\n * from-[#hex], etc.) and replace with semantic classes. Models like Gemini often\n * emit these because Tailwind JIT accepts them — they bypass the entire token\n * system and break brandkit/theme swaps. */\nfunction arbitraryValueReplacements(html: string, themeColors?: Record<string, string>): string {\n let s = html;\n\n // bg-like utilities (incl. hover:/focus:/group-hover:/etc. variants), with optional /opacity suffix.\n // Leading (?<![A-Za-z0-9_-]) anchors at a class boundary; trailing (?![A-Za-z0-9_-]) prevents\n // matching into adjacent tokens. \\b doesn't work here because [ and ] are non-word chars.\n const bgUtilGroup = BG_LIKE_UTILS.join(\"|\");\n const bgPattern = new RegExp(\n `(?<![A-Za-z0-9_-])((?:[a-z-]+:)*)(${bgUtilGroup})-\\\\[#([0-9a-fA-F]{3,8})\\\\](\\\\/\\\\d{1,3})?(?![A-Za-z0-9_-])`,\n \"g\"\n );\n s = s.replace(bgPattern, (_m, variants: string, util: string, hex: string, opacity: string | undefined) => {\n const role = hexToRole(hex, themeColors);\n const op = opacity || \"\";\n return `${variants}${util}-${role}${op}`;\n });\n\n // text-[#hex] → seed marker. Walker resolves to text-on-X based on ancestor bg.\n const textPattern = /(?<![A-Za-z0-9_-])((?:[a-z-]+:)*)text-\\[#([0-9a-fA-F]{3,8})\\](\\/\\d{1,3})?(?![A-Za-z0-9_-])/g;\n s = s.replace(textPattern, (_m, variants: string) => {\n // Seed as MUTED — most arbitrary text colors are body copy. Walker upgrades on dark bg.\n return `${variants}text-on-surface-MUTED`;\n });\n\n return s;\n}\n\nexport function sanitizeSemanticColors(\n html: string,\n themeColors?: Record<string, string>\n): string {\n let result = html;\n\n // 1. Replace neutral bg classes (bg-white, bg-gray-*, etc.)\n for (const [pattern, replacement] of neutralReplacements) {\n result = result.replace(pattern, replacement);\n }\n\n // 2. Seed hardcoded text colors with markers that the walker will resolve per ancestor.\n for (const [pattern, replacement] of textSeedReplacements) {\n result = result.replace(pattern, replacement);\n }\n\n // 3. Strip arbitrary chromatic values (bg-[#hex], text-[#hex], from-[#hex], etc.)\n // Done BEFORE chromatic sanitization so the \"hasSemanticClasses\" probe sees the\n // rewritten classes too.\n result = arbitraryValueReplacements(result, themeColors);\n\n // 4. Skip chromatic sanitization if the AI already used semantic classes.\n const hasSemanticClasses = /\\b(?:bg-primary|bg-secondary|bg-accent|bg-surface)\\b/.test(result);\n if (!hasSemanticClasses) {\n for (const [pattern, replacer] of chromaticReplacements) {\n result = result.replace(pattern, replacer as any);\n }\n }\n\n // 5. Ancestor-aware pass: resolve seed markers and fix mis-matched text-on-X classes.\n result = ancestorAwareTextPass(result);\n\n return result;\n}\n"],"mappings":"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","names":["createAnthropic","openaiKey","anthropicKey","createAnthropic"]}
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  dataUrlToImagePart,
3
3
  streamGenerate
4
- } from "./chunk-IDJWYC4U.js";
4
+ } from "./chunk-H2YYYKUI.js";
5
5
  import {
6
6
  buildThemePromptContext
7
- } from "./chunk-VV5I53WR.js";
7
+ } from "./chunk-DCAQAHSU.js";
8
8
 
9
9
  // src/generate.ts
10
10
  var SYSTEM_PROMPT = `You are a world-class web designer who creates AWARD-WINNING landing pages. Your designs win Awwwards, FWA, and CSS Design Awards. You think in terms of visual hierarchy, whitespace, and emotional impact.
@@ -49,8 +49,15 @@ IMAGE OVERLAYS \u2014 CRITICAL:
49
49
  - For testimonial/quote backgrounds: use bg-surface/90 backdrop-blur-sm on the card
50
50
 
51
51
  COLOR SYSTEM \u2014 CRITICAL (READ CAREFULLY):
52
- - 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
52
+ - 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
53
+ - POLARITY of surface tokens (CRITICAL \u2014 agents confuse these):
54
+ \u2022 bg-surface = the page background (light on light themes, dark on dark themes)
55
+ \u2022 bg-surface-alt = a SLIGHT TINT of bg-surface (almost the same lightness \u2014 used for cards/alternating rows). NOT a dark surface. Pair with text-on-surface (NOT text-on-primary).
56
+ \u2022 bg-surface-deep = a HIGH-CONTRAST DARK SURFACE, brand-independent (use for dark cards/footers/sidebars on light themes). Pair with text-on-surface-deep (light text).
57
+ \u2022 bg-secondary = the BRAND'S SECONDARY color (from brandkit). Different from bg-surface-alt \u2014 use this when you want a "second brand color" feel, not just a tint.
58
+ Common mistake: agents reach for "bg-surface-alt + text-on-primary" thinking it's a dark card. That produces white text on near-white background. For dark cards, use bg-surface-deep, bg-primary, or bg-secondary instead.
53
59
  - NEVER use hardcoded Tailwind color classes: NO bg-gray-*, bg-black, bg-white, bg-indigo-*, bg-blue-*, bg-purple-*, text-gray-*, text-black, text-white, etc.
60
+ - 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].
54
61
  - The ONLY exception: border-gray-200 or border-gray-700 for subtle dividers.
55
62
  - ALL backgrounds MUST use: bg-primary, bg-primary-dark, bg-surface, bg-surface-alt
56
63
  - 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).
@@ -131,11 +138,11 @@ IMPORTANT: Make each section VISUALLY UNIQUE \u2014 different layouts, different
131
138
  Think like a premium design agency creating a $50K landing page.
132
139
  NO generic Bootstrap layouts. Use creative grids, bento layouts, overlapping elements, asymmetric columns.`;
133
140
  }
134
- function buildVisualContext(themeName, brandKit) {
141
+ function buildVisualContext(themeName, brandKit, themeColors) {
135
142
  if (!themeName && !brandKit) return "";
136
143
  const lines = ["\n\n## Visual Context \u2014 MANDATORY"];
137
- if (themeName && themeName !== "custom") {
138
- lines.push(buildThemePromptContext(themeName));
144
+ if (themeName) {
145
+ lines.push(buildThemePromptContext(themeName, themeColors));
139
146
  }
140
147
  if (brandKit?.fonts) {
141
148
  const { heading, body } = brandKit.fonts;
@@ -156,12 +163,12 @@ async function generateLanding(options) {
156
163
  referenceImage,
157
164
  extraInstructions,
158
165
  systemPrompt = SYSTEM_PROMPT,
159
- themeColors: _themeColors,
166
+ themeColors,
160
167
  themeName,
161
168
  brandKit,
162
169
  ...rest
163
170
  } = options;
164
- const visualContext = buildVisualContext(themeName, brandKit);
171
+ const visualContext = buildVisualContext(themeName, brandKit, themeColors);
165
172
  const extra = extraInstructions ? `
166
173
  Additional instructions: ${extraInstructions}` : "";
167
174
  const content = [];
@@ -187,7 +194,8 @@ IMPORTANT: Use the reference image as a DIRECT visual guide. Replicate its layou
187
194
  return streamGenerate({
188
195
  ...rest,
189
196
  systemPrompt: systemPrompt + visualContext,
190
- userContent: content
197
+ userContent: content,
198
+ themeColors
191
199
  });
192
200
  }
193
201
 
@@ -196,4 +204,4 @@ export {
196
204
  PROMPT_SUFFIX,
197
205
  generateLanding
198
206
  };
199
- //# sourceMappingURL=chunk-6OJXDEL2.js.map
207
+ //# sourceMappingURL=chunk-QFT3PN3L.js.map