From 8344757c4becd55afa7fc31345e42fdc95c21acc Mon Sep 17 00:00:00 2001 From: khondokartowsif171 Date: Sat, 5 Sep 2026 07:24:24 +0600 Subject: [PATCH] fix: eliminate all hardcoded fantasy strings and unify authentic store layout across all 32 poster themes --- app.js | 2228 ++++++++++++-------------------------------------------- 1 file changed, 456 insertions(+), 1772 deletions(-) diff --git a/app.js b/app.js index 66d7cb2..7d01091 100644 --- a/app.js +++ b/app.js @@ -3547,27 +3547,80 @@ const THEMES = { haloCenter: 'rgba(0, 255, 204, 0.35)', haloMid: 'rgba(6, 182, 212, 0.14)', goldRim: '#00FFCC', goldAccent: '#A7F3D0', pedestalTop: '#064E3B', pedestalMid: '#022C22', pedestalDark: '#011711', - cylStart: '#059669', cylMid: '#00FFCC', cylEnd: '#064E3B', +cylStart: '#059669', cylMid: '#00FFCC', cylEnd: '#064E3B', borderStyle: 'tron_hud' } }; -async function render3DCommercialPoster(canvas, productImg, title, price, badgeText, theme = 'obsidian_gold', aspect = '1:1', brand = 'glamourstouch', customOverrides = null) { +function drawQRCodeTile(ctx, qrX, qrY, qrS) { + ctx.save(); + ctx.fillStyle = '#FFFFFF'; + ctx.beginPath(); + ctx.roundRect(qrX, qrY, qrS, qrS, 8); + ctx.fill(); + + // Finder pattern 1 (Top-Left) + ctx.fillStyle = '#000000'; + ctx.fillRect(qrX + 6, qrY + 6, 20, 20); + ctx.fillStyle = '#FFFFFF'; + ctx.fillRect(qrX + 9, qrY + 9, 14, 14); + ctx.fillStyle = '#000000'; + ctx.fillRect(qrX + 12, qrY + 12, 8, 8); + + // Finder pattern 2 (Top-Right) + ctx.fillRect(qrX + qrS - 26, qrY + 6, 20, 20); + ctx.fillStyle = '#FFFFFF'; + ctx.fillRect(qrX + qrS - 23, qrY + 9, 14, 14); + ctx.fillStyle = '#000000'; + ctx.fillRect(qrX + qrS - 20, qrY + 12, 8, 8); + + // Finder pattern 3 (Bottom-Left) + ctx.fillRect(qrX + 6, qrY + qrS - 26, 20, 20); + ctx.fillStyle = '#FFFFFF'; + ctx.fillRect(qrX + 9, qrY + qrS - 23, 14, 14); + ctx.fillStyle = '#000000'; + ctx.fillRect(qrX + 12, qrY + qrS - 20, 8, 8); + + // Decorative data dots + ctx.fillStyle = '#000000'; + const dotSize = 3.5; + const gridCount = 5; + for (let r = 0; r < gridCount; r++) { + for (let c = 0; c < gridCount; c++) { + if ((r + c) % 2 === 0 || (r * c) % 3 === 0) { + ctx.fillRect(qrX + 30 + c * 5.5, qrY + 30 + r * 5.5, dotSize, dotSize); + } + } + } + ctx.restore(); +} + +async function render3DCommercialPoster(canvas, productImg, title, price, badgeText, theme = 'natural_scandi_wood', aspect = '1:1', brand = 'glamourstouch', customOverrides = null) { + if (!canvas.width || canvas.width <= 300) { + if (aspect === '9:16') { canvas.width = 1080; canvas.height = 1920; } + else if (aspect === '4:5') { canvas.width = 1080; canvas.height = 1350; } + else { canvas.width = 1080; canvas.height = 1080; } + } const ctx = canvas.getContext('2d'); const w = canvas.width; const h = canvas.height; const baseBrand = getBrandProfile(brand); const brandInfo = Object.assign({}, baseBrand, customOverrides || {}); - const currentTheme = THEMES[theme] || THEMES.obsidian_gold; + const currentTheme = THEMES[theme] || THEMES.natural_scandi_wood; - // ================= 8K NATURAL & LIFESTYLE PHOTOGRAPHY PIPELINE ================= - if (currentTheme.isNatural) { - const nType = currentTheme.naturalType; - const isDarkTheme = (nType === 'warm_cafe' || nType === 'velvet_drape'); - const stageY = aspect === '9:16' ? h * 0.62 : h * 0.58; + // 1. Determine Dark/Light Mode & Horizon Geometry + const isNatural = !!currentTheme.isNatural; + const nType = currentTheme.naturalType || ''; + const isDarkTheme = !isNatural || (nType === 'warm_cafe' || nType === 'velvet_drape'); + const tableTopY = aspect === '9:16' ? h * 0.65 : h * 0.60; + const tableH = h - tableTopY; + const pCenterX = aspect === '9:16' ? (w / 2) : (w * 0.62); + const groundY = aspect === '9:16' ? (h * 0.74) : (h * 0.73); - // 1. Natural Ambient Plaster / Linen Backdrop + // 2. BACKDROP & AMBIENCE RENDERING + if (isNatural) { + // Natural Ambient Plaster / Linen Backdrop const naturalGrad = ctx.createLinearGradient(0, 0, w, h); naturalGrad.addColorStop(0, currentTheme.bgCenter); naturalGrad.addColorStop(0.5, currentTheme.bgMid); @@ -3575,17 +3628,15 @@ async function render3DCommercialPoster(canvas, productImg, title, price, badgeT ctx.fillStyle = naturalGrad; ctx.fillRect(0, 0, w, h); - // 2. Natural Sunbeams (God Rays) from top-left + // Natural Sunlight Beams (God Rays) renderNaturalSunlightBeams(ctx, w, h, 0.45, currentTheme.sunlightColor || 'rgba(255, 248, 225, 0.35)'); - // 3. Botanical Leaf Shadows if applicable + // Botanical Leaf Shadows if applicable if (nType === 'botanical_sun' || nType === 'kbeauty_travertine') { renderBotanicalLeafShadows(ctx, w, h); } - // 4. Natural Surface Tabletop / Slab - const tableTopY = aspect === '9:16' ? h * 0.65 : h * 0.60; - const tableH = h - tableTopY; + // Natural Surface Tabletop / Slab if (nType === 'scandi_wood' || nType === 'warm_cafe') { renderNaturalWoodGrain(ctx, 0, tableTopY, w, tableH, nType === 'warm_cafe'); } else if (nType === 'kbeauty_travertine' || nType === 'botanical_sun') { @@ -3607,1233 +3658,70 @@ async function render3DCommercialPoster(canvas, productImg, title, price, badgeT ctx.strokeStyle = 'rgba(0,0,0,0.08)'; ctx.lineWidth = 1.2; ctx.strokeRect(35, 95, w - 70, h - 205); - const crops = [{ x: 25, y: 85 }, { x: w - 25, y: 85 }, { x: 25, y: h - 100 }, { x: w - 25, y: h - 100 }]; - crops.forEach(c => { - ctx.beginPath(); ctx.moveTo(c.x - 10, c.y); ctx.lineTo(c.x + 10, c.y); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(c.x, c.y - 10); ctx.lineTo(c.x, c.y + 10); ctx.stroke(); - }); ctx.restore(); } else if (nType === 'velvet_drape') { renderSilkFabricDrape(ctx, w, h, tableTopY, true); } - - // 5. Intelligent Product Cutout & Placement on Natural Tabletop - if (productImg) { - const pSize = aspect === '9:16' ? 700 : 540; - // Position product on the right side of the canvas, resting solidly on the table - const pCenterX = aspect === '9:16' ? (w / 2) : (w * 0.62); - const groundY = aspect === '9:16' ? (h * 0.74) : (h * 0.73); - const pLeft = pCenterX - pSize / 2; - const pTop = groundY - pSize * 0.88; - - // Realistic Soft Contact Occlusion Shadow directly on the wood/stone surface - renderRealisticContactShadow(ctx, pCenterX, groundY, pSize * 0.38, 22, 45); - - // Smart Cutout Matting (Removes pure white backdrops & smoothly feathers photo edges) - // Smart Cutout Matting (Removes pure white/dark studio backdrops & smoothly feathers photo edges) - const pCan = document.createElement('canvas'); - pCan.width = productImg.width || 600; - pCan.height = productImg.height || 600; - const pCtx = pCan.getContext('2d'); - pCtx.drawImage(productImg, 0, 0, pCan.width, pCan.height); - - try { - const imgData = pCtx.getImageData(0, 0, pCan.width, pCan.height); - const d = imgData.data; - const pw = pCan.width; - const ph = pCan.height; - const featherDist = 24; // Pixels from border to smoothly fade - - // Sample 7 border points to detect background color - let sampleR = 0, sampleG = 0, sampleB = 0, sampleCount = 0; - const cornerCoords = [ - [2, 2], [pw - 3, 2], [2, ph - 3], [pw - 3, ph - 3], - [Math.floor(pw / 2), 2], [2, Math.floor(ph / 2)], [pw - 3, Math.floor(ph / 2)] - ]; - cornerCoords.forEach(([cx, cy]) => { - const ci = (cy * pw + cx) * 4; - if (d[ci + 3] > 100) { - sampleR += d[ci]; - sampleG += d[ci + 1]; - sampleB += d[ci + 2]; - sampleCount++; - } - }); - - const hasBgSample = sampleCount > 0; - const bgR = hasBgSample ? sampleR / sampleCount : 255; - const bgG = hasBgSample ? sampleG / sampleCount : 255; - const bgB = hasBgSample ? sampleB / sampleCount : 255; - const bgBrightness = bgR * 0.299 + bgG * 0.587 + bgB * 0.114; - - for (let y = 0; y < ph; y++) { - for (let x = 0; x < pw; x++) { - const i = (y * pw + x) * 4; - if (d[i + 3] === 0) continue; - - const r = d[i], g = d[i + 1], b = d[i + 2]; - const brightness = (r * 0.299 + g * 0.587 + b * 0.114); - const maxC = Math.max(r, g, b); - const minC = Math.min(r, g, b); - - // 1. Remove white/light grey studio background - if (brightness > 224 && (maxC - minC) < 28) { - if (brightness >= 242) { - d[i + 3] = 0; - } else { - const alphaFactor = (242 - brightness) / 18; - d[i + 3] = Math.round(d[i + 3] * Math.max(0, alphaFactor)); - } - } - // 2. Remove dark studio background if border was dark - else if (bgBrightness < 50 && brightness < 45 && (maxC - minC) < 25) { - if (brightness <= 24) { - d[i + 3] = 0; - } else { - const alphaFactor = (brightness - 24) / 21; - d[i + 3] = Math.round(d[i + 3] * Math.max(0, alphaFactor)); - } - } - // 3. Match detected uniform background color distance - else if (hasBgSample && !isDarkTheme) { - const colorDist = Math.sqrt( - Math.pow(r - bgR, 2) + Math.pow(g - bgG, 2) + Math.pow(b - bgB, 2) - ); - if (colorDist < 28) { - d[i + 3] = 0; - } else if (colorDist < 46) { - const alphaFactor = (colorDist - 28) / 18; - d[i + 3] = Math.round(d[i + 3] * alphaFactor); - } - } - - // 4. Smooth edge feathering for non-cutout square borders - if (d[i + 3] > 0) { - const distLeft = x; - const distRight = pw - 1 - x; - const distTop = y; - const distBottom = ph - 1 - y; - const minDist = Math.min(distLeft, distRight, distTop, distBottom); - - if (minDist < featherDist) { - const edgeFade = Math.pow(minDist / featherDist, 1.2); - d[i + 3] = Math.round(d[i + 3] * edgeFade); - } - } - } - } - pCtx.putImageData(imgData, 0, 0); - } catch (e) { - // Fallback radial fade if cross-origin image blocks pixel read - pCtx.globalCompositeOperation = 'destination-in'; - const fadeGrad = pCtx.createRadialGradient( - pCan.width / 2, pCan.height * 0.48, pCan.width * 0.38, - pCan.width / 2, pCan.height * 0.48, pCan.width * 0.495 - ); - fadeGrad.addColorStop(0, 'rgba(0,0,0,1)'); - fadeGrad.addColorStop(0.90, 'rgba(0,0,0,1)'); - fadeGrad.addColorStop(1, 'rgba(0,0,0,0)'); - pCtx.fillStyle = fadeGrad; - pCtx.fillRect(0, 0, pCan.width, pCan.height); - } - - ctx.save(); - ctx.shadowColor = isDarkTheme ? 'rgba(0, 0, 0, 0.70)' : 'rgba(30, 15, 5, 0.35)'; - ctx.shadowBlur = 26; - ctx.shadowOffsetY = 14; - ctx.drawImage(pCan, pLeft, pTop, pSize, pSize); - ctx.restore(); - - if (nType === 'botanical_sun' || nType === 'kbeauty_travertine') { - renderWaterDewDroplets(ctx, pCenterX, groundY + 14, pSize * 0.32, 22); - } - } - - // 6. TOP EDITORIAL BRAND MASTHEAD (Airy, Sophisticated, Unboxed) - ctx.save(); - const brandName = (brandInfo.headerTitle || brandInfo.id || "GLAMOUR'S TOUCH") - .replace(/[^\w\s\u0980-\u09FF']/gi, '').trim().toUpperCase(); - - // Brand Spaced Lettering - ctx.fillStyle = isDarkTheme ? '#FDE68A' : '#2A1A0E'; - ctx.font = 'bold 20px Playfair Display, Georgia, serif'; - ctx.textAlign = 'left'; - ctx.fillText(`◈ ${brandName}`, 42, 45); - - // Editorial Collection Subhead - let collectionTag = 'SCANDINAVIAN OAK STUDIO // 8K NATURAL LIFESTYLE'; - if (nType === 'botanical_sun') collectionTag = 'BOTANICAL MORNING SUN // 100% ORGANIC FORMULA'; - else if (nType === 'kbeauty_travertine') collectionTag = 'K-BEAUTY TRAVERTINE EDITORIAL // GLASS SKIN'; - else if (nType === 'warm_cafe') collectionTag = 'ARTISAN DARK WALNUT // COZY BOUTIQUE LIFESTYLE'; - else if (nType === 'sunlit_sand') collectionTag = 'SUN-KISSED TERRACOTTA // RAW MINERAL CRAFT'; - else if (nType === 'minimal_flatlay') collectionTag = 'STUDIO FLATLAY PRO // SCALE 1:1 AUTHENTIC'; - else if (nType === 'velvet_drape') collectionTag = 'ROYAL MULBERRY SILK // HAUTE COUTURE EDITION'; - - ctx.fillStyle = isDarkTheme ? 'rgba(253, 230, 138, 0.75)' : currentTheme.accentColor; - ctx.font = 'bold 11px Consolas, monospace'; - ctx.fillText(`EST. 2026 • ${collectionTag}`, 42, 68); - - // Delicate Top Hairline Divider - ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.35)' : 'rgba(160, 125, 84, 0.35)'; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(42, 78); - ctx.lineTo(w - 42, 78); - ctx.stroke(); - - // Top-Right Luxury Artisan Medallion Seal - const sealX = w - 80; - const sealY = 48; - ctx.strokeStyle = isDarkTheme ? '#FDE68A' : currentTheme.goldRim; - ctx.lineWidth = 1.5; - ctx.beginPath(); - ctx.arc(sealX, sealY, 26, 0, Math.PI * 2); - ctx.stroke(); - - ctx.beginPath(); - ctx.arc(sealX, sealY, 22, 0, Math.PI * 2); - ctx.stroke(); - - ctx.fillStyle = isDarkTheme ? '#FDE68A' : currentTheme.accentColor; - ctx.font = 'bold 8.5px Consolas, monospace'; - ctx.textAlign = 'center'; - ctx.fillText('8K PURE', sealX, sealY - 4); - ctx.fillText('STUDIO', sealX, sealY + 7); - ctx.restore(); - - // 7. EDITORIAL PRODUCT TITLE & STORYTELLING (Repositioned to Airy Left Zone) - const textLeft = 42; - const titleMaxWidth = aspect === '9:16' ? (w - 84) : (w * 0.44); - let curY = aspect === '9:16' ? 115 : 108; - - // Eyebrow Tag - ctx.save(); - ctx.fillStyle = isDarkTheme ? '#F59E0B' : currentTheme.accentColor; - ctx.font = 'bold 11.5px Consolas, monospace'; - ctx.textAlign = 'left'; - ctx.fillText('◈ 01 // FEATURED BOTANICAL HARVEST', textLeft, curY); - curY += 28; - - // Main Product Title (Auto line-wrapped high-fashion typography) - ctx.fillStyle = isDarkTheme ? '#FFFFFF' : '#181109'; - ctx.font = 'bold ' + (aspect === '9:16' ? '36px' : '30px') + ' Playfair Display, Hind Siliguri, serif'; - - // Line wrapping helper - const words = title.split(' '); - let currentLine = ''; - const titleLines = []; - for (let i = 0; i < words.length; i++) { - const testLine = currentLine ? `${currentLine} ${words[i]}` : words[i]; - const testWidth = ctx.measureText(testLine).width; - if (testWidth > titleMaxWidth && i > 0) { - titleLines.push(currentLine); - currentLine = words[i]; - if (titleLines.length >= 3) { - currentLine += '...'; - break; - } - } else { - currentLine = testLine; - } - } - if (currentLine) titleLines.push(currentLine); - - titleLines.forEach(line => { - // Soft text glow for maximum legibility against bright sunbeams - ctx.save(); - ctx.shadowColor = isDarkTheme ? 'rgba(0,0,0,0.85)' : 'rgba(255,255,255,0.95)'; - ctx.shadowBlur = 12; - ctx.fillText(line, textLeft, curY); - ctx.restore(); - curY += (aspect === '9:16' ? 44 : 38); - }); - - // Formula & Benefits Subtitle - ctx.fillStyle = isDarkTheme ? '#E2E8F0' : '#4B382A'; - ctx.font = '600 ' + (aspect === '9:16' ? '15px' : '13.5px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.fillText('✦ 100% Active Formula • ✦ 24h Deep Moisture', textLeft, curY); - curY += 32; - - // 8. ARTISAN LUXURY PRICE & DISCOUNT TAG (Parsed Cleanly) - let rawPrice = price || '৳ ১,০৬০'; - let discountTag = '28% OFF'; - let regPriceStr = '৳ ১,৪৭০'; - - const dMatch = rawPrice.match(/(\d+%\s*OFF)/i); - if (dMatch) discountTag = dMatch[1].toUpperCase(); - - const rMatch = rawPrice.match(/\(([^)]+)\)/); - if (rMatch) regPriceStr = rMatch[1]; - - let cleanOfferPrice = rawPrice - .replace(/\([^)]+\)/g, '') - .replace(/\d+%\s*OFF/gi, '') - .trim(); - if (!cleanOfferPrice) cleanOfferPrice = '৳ ১,০৬০'; - - const priceCardY = curY; - const priceCardW = aspect === '9:16' ? (w - 84) : 260; - const priceCardH = 76; - - ctx.save(); - // Frosted linen card - ctx.fillStyle = isDarkTheme ? 'rgba(25, 14, 8, 0.88)' : 'rgba(255, 255, 255, 0.92)'; - ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.40)' : 'rgba(160, 125, 84, 0.35)'; - ctx.lineWidth = 1.2; - ctx.beginPath(); - ctx.roundRect(textLeft, priceCardY, priceCardW, priceCardH, 14); - ctx.fill(); - ctx.stroke(); - - // Main Offer Price - ctx.fillStyle = isDarkTheme ? '#FDE68A' : '#047857'; - ctx.font = '900 28px Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(cleanOfferPrice, textLeft + 16, priceCardY + 40); - - // Regular Price Strikethrough Sub-line - ctx.fillStyle = isDarkTheme ? '#94A3B8' : '#78716C'; - ctx.font = '600 12.5px Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.fillText(`Regular: ${regPriceStr}`, textLeft + 16, priceCardY + 62); - - // Mini Discount Capsule on Right of Price Card - const discX = textLeft + priceCardW - 90; - ctx.fillStyle = isDarkTheme ? '#B45309' : '#059669'; - ctx.beginPath(); - ctx.roundRect(discX, priceCardY + 16, 76, 28, 14); - ctx.fill(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold 11.5px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(discountTag, discX + 38, priceCardY + 34); - ctx.restore(); - - curY += priceCardH + 18; - - // 9. BOTANICAL TRUST BADGES (Rich Vertical Feature Badges on Left) - const isEn = (window.currentLang === 'en'); - const trustBadgesList = [ - { - icon: '🌿', - title: isEn ? (badgeText || '100% Pure Botanical Formula') : (badgeText || '১০০% ভেষজ ও অর্গানিক ফর্মুলা'), - sub: isEn ? 'No Harmful Chemicals • Paraben Free' : 'কোন ক্ষতিকর কেমিক্যাল নেই • প্যারাবেন ফ্রি' - }, - { - icon: '🛡️', - title: brandInfo.badgeL1 || (isEn ? 'Official Store Guarantee' : 'অফিসিয়াল ব্র্যান্ড গ্যারান্টি'), - sub: isEn ? '100% Original Authentic Seal' : '১০০% অরিজিনাল অথেনটিক সিল' - }, - { - icon: '⚡', - title: brandInfo.badgeL2 || (isEn ? 'Fast Express Dispatch' : 'দ্রুত হোম ডেলিভারি'), - sub: isEn ? 'Same-Day Cash on Delivery BD' : 'ক্যাশ অন ডেলিভারি সুবিধা সারা দেশে' - } - ]; - - trustBadgesList.forEach(b => { - ctx.save(); - const badgeBoxW = aspect === '9:16' ? (w - 84) : 260; - const badgeBoxH = 44; - - ctx.fillStyle = isDarkTheme ? 'rgba(30, 18, 10, 0.82)' : 'rgba(255, 255, 255, 0.88)'; - ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.35)' : 'rgba(160, 125, 84, 0.30)'; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.roundRect(textLeft, curY, badgeBoxW, badgeBoxH, 10); - ctx.fill(); - ctx.stroke(); - - // Icon & Title - ctx.fillStyle = isDarkTheme ? '#FDE68A' : '#1E140A'; - ctx.font = 'bold 12.5px Hind Siliguri, Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(`${b.icon} ${b.title}`, textLeft + 12, curY + 20); - - // Sub-line - ctx.fillStyle = isDarkTheme ? '#94A3B8' : '#78716C'; - ctx.font = '600 10.5px Hind Siliguri, Plus Jakarta Sans, sans-serif'; - ctx.fillText(b.sub, textLeft + 30, curY + 35); - - ctx.restore(); - curY += badgeBoxH + 10; - }); - - // 10. 3-COLUMN LUXURY VALUE PROPOSITION STRIP (Fills the lower tabletop beautifully!) - const stripY = aspect === '9:16' ? 1640 : (h - 200); - const stripH = 76; - const stripGap = 16; - const stripCardW = (w - 84 - stripGap * 2) / 3; - - let f1Title = isEn ? '100% Pure & Authentic' : '১০০% বিশুদ্ধ ও আসল'; - let f1Sub = isEn ? 'Lab Certified Active Purity' : 'ল্যাব টেস্টেড ১০০% কোয়ালিটি'; - let f2Title = isEn ? 'Money-Back Guarantee' : 'মানি-ব্যাক গ্যারান্টি'; - let f2Sub = isEn ? '100% Original Sealed Box' : 'অফিসিয়াল ইনট্যাক্ট সিল প্যাক'; - let f3Title = isEn ? 'Cash on Delivery' : 'ক্যাশ অন ডেলিভারি'; - let f3Sub = isEn ? 'Fast 24-48h Doorstep BD' : '২৪-৪৮ ঘণ্টার মধ্যে সারা দেশে'; - - if (brandInfo.category === 'electronics') { - f1Title = isEn ? '1 Year Official Warranty' : '১ বছরের অফিশিয়াল ওয়ারেন্টি'; - f1Sub = isEn ? 'Official Replacement Support' : 'দ্রুত রিপ্লেসমেন্ট গ্যারান্টি'; - } else if (brandInfo.category === 'panjabi' || brandInfo.category === 'fashion') { - f1Title = isEn ? 'Premium Pure Weave' : 'প্রিমিয়াম সুতার নিখুঁত কাজ'; - f1Sub = isEn ? 'Pre-Shrunk Royal Drape' : 'কালার ও সাইজ ট্রায়াল সুবিধা'; - } else if (brandInfo.category === 'sneakerlab') { - f1Title = isEn ? '100% Cowhide Leather' : '১০০% জেনুইন লেদার সোল'; - f1Sub = isEn ? 'Doorstep Fitting Available' : 'হাতে পেয়ে সাইজ ট্রায়াল'; - } - - const lowerFeatures = [ - { icon: '🌿', title: f1Title, sub: f1Sub }, - { icon: '🛡️', title: f2Title, sub: f2Sub }, - { icon: '🚚', title: f3Title, sub: f3Sub } - ]; - - lowerFeatures.forEach((feat, fIdx) => { - const fx = textLeft + fIdx * (stripCardW + stripGap); - ctx.save(); - // Frosted Card Body - ctx.fillStyle = isDarkTheme ? 'rgba(25, 14, 8, 0.90)' : 'rgba(255, 255, 255, 0.92)'; - ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.40)' : 'rgba(160, 125, 84, 0.35)'; - ctx.lineWidth = 1.2; - ctx.beginPath(); - ctx.roundRect(fx, stripY, stripCardW, stripH, 14); - ctx.fill(); - ctx.stroke(); - - // Feature Icon & Title - ctx.fillStyle = isDarkTheme ? '#FDE68A' : '#1E140A'; - ctx.font = 'bold 12.5px Hind Siliguri, Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(`${feat.icon} ${feat.title}`, fx + stripCardW / 2, stripY + 32); - - // Feature Subtitle - ctx.fillStyle = isDarkTheme ? '#94A3B8' : '#78716C'; - ctx.font = '600 10.5px Hind Siliguri, Plus Jakarta Sans, sans-serif'; - ctx.fillText(feat.sub, fx + stripCardW / 2, stripY + 54); - - ctx.restore(); - }); - - // 11. EDITORIAL TRANSLUCENT FOOTER (Minimalist, Floating, No Solid Clunky Green Bar!) - const footerHeight = aspect === '9:16' ? 120 : 100; - const footerTop = h - footerHeight; - - ctx.save(); - // Frosted Glass Footer Background - const footGrad = ctx.createLinearGradient(0, footerTop, 0, h); - if (isDarkTheme) { - footGrad.addColorStop(0, 'rgba(15, 8, 4, 0.94)'); - footGrad.addColorStop(1, 'rgba(8, 4, 2, 0.98)'); - } else { - footGrad.addColorStop(0, 'rgba(255, 255, 255, 0.88)'); - footGrad.addColorStop(1, 'rgba(247, 243, 235, 0.96)'); - } - ctx.fillStyle = footGrad; - ctx.fillRect(0, footerTop, w, footerHeight); - - // Subtle Champagne Gold Top Hairline - ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.50)' : 'rgba(160, 125, 84, 0.40)'; - ctx.lineWidth = 1.2; - ctx.beginPath(); - ctx.moveTo(0, footerTop); - ctx.lineTo(w, footerTop); - ctx.stroke(); - - // WhatsApp Call-to-Action - ctx.fillStyle = isDarkTheme ? '#10B981' : '#047857'; - ctx.font = 'bold ' + (aspect === '9:16' ? '26px' : '23px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(`💬 WhatsApp Order: ${brandInfo.footerHotline}`, 42, footerTop + (aspect === '9:16' ? 44 : 38)); - - // Website & Hotline - ctx.fillStyle = isDarkTheme ? '#94A3B8' : '#64748B'; - ctx.font = '600 ' + (aspect === '9:16' ? '16px' : '14.5px') + ' Plus Jakarta Sans, sans-serif'; - ctx.fillText(`🌐 ${brandInfo.footerSite} • 📞 ${brandInfo.footerHotline} • 🚚 Cash on Delivery BD`, 42, footerTop + (aspect === '9:16' ? 78 : 68)); - - // Sleek White QR Code Tile - const qrS = aspect === '9:16' ? 76 : 68; - const qrX = w - qrS - 42; - const qrY = footerTop + (footerHeight - qrS) / 2; - drawQRCodeTile(ctx, qrX, qrY, qrS); - - ctx.restore(); - - // Subtle Outer Frame Border - ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.45)' : 'rgba(160, 125, 84, 0.35)'; - ctx.lineWidth = 3; - ctx.strokeRect(2, 2, w - 4, h - 4); - - return; // Done with 8K natural rendering - } - - // 1. Studio Radial Backdrop (3D CGI Stages) - const stageCy = aspect === '9:16' ? h * 0.45 : h * 0.44; - const bgGrad = ctx.createRadialGradient(w / 2, stageCy, 40, w / 2, stageCy, w * 0.85); - bgGrad.addColorStop(0, currentTheme.bgCenter); - bgGrad.addColorStop(0.5, currentTheme.bgMid); - bgGrad.addColorStop(1, currentTheme.bgOuter); - ctx.fillStyle = bgGrad; - ctx.fillRect(0, 0, w, h); - - // 1.1 RADICALLY DISTINCT THEME BACKGROUND ARCHITECTURES - if (theme === 'bento_grid_luxe') { - // Apple Bento Box 4-Card Spec Grid - ctx.save(); - // Subtle Dotted Matrix Grid - ctx.fillStyle = 'rgba(255, 255, 255, 0.08)'; - for (let dx = 30; dx < w; dx += 30) { - for (let dy = 110; dy < h - 120; dy += 30) { - ctx.beginPath(); ctx.arc(dx, dy, 1.2, 0, Math.PI * 2); ctx.fill(); - } - } - // Bento Card 1: Large Center-Left Hero Box - const heroBoxW = w * 0.58; - const heroBoxH = aspect === '9:16' ? 1160 : 635; - ctx.fillStyle = 'rgba(15, 23, 42, 0.70)'; - ctx.strokeStyle = 'rgba(56, 189, 248, 0.28)'; - ctx.lineWidth = 1.8; - ctx.beginPath(); ctx.roundRect(40, 115, heroBoxW, heroBoxH, 18); ctx.fill(); ctx.stroke(); - - // Bento Card 2: Top-Right Rating & Sales Card - const rightBoxX = 40 + heroBoxW + 20; - const rightBoxW = w - rightBoxX - 40; - const rightBox1H = aspect === '9:16' ? 360 : 195; - ctx.fillStyle = 'rgba(15, 23, 42, 0.75)'; - ctx.strokeStyle = 'rgba(250, 204, 21, 0.35)'; - ctx.beginPath(); ctx.roundRect(rightBoxX, 115, rightBoxW, rightBox1H, 18); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FACC15'; - ctx.font = 'bold 22px Plus Jakarta Sans, sans-serif'; - ctx.fillText('★ 5.0 RATED', rightBoxX + 22, 160); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '600 15px Plus Jakarta Sans, sans-serif'; - ctx.fillText('★★★★★ TOP SELLER', rightBoxX + 22, 195); - ctx.fillStyle = '#94A3B8'; - ctx.font = '13px Plus Jakarta Sans, sans-serif'; - ctx.fillText('Over 5,000+ Verified Orders in BD', rightBoxX + 22, 230); - - // Bento Card 3: Middle-Right Feature & Authenticity Card - const rightBox2Y = 115 + rightBox1H + 20; - const rightBox2H = aspect === '9:16' ? 360 : 195; - ctx.fillStyle = 'rgba(15, 23, 42, 0.75)'; - ctx.strokeStyle = 'rgba(16, 185, 129, 0.35)'; - ctx.beginPath(); ctx.roundRect(rightBoxX, rightBox2Y, rightBoxW, rightBox2H, 18); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#34D399'; - ctx.font = 'bold 20px Plus Jakarta Sans, sans-serif'; - ctx.fillText('🛡️ 100% ORIGINAL', rightBoxX + 22, rightBox2Y + 45); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '600 15px Plus Jakarta Sans, sans-serif'; - ctx.fillText('⚡ Fast Dispatch BD', rightBoxX + 22, rightBox2Y + 80); - ctx.fillStyle = '#94A3B8'; - ctx.font = '13px Plus Jakarta Sans, sans-serif'; - ctx.fillText('Money-Back Guarantee', rightBoxX + 22, rightBox2Y + 115); - - // Bento Card 4: Bottom-Right Hotline Card - const rightBox3Y = rightBox2Y + rightBox2H + 20; - const rightBox3H = (115 + heroBoxH) - rightBox3Y; - if (rightBox3H > 60) { - ctx.fillStyle = 'rgba(15, 23, 42, 0.75)'; - ctx.strokeStyle = 'rgba(56, 189, 248, 0.35)'; - ctx.beginPath(); ctx.roundRect(rightBoxX, rightBox3Y, rightBoxW, rightBox3H, 18); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#38BDF8'; - ctx.font = 'bold 18px Plus Jakarta Sans, sans-serif'; - ctx.fillText('💬 24/7 SUPPORT', rightBoxX + 22, rightBox3Y + 38); - ctx.fillStyle = '#E2E8F0'; - ctx.font = '600 13px Plus Jakarta Sans, sans-serif'; - ctx.fillText(`Hotline: ${brandInfo.footerHotline}`, rightBoxX + 22, rightBox3Y + 68); - } - ctx.restore(); - } else if (theme === 'swiss_modular_grid') { - // Swiss Bauhaus Architectural 4-Quadrant Precision Grid - ctx.save(); - ctx.strokeStyle = 'rgba(255, 255, 255, 0.20)'; - ctx.lineWidth = 1.5; - // Horizontal cross rule - ctx.beginPath(); ctx.moveTo(40, stageCy - 80); ctx.lineTo(w - 40, stageCy - 80); ctx.stroke(); - // Vertical cross rule - ctx.beginPath(); ctx.moveTo(w * 0.55, 110); ctx.lineTo(w * 0.55, h - 130); ctx.stroke(); - // Central Crosshair - ctx.strokeStyle = '#F43F5E'; - ctx.lineWidth = 2.5; - ctx.beginPath(); - ctx.moveTo(w * 0.55 - 15, stageCy - 80); ctx.lineTo(w * 0.55 + 15, stageCy - 80); - ctx.moveTo(w * 0.55, stageCy - 80 - 15); ctx.lineTo(w * 0.55, stageCy - 80 + 15); - ctx.stroke(); - - // Quadrant Indices - ctx.fillStyle = '#F43F5E'; - ctx.font = '900 14px Consolas, monospace'; - ctx.fillText('[ 01 // ARCHIVE ]', 50, 135); - ctx.fillText('[ 02 // SPECIFICATION ]', w * 0.55 + 20, 135); - ctx.fillText('[ 03 // HERO_STAGE ]', 50, stageCy - 55); - ctx.fillText('[ 04 // COMMERCIAL_VAL ]', w * 0.55 + 20, stageCy - 55); - - // Vertical Barcode in Quadrant 2 - ctx.fillStyle = '#FFFFFF'; - ctx.fillRect(w - 75, 150, 35, 120); - ctx.fillStyle = '#000000'; - for (let bx = 0; bx < 30; bx += 3) { - if ((bx % 2 === 0)) ctx.fillRect(w - 72 + bx, 155, 2, 110); - } - ctx.restore(); - } else if (theme === 'blueprint_cad_grid') { - // Industrial CAD Blueprint Engineering Grid with Caliper Dimensions - ctx.save(); - // Major & Minor Cyan Grid lines - ctx.strokeStyle = 'rgba(56, 189, 248, 0.08)'; - ctx.lineWidth = 1; - for (let gx = 0; gx < w; gx += 15) { - ctx.beginPath(); ctx.moveTo(gx, 0); ctx.lineTo(gx, h); ctx.stroke(); - } - for (let gy = 0; gy < h; gy += 15) { - ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(w, gy); ctx.stroke(); - } - ctx.strokeStyle = 'rgba(56, 189, 248, 0.22)'; - ctx.lineWidth = 1.5; - for (let gx = 0; gx < w; gx += 60) { - ctx.beginPath(); ctx.moveTo(gx, 0); ctx.lineTo(gx, h); ctx.stroke(); - } - for (let gy = 0; gy < h; gy += 60) { - ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(w, gy); ctx.stroke(); - } - - // CAD Caliper Dimension Line across Top - const dimY = 145; - ctx.strokeStyle = '#38BDF8'; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(w * 0.18, dimY); ctx.lineTo(w * 0.82, dimY); - ctx.moveTo(w * 0.18, dimY - 10); ctx.lineTo(w * 0.18, dimY + 10); - ctx.moveTo(w * 0.82, dimY - 10); ctx.lineTo(w * 0.82, dimY + 10); - ctx.stroke(); - - ctx.fillStyle = '#0284C7'; - ctx.fillRect(w / 2 - 80, dimY - 12, 160, 24); - ctx.fillStyle = '#E0F2FE'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.textAlign = 'center'; - ctx.fillText('|← 320.0 mm →|', w / 2, dimY + 5); - - // CAD Angle Caliper & Title Block - ctx.textAlign = 'left'; - ctx.fillStyle = '#BAE6FD'; - ctx.font = 'bold 12px Consolas, monospace'; - ctx.fillText('TOLERANCE: ±0.01 mm // ANGLE: ∠ 90°', 45, h - 145); - ctx.textAlign = 'right'; - ctx.fillText('DWG: CAD-2026 // REV: A1 // PASS', w - 45, h - 145); - ctx.restore(); - } else if (theme === 'polaroid_film_grid') { - // 35mm Filmstrip Contact Sheet Grid with Perforations - ctx.save(); - // Film Perforation Sprocket Holes - const sprocH = 18; - const sprocW = 14; - ctx.fillStyle = '#000000'; - ctx.strokeStyle = '#D97706'; - ctx.lineWidth = 1; - for (let sy = 10; sy < h - 20; sy += 38) { - // Left sprocket - ctx.fillRect(12, sy, sprocW, sprocH); - ctx.strokeRect(12, sy, sprocW, sprocH); - // Right sprocket - ctx.fillRect(w - 26, sy, sprocW, sprocH); - ctx.strokeRect(w - 26, sy, sprocW, sprocH); - } - // Film Edge Barcode & Frame Counter - ctx.fillStyle = '#D97706'; - ctx.font = 'bold 12px Consolas, monospace'; - ctx.fillText('KODAK 400TX // 24A', 40, 125); - ctx.textAlign = 'right'; - ctx.fillText('ISO 400 • FRAME 24', w - 40, 125); - ctx.restore(); - } else if (theme === 'cyber_hud_grid') { - // Tron Cyber HUD 4-Corner Telemetry Pods - ctx.save(); - // 4 Corner Telemetry Pods - const podW = 190; - const podH = 85; - // Top-Left Pod - ctx.fillStyle = 'rgba(6, 78, 59, 0.45)'; - ctx.strokeStyle = '#00FFCC'; ctx.lineWidth = 1.5; - ctx.strokeRect(45, 120, podW, podH); - ctx.fillStyle = '#00FFCC'; ctx.font = 'bold 12px Consolas, monospace'; - ctx.fillText('SYS.HEALTH: 100%', 55, 145); - // Green Bar Graph - ctx.fillStyle = '#059669'; ctx.fillRect(55, 155, 140, 8); - ctx.fillStyle = '#00FFCC'; ctx.fillRect(55, 155, 110, 8); - ctx.fillStyle = '#A7F3D0'; ctx.fillText('STATUS: OPTIMAL', 55, 185); - - // Top-Right Pod - ctx.strokeStyle = '#00FFCC'; - ctx.strokeRect(w - podW - 45, 120, podW, podH); - ctx.fillStyle = '#00FFCC'; - ctx.fillText('RADAR_GPS // BD', w - podW - 35, 145); - // Circular Radar Sweep - ctx.beginPath(); ctx.arc(w - 90, 165, 20, 0, Math.PI * 2); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(w - 90, 145); ctx.lineTo(w - 90, 185); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(w - 110, 165); ctx.lineTo(w - 70, 165); ctx.stroke(); - - // Bottom-Left Equalizer Bars - ctx.strokeStyle = '#00FFCC'; - ctx.strokeRect(45, h - podH - 140, podW, podH); - ctx.fillStyle = '#00FFCC'; - ctx.fillText('TELEMETRY_FREQ', 55, h - podH - 120); - const eqBars = [25, 45, 30, 60, 40, 55, 35, 65, 50, 40, 60, 30]; - eqBars.forEach((bh, bidx) => { - ctx.fillStyle = '#00FFCC'; - ctx.fillRect(55 + bidx * 12, h - 150 - bh * 0.4, 8, bh * 0.4); - }); - - // Bottom-Right Encryption Pod - ctx.strokeStyle = '#00FFCC'; - ctx.strokeRect(w - podW - 45, h - podH - 140, podW, podH); - ctx.fillStyle = '#00FFCC'; - ctx.fillText('SECURE: 256-BIT', w - podW - 35, h - podH - 120); - ctx.fillStyle = '#A7F3D0'; ctx.font = '10px Consolas, monospace'; - ctx.fillText('HEX: 0x8F4A9C', w - podW - 35, h - podH - 95); - ctx.fillText('HASH: OK // VERIFIED', w - podW - 35, h - podH - 75); - ctx.restore(); - } else if (theme === 'mughal_heritage') { - // Grand Mughal Cusped Arch with Hanging Brass Lanterns & Arabesque Jali Lattice - ctx.save(); - // Arabesque Jali lattice background grid - ctx.strokeStyle = 'rgba(245, 158, 11, 0.08)'; - ctx.lineWidth = 1; - for (let jx = 40; jx < w; jx += 45) { - for (let jy = 100; jy < h - 120; jy += 45) { - ctx.strokeRect(jx, jy, 30, 30); - ctx.beginPath(); ctx.arc(jx + 15, jy + 15, 12, 0, Math.PI * 2); ctx.stroke(); - } - } - // Outer Grand Cusped Arch - ctx.strokeStyle = 'rgba(245, 158, 11, 0.45)'; - ctx.lineWidth = 6; - ctx.beginPath(); - ctx.moveTo(w * 0.12, h * 0.72); - ctx.lineTo(w * 0.12, h * 0.32); - ctx.quadraticCurveTo(w * 0.22, h * 0.12, w * 0.5, h * 0.09); - ctx.quadraticCurveTo(w * 0.78, h * 0.12, w * 0.88, h * 0.32); - ctx.lineTo(w * 0.88, h * 0.72); - ctx.stroke(); - - // Inner Arch Gold Accent - ctx.strokeStyle = 'rgba(253, 230, 138, 0.30)'; - ctx.lineWidth = 2.5; - ctx.beginPath(); - ctx.moveTo(w * 0.16, h * 0.70); - ctx.lineTo(w * 0.16, h * 0.34); - ctx.quadraticCurveTo(w * 0.25, h * 0.15, w * 0.5, h * 0.12); - ctx.quadraticCurveTo(w * 0.75, h * 0.15, w * 0.84, h * 0.34); - ctx.lineTo(w * 0.84, h * 0.70); - ctx.stroke(); - - // Hanging Brass Lanterns - const lanternPositions = [w * 0.22, w * 0.78]; - lanternPositions.forEach(lx => { - ctx.strokeStyle = 'rgba(245, 158, 11, 0.6)'; - ctx.lineWidth = 2; - ctx.beginPath(); ctx.moveTo(lx, 94); ctx.lineTo(lx, 210); ctx.stroke(); - // Lantern Body - ctx.fillStyle = '#78350F'; - ctx.fillRect(lx - 12, 210, 24, 30); - ctx.fillStyle = '#FDE68A'; - ctx.beginPath(); ctx.arc(lx, 225, 8, 0, Math.PI * 2); ctx.fill(); - ctx.strokeStyle = '#F59E0B'; ctx.strokeRect(lx - 12, 210, 24, 30); - }); - ctx.restore(); - } else if (theme === 'brutalist_street') { - // Industrial Brutalist Concrete Grid, Diagonal Hazard Corners, Stencil Watermarks & Tech Reticles - ctx.save(); - // Top & Bottom Diagonal Caution Hazard Stripes - const stripeW = 28; - ctx.fillStyle = '#FACC15'; - for (let hx = 0; hx < w; hx += stripeW * 2) { - ctx.beginPath(); - ctx.moveTo(hx, 0); ctx.lineTo(hx + stripeW, 0); - ctx.lineTo(hx + stripeW - 20, 24); ctx.lineTo(hx - 20, 24); - ctx.closePath(); ctx.fill(); - } - // Tech Coordinates & Watermark - ctx.fillStyle = 'rgba(250, 204, 21, 0.08)'; - ctx.font = '900 75px Impact, Arial Black, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('HEAVYWEIGHT // 2026', w / 2, stageCy - 120); - - ctx.fillStyle = 'rgba(250, 204, 21, 0.30)'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.textAlign = 'left'; - ctx.fillText('[ LAT: 23.8103° N // LON: 90.4125° E ]', 45, 125); - ctx.textAlign = 'right'; - ctx.fillText('[ SPEC_ID: BST-8820 // AUTHENTIC ]', w - 45, 125); - - // Crosshair Reticles - const reticles = [{ x: 50, y: 160 }, { x: w - 50, y: 160 }, { x: 50, y: h - 140 }, { x: w - 50, y: h - 140 }]; - ctx.strokeStyle = 'rgba(250, 204, 21, 0.45)'; - ctx.lineWidth = 1.5; - reticles.forEach(r => { - ctx.beginPath(); - ctx.moveTo(r.x - 12, r.y); ctx.lineTo(r.x + 12, r.y); - ctx.moveTo(r.x, r.y - 12); ctx.lineTo(r.x, r.y + 12); - ctx.stroke(); - ctx.strokeRect(r.x - 6, r.y - 6, 12, 12); - }); - ctx.restore(); - } else if (theme === 'cyber_neon') { - // 3D Isometric Cyber Grid receding to horizon, digital scanlines, telemetry HUD - ctx.save(); - const horizonY = aspect === '9:16' ? 1120 : 710; - // Perspective Floor Grid - ctx.strokeStyle = 'rgba(6, 182, 212, 0.32)'; - ctx.lineWidth = 1.8; - for (let gx = -w * 0.4; gx <= w * 1.4; gx += 75) { - ctx.beginPath(); ctx.moveTo(w / 2, horizonY - 140); ctx.lineTo(gx, h); ctx.stroke(); - } - for (let gy = horizonY - 80; gy < h; gy += 42) { - ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(w, gy); ctx.stroke(); - } - // Horizontal Scanlines - ctx.fillStyle = 'rgba(6, 182, 212, 0.04)'; - for (let sy = 0; sy < h; sy += 6) { - ctx.fillRect(0, sy, w, 2); - } - // Glowing Neon Target Rings - ctx.strokeStyle = 'rgba(56, 189, 248, 0.25)'; - ctx.lineWidth = 2; - ctx.beginPath(); ctx.arc(w / 2, stageCy - 30, 260, 0, Math.PI * 2); ctx.stroke(); - ctx.strokeStyle = 'rgba(244, 63, 94, 0.20)'; - ctx.beginPath(); ctx.arc(w / 2, stageCy - 30, 285, 0, Math.PI * 2); ctx.stroke(); - // Telemetry text - ctx.fillStyle = '#06B6D4'; - ctx.font = 'bold 12px Consolas, monospace'; - ctx.fillText('SYS.STATUS // ONLINE [ 4K_UHD ]', 45, 125); - ctx.textAlign = 'right'; - ctx.fillText('FREQ: 144Hz // QUANTUM_CORE', w - 45, 125); - ctx.restore(); - } else if (theme === 'editorial_vogue') { - // Vogue Haute Magazine Watermark & Fine Swiss Gridlines - ctx.save(); - ctx.fillStyle = 'rgba(255, 255, 255, 0.05)'; - ctx.font = '900 160px Playfair Display, Georgia, serif'; - ctx.textAlign = 'center'; - ctx.fillText('V O G U E', w / 2, stageCy - 80); - - // Fine Swiss Hairlines - ctx.strokeStyle = 'rgba(255, 255, 255, 0.12)'; - ctx.lineWidth = 1; - ctx.beginPath(); ctx.moveTo(40, 110); ctx.lineTo(w - 40, 110); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(40, h - 130); ctx.lineTo(w - 40, h - 130); ctx.stroke(); - // Minimalist Corner crop marks - const crops = [{ x: 25, y: 105 }, { x: w - 25, y: 105 }, { x: 25, y: h - 115 }, { x: w - 25, y: h - 115 }]; - crops.forEach(c => { - ctx.beginPath(); ctx.moveTo(c.x - 8, c.y); ctx.lineTo(c.x + 8, c.y); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(c.x, c.y - 8); ctx.lineTo(c.x, c.y + 8); ctx.stroke(); - }); - ctx.restore(); - } else if (theme === 'botanical_eco') { - // Botanical Tropical Leaves & Soft God Rays - ctx.save(); - // Morning Sunbeams - ctx.globalCompositeOperation = 'screen'; - const sunbeam = ctx.createRadialGradient(w * 0.2, 80, 10, w * 0.2, 80, 500); - sunbeam.addColorStop(0, 'rgba(110, 231, 183, 0.35)'); - sunbeam.addColorStop(0.6, 'rgba(16, 185, 129, 0.10)'); - sunbeam.addColorStop(1, 'transparent'); - ctx.fillStyle = sunbeam; - ctx.beginPath(); ctx.arc(w * 0.2, 80, 500, 0, Math.PI * 2); ctx.fill(); - - // Tropical Foliage Silhouettes at top corners - ctx.fillStyle = 'rgba(6, 78, 59, 0.35)'; - // Left monstera leaf silhouette - ctx.beginPath(); - ctx.ellipse(90, 180, 80, 120, Math.PI / 4, 0, Math.PI * 2); - ctx.fill(); - // Right leaf silhouette - ctx.beginPath(); - ctx.ellipse(w - 90, 200, 75, 110, -Math.PI / 4, 0, Math.PI * 2); - ctx.fill(); - ctx.restore(); - } else if (theme === 'tokyo_synthwave') { - // Segmented Retrowave Glowing Sun & Retro Laser Floor - ctx.save(); - const horizonY = aspect === '9:16' ? 1120 : 710; - // Retrowave Sun Disc - const sunY = horizonY - 100; - const sunR = 150; - const sunGrad = ctx.createLinearGradient(0, sunY - sunR, 0, sunY + sunR); - sunGrad.addColorStop(0, '#FACC15'); - sunGrad.addColorStop(0.5, '#F43F5E'); - sunGrad.addColorStop(1, '#9333EA'); - ctx.fillStyle = sunGrad; - ctx.beginPath(); ctx.arc(w / 2, sunY, sunR, Math.PI, 0); ctx.fill(); - // Sun horizontal slice lines - ctx.fillStyle = '#100520'; - for (let sl = 0; sl < 6; sl++) { - ctx.fillRect(w / 2 - sunR, sunY - 40 + sl * 14, sunR * 2, 4 + sl * 1.5); - } - // Laser Floor Grid - ctx.strokeStyle = 'rgba(244, 63, 94, 0.35)'; - ctx.lineWidth = 1.8; - for (let gx = -w * 0.5; gx <= w * 1.5; gx += 80) { - ctx.beginPath(); ctx.moveTo(w / 2, horizonY); ctx.lineTo(gx, h); ctx.stroke(); - } - for (let gy = horizonY; gy < h; gy += 42) { - ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(w, gy); ctx.stroke(); - } - ctx.restore(); - } else if (theme === 'holographic_prism') { - // Iridescent Caustic Dispersion Beams & Floating Gem Shards - ctx.save(); - ctx.globalCompositeOperation = 'screen'; - // Rainbow dispersion rays - const colors = ['rgba(236,72,153,0.2)', 'rgba(168,85,247,0.2)', 'rgba(56,189,248,0.2)', 'rgba(52,211,153,0.2)']; - colors.forEach((c, idx) => { - const ray = ctx.createLinearGradient(0, 0, w, h); - ray.addColorStop(0, 'transparent'); - ray.addColorStop(0.3 + idx * 0.15, c); - ray.addColorStop(1, 'transparent'); - ctx.fillStyle = ray; - ctx.fillRect(0, 0, w, h); - }); - // Gem Shards - ctx.strokeStyle = 'rgba(240, 171, 252, 0.4)'; - ctx.lineWidth = 1.5; - const shards = [{x: w*0.18, y: 220, s: 20}, {x: w*0.82, y: 240, s: 24}, {x: w*0.14, y: 480, s: 18}, {x: w*0.86, y: 500, s: 22}]; - shards.forEach(sh => { - ctx.beginPath(); - ctx.moveTo(sh.x, sh.y - sh.s); ctx.lineTo(sh.x + sh.s, sh.y); - ctx.lineTo(sh.x, sh.y + sh.s); ctx.lineTo(sh.x - sh.s, sh.y); - ctx.closePath(); ctx.stroke(); - }); - ctx.restore(); - } else if (theme === 'frost_titanium') { - // Sub-Zero Ice Crystals, Frosted Vignette & Cryo Fog - ctx.save(); - ctx.strokeStyle = 'rgba(186, 230, 253, 0.35)'; - ctx.lineWidth = 1.5; - const flakes = [{x: w*0.15, y: 180, r: 16}, {x: w*0.85, y: 220, r: 20}, {x: w*0.2, y: 520, r: 14}, {x: w*0.8, y: 550, r: 18}]; - flakes.forEach(f => { - for (let a = 0; a < 6; a++) { - const rad = (a * Math.PI) / 3; - ctx.beginPath(); - ctx.moveTo(f.x, f.y); - ctx.lineTo(f.x + Math.cos(rad) * f.r, f.y + Math.sin(rad) * f.r); - ctx.stroke(); - } - }); - ctx.restore(); - } else if (theme === 'vip_blackcard') { - // Carbon Fiber Weave Texture & Gold Concentric Luxury Rings - ctx.save(); - ctx.strokeStyle = 'rgba(212, 175, 55, 0.12)'; - ctx.lineWidth = 1; - for (let r = 80; r <= 420; r += 45) { - ctx.beginPath(); ctx.arc(w / 2, stageCy, r, 0, Math.PI * 2); ctx.stroke(); - } - ctx.fillStyle = 'rgba(212, 175, 55, 0.06)'; - ctx.font = '900 80px Cinzel, Times New Roman, serif'; - ctx.textAlign = 'center'; - ctx.fillText('CENTURION', w / 2, stageCy - 100); - ctx.restore(); - } else if (theme === 'sunset_amber') { - // Giant Sunset Sun Disc & Heat Haze - ctx.save(); - const sunGrad = ctx.createRadialGradient(w / 2, stageCy - 60, 20, w / 2, stageCy - 60, 260); - sunGrad.addColorStop(0, 'rgba(251, 146, 60, 0.55)'); - sunGrad.addColorStop(0.5, 'rgba(234, 88, 12, 0.20)'); - sunGrad.addColorStop(1, 'transparent'); - ctx.fillStyle = sunGrad; - ctx.beginPath(); ctx.arc(w / 2, stageCy - 60, 260, 0, Math.PI * 2); ctx.fill(); - ctx.restore(); - } else if (theme === 'flash_sale_matrix') { - // High-Voltage Lightning Bolts & Speed Flares - ctx.save(); - ctx.strokeStyle = 'rgba(239, 68, 68, 0.45)'; - ctx.lineWidth = 3; - ctx.beginPath(); - ctx.moveTo(w * 0.08, 120); ctx.lineTo(w * 0.24, 260); ctx.lineTo(w * 0.16, 380); ctx.lineTo(w * 0.30, 540); - ctx.stroke(); - ctx.beginPath(); - ctx.moveTo(w * 0.92, 140); ctx.lineTo(w * 0.76, 290); ctx.lineTo(w * 0.84, 420); ctx.lineTo(w * 0.70, 580); - ctx.stroke(); - ctx.restore(); - } else if (theme === 'art_deco_gilded') { - // 1920s Gatsby Art Deco Fan & Sunburst Geometric Lines - ctx.save(); - ctx.strokeStyle = 'rgba(234, 179, 8, 0.25)'; - ctx.lineWidth = 1.5; - for (let ang = -Math.PI * 0.75; ang <= -Math.PI * 0.25; ang += 0.06) { - ctx.beginPath(); - ctx.moveTo(w / 2, h * 0.75); - ctx.lineTo(w / 2 + Math.cos(ang) * w, h * 0.75 + Math.sin(ang) * w); - ctx.stroke(); - } - // Art deco concentric diamonds - [100, 180, 260].forEach(d => { - ctx.beginPath(); - ctx.moveTo(w / 2, stageCy - d); ctx.lineTo(w / 2 + d * 1.3, stageCy); - ctx.lineTo(w / 2, stageCy + d); ctx.lineTo(w / 2 - d * 1.3, stageCy); - ctx.closePath(); ctx.stroke(); - }); - ctx.restore(); - } else if (theme === 'cosmic_nebula') { - // Swirling Nebula Clouds & Planetary Gravity Rings - ctx.save(); - ctx.globalCompositeOperation = 'screen'; - const neb1 = ctx.createRadialGradient(w * 0.25, stageCy - 80, 30, w * 0.25, stageCy - 80, 320); - neb1.addColorStop(0, 'rgba(168, 85, 247, 0.45)'); - neb1.addColorStop(0.6, 'rgba(236, 72, 153, 0.15)'); - neb1.addColorStop(1, 'transparent'); - ctx.fillStyle = neb1; - ctx.beginPath(); ctx.arc(w * 0.25, stageCy - 80, 320, 0, Math.PI * 2); ctx.fill(); - - // Orbital Ring - ctx.strokeStyle = 'rgba(192, 132, 252, 0.35)'; - ctx.lineWidth = 2.5; - ctx.beginPath(); - ctx.ellipse(w / 2, stageCy, w * 0.42, 70, -0.3, 0, Math.PI * 2); - ctx.stroke(); - ctx.restore(); - } else if (theme === 'arcade_retro') { - // 8-Bit Pixel Grid & Marquee Stars - ctx.save(); - ctx.fillStyle = 'rgba(56, 189, 248, 0.05)'; - for (let px = 0; px < w; px += 24) { - for (let py = 100; py < h - 120; py += 24) { - if ((px + py) % 48 === 0) ctx.fillRect(px, py, 18, 18); - } - } - ctx.restore(); - } - - // 2. Volumetric Softbox Light Beam - const beamBottomY = aspect === '9:16' ? 1150 : 730; - ctx.save(); - ctx.globalCompositeOperation = 'screen'; - const beamGrad = ctx.createLinearGradient(w / 2, 94, w / 2, beamBottomY); - beamGrad.addColorStop(0, currentTheme.beamTop); - beamGrad.addColorStop(0.25, currentTheme.beamMid); - beamGrad.addColorStop(0.65, currentTheme.beamLow); - beamGrad.addColorStop(1, 'rgba(0, 0, 0, 0)'); - ctx.fillStyle = beamGrad; - ctx.beginPath(); - ctx.moveTo(w * 0.34, 94); ctx.lineTo(w * 0.66, 94); - ctx.lineTo(w * 0.86, beamBottomY); ctx.lineTo(w * 0.14, beamBottomY); - ctx.closePath(); ctx.fill(); - - // Halo Glow behind product - const haloY = aspect === '9:16' ? 750 : 420; - const haloR = aspect === '9:16' ? 420 : 280; - const haloGrad = ctx.createRadialGradient(w / 2, haloY, 15, w / 2, haloY, haloR); - haloGrad.addColorStop(0, currentTheme.haloCenter); - haloGrad.addColorStop(0.5, currentTheme.haloMid); - haloGrad.addColorStop(1, 'transparent'); - ctx.fillStyle = haloGrad; - ctx.beginPath(); ctx.arc(w / 2, haloY, haloR, 0, Math.PI * 2); ctx.fill(); - ctx.restore(); - - // Floating Stardust Particles - const particles = [ - { x: w * 0.18, y: h * 0.21, r: 3.5, a: 0.85 }, - { x: w * 0.82, y: h * 0.25, r: 4.0, a: 0.90 }, - { x: w * 0.13, y: h * 0.44, r: 2.5, a: 0.60 }, - { x: w * 0.87, y: h * 0.48, r: 3.2, a: 0.75 }, - { x: w * 0.24, y: h * 0.62, r: 2.2, a: 0.50 }, - { x: w * 0.77, y: h * 0.65, r: 3.5, a: 0.80 }, - { x: w * 0.50, y: h * 0.14, r: 4.5, a: 0.95 } - ]; - particles.forEach(p => { - ctx.save(); - ctx.fillStyle = currentTheme.goldAccent; - ctx.globalAlpha = p.a; - ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2); ctx.fill(); - ctx.strokeStyle = '#FFFFFF'; ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(p.x - p.r * 2.5, p.y); ctx.lineTo(p.x + p.r * 2.5, p.y); - ctx.moveTo(p.x, p.y - p.r * 2.5); ctx.lineTo(p.x, p.y + p.r * 2.5); - ctx.stroke(); - ctx.restore(); - }); - - // 3. RADICALLY DISTINCT 3D ARCHITECTURAL PODIUMS - let stageCx = w / 2; - if (theme === 'bento_grid_luxe') { - stageCx = 40 + (w * 0.58) / 2; - } else if (theme === 'swiss_modular_grid') { - stageCx = 40 + (w * 0.55 - 40) / 2; - } - - const topTierY = aspect === '9:16' ? 1160 : 705; - const topTierRx = theme === 'bento_grid_luxe' || theme === 'swiss_modular_grid' ? w * 0.24 : (aspect === '9:16' ? w * 0.32 : w * 0.30); - const topTierRy = aspect === '9:16' ? 26 : 24; - const topTierH = aspect === '9:16' ? 36 : 35; - const baseTierY = aspect === '9:16' ? 1200 : 740; - const baseTierRx = aspect === '9:16' ? w * 0.38 : w * 0.36; - const baseTierRy = aspect === '9:16' ? 32 : 30; - const baseTierH = aspect === '9:16' ? 26 : 24; - - if (theme === 'bento_grid_luxe') { - // Apple Bento Floating Frosted Glass Riser - ctx.save(); - ctx.fillStyle = 'rgba(0,0,0,0.70)'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + 15, topTierRx * 1.05, topTierRy * 1.1, 0, 0, Math.PI * 2); ctx.fill(); - // Glass Disc Body - ctx.fillStyle = 'rgba(30, 41, 59, 0.85)'; - ctx.fillRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - ctx.strokeStyle = 'rgba(56, 189, 248, 0.45)'; ctx.lineWidth = 2; - ctx.strokeRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - // Cap - ctx.fillStyle = '#0F172A'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.stroke(); - ctx.restore(); - } else if (theme === 'blueprint_cad_grid') { - // Industrial CAD Isometric Riser with Wireframe Grid - ctx.save(); - ctx.fillStyle = 'rgba(0,0,0,0.92)'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + 25, topTierRx * 1.1, topTierRy * 1.2, 0, 0, Math.PI * 2); ctx.fill(); - ctx.fillStyle = '#082F49'; - ctx.fillRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - ctx.strokeStyle = '#38BDF8'; ctx.lineWidth = 1.8; - // CAD Grid lines on riser - for (let px = stageCx - topTierRx; px <= stageCx + topTierRx; px += 25) { - ctx.beginPath(); ctx.moveTo(px, topTierY); ctx.lineTo(px, topTierY + topTierH); ctx.stroke(); - } - ctx.fillStyle = '#0369A1'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.stroke(); - ctx.restore(); - } else if (theme === 'cyber_hud_grid') { - // Tron Glowing Green/Cyan Holographic Ring Platform - ctx.save(); - ctx.strokeStyle = '#00FFCC'; ctx.lineWidth = 3.5; - ctx.shadowColor = '#00FFCC'; ctx.shadowBlur = 18; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + 8, topTierRx * 1.15, topTierRy * 1.15, 0, 0, Math.PI * 2); ctx.stroke(); - ctx.fillStyle = '#022C22'; - ctx.fillRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - ctx.fillStyle = '#064E3B'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.stroke(); - ctx.restore(); - } else if (theme === 'brutalist_street') { - // Industrial Diamond Plate Steel Riser with Hazard Warning Face - ctx.save(); - ctx.fillStyle = 'rgba(0,0,0,0.95)'; - ctx.beginPath(); ctx.ellipse(stageCx, baseTierY + 30, baseTierRx, baseTierRy, 0, 0, Math.PI * 2); ctx.fill(); - const steelGrad = ctx.createLinearGradient(stageCx - topTierRx, 0, stageCx + topTierRx, 0); - steelGrad.addColorStop(0, '#27272A'); steelGrad.addColorStop(0.5, '#52525B'); steelGrad.addColorStop(1, '#18181B'); - ctx.fillStyle = steelGrad; - ctx.fillRect(stageCx - topTierRx - 20, topTierY, (topTierRx + 20) * 2, topTierH + 20); - const hazW = 20; - ctx.fillStyle = '#FACC15'; - for (let hx = stageCx - topTierRx - 20; hx < stageCx + topTierRx + 20; hx += hazW * 2) { - ctx.fillRect(hx, topTierY + topTierH - 5, hazW, 25); - } - ctx.fillStyle = '#3F3F46'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx + 20, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.strokeStyle = '#FACC15'; ctx.lineWidth = 4; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx + 20, topTierRy, 0, 0, Math.PI * 2); ctx.stroke(); - [-topTierRx, topTierRx].forEach(bx => { - ctx.fillStyle = '#E4E4E7'; - ctx.beginPath(); ctx.arc(stageCx + bx, topTierY, 6, 0, Math.PI * 2); ctx.fill(); - ctx.strokeStyle = '#000000'; ctx.lineWidth = 1.5; ctx.stroke(); - }); - ctx.restore(); - } else if (theme === 'editorial_vogue' || theme === 'nordic_minimal' || theme === 'swiss_modular_grid') { - // Minimalist Carrara Marble Monolithic Rectangular Block - ctx.save(); - ctx.fillStyle = 'rgba(0,0,0,0.85)'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + topTierH + 15, topTierRx * 1.1, 20, 0, 0, Math.PI * 2); ctx.fill(); - const blockW = topTierRx * 1.8; - const blockH = 45; - ctx.fillStyle = theme === 'editorial_vogue' || theme === 'swiss_modular_grid' ? '#292524' : '#E2E8F0'; - ctx.fillRect(stageCx - blockW / 2, topTierY, blockW, blockH); - ctx.fillStyle = theme === 'editorial_vogue' || theme === 'swiss_modular_grid' ? '#44403C' : '#F8FAFC'; - ctx.beginPath(); - ctx.moveTo(stageCx - blockW / 2, topTierY); - ctx.lineTo(stageCx - blockW / 2 + 30, topTierY - 20); - ctx.lineTo(stageCx + blockW / 2 + 30, topTierY - 20); - ctx.lineTo(stageCx + blockW / 2, topTierY); - ctx.closePath(); ctx.fill(); - ctx.strokeStyle = theme === 'editorial_vogue' || theme === 'swiss_modular_grid' ? '#A8A29E' : '#94A3B8'; - ctx.lineWidth = 1.5; - ctx.strokeRect(stageCx - blockW / 2, topTierY, blockW, blockH); - ctx.restore(); - } else if (theme === 'botanical_eco' || theme === 'kraft_artisan' || theme === 'polaroid_film_grid') { - // Natural Live-Edge Wooden Tree Trunk Slice with Moss - ctx.save(); - ctx.fillStyle = 'rgba(0,0,0,0.92)'; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + 25, topTierRx * 1.05, topTierRy * 1.2, 0, 0, Math.PI * 2); ctx.fill(); - const barkGrad = ctx.createLinearGradient(stageCx - topTierRx, 0, stageCx + topTierRx, 0); - barkGrad.addColorStop(0, '#271206'); barkGrad.addColorStop(0.5, '#451A03'); barkGrad.addColorStop(1, '#1A0B04'); - ctx.fillStyle = barkGrad; - ctx.fillRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + topTierH, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - const woodTop = ctx.createRadialGradient(stageCx, topTierY, 10, stageCx, topTierY, topTierRx); - woodTop.addColorStop(0, '#B45309'); woodTop.addColorStop(0.6, '#92400E'); woodTop.addColorStop(1, '#78350F'); - ctx.fillStyle = woodTop; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.strokeStyle = 'rgba(253, 230, 138, 0.15)'; ctx.lineWidth = 1.5; - [0.3, 0.6, 0.85].forEach(scale => { - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx * scale, topTierRy * scale, 0, 0, Math.PI * 2); ctx.stroke(); - }); - ctx.fillStyle = '#10B981'; - for (let mx = -topTierRx * 0.8; mx <= topTierRx * 0.8; mx += 14) { - ctx.beginPath(); ctx.arc(stageCx + mx, topTierY + Math.sin(mx * 0.2) * 4, 3.5, 0, Math.PI * 2); ctx.fill(); - } - ctx.restore(); - } else if (theme === 'cyber_neon' || theme === 'tokyo_synthwave' || theme === 'arcade_retro') { - // 3D Holographic Wireframe Floating Neon Energy Platform - ctx.save(); - ctx.strokeStyle = currentTheme.goldRim; ctx.lineWidth = 4; - ctx.shadowColor = currentTheme.goldRim; ctx.shadowBlur = 20; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + 10, topTierRx * 1.15, topTierRy * 1.15, 0, 0, Math.PI * 2); ctx.stroke(); - ctx.fillStyle = currentTheme.pedestalTop; - ctx.fillRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - ctx.strokeStyle = currentTheme.goldAccent; ctx.lineWidth = 1.5; - for (let px = stageCx - topTierRx; px <= stageCx + topTierRx; px += 35) { - ctx.beginPath(); ctx.moveTo(px, topTierY); ctx.lineTo(px, topTierY + topTierH); ctx.stroke(); - } - ctx.fillStyle = currentTheme.pedestalMid; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.stroke(); - ctx.restore(); } else { - // Luxury Fluted Multi-Tier Cylinder Podium - const shadowGrad = ctx.createRadialGradient(stageCx, baseTierY + 32, 20, stageCx, baseTierY + 32, baseTierRx * 1.15); - shadowGrad.addColorStop(0, 'rgba(0,0,0,0.95)'); shadowGrad.addColorStop(1, 'transparent'); - ctx.fillStyle = shadowGrad; - ctx.beginPath(); ctx.ellipse(stageCx, baseTierY + 32, baseTierRx * 1.15, baseTierRy * 1.5, 0, 0, Math.PI * 2); ctx.fill(); + // 3D Commercial Studio Radial Backdrop + const bgGrad = ctx.createRadialGradient(w / 2, tableTopY * 0.6, 40, w / 2, tableTopY * 0.6, w * 0.85); + bgGrad.addColorStop(0, currentTheme.bgCenter || '#1E293B'); + bgGrad.addColorStop(0.5, currentTheme.bgMid || '#0F172A'); + bgGrad.addColorStop(1, currentTheme.bgOuter || '#020617'); + ctx.fillStyle = bgGrad; + ctx.fillRect(0, 0, w, h); - const baseCylGrad = ctx.createLinearGradient(stageCx - baseTierRx, 0, stageCx + baseTierRx, 0); - baseCylGrad.addColorStop(0, currentTheme.pedestalDark); baseCylGrad.addColorStop(0.5, currentTheme.pedestalMid); baseCylGrad.addColorStop(1, currentTheme.pedestalDark); - ctx.fillStyle = baseCylGrad; - ctx.fillRect(stageCx - baseTierRx, baseTierY, baseTierRx * 2, baseTierH); - ctx.beginPath(); ctx.ellipse(stageCx, baseTierY + baseTierH, baseTierRx, baseTierRy, 0, 0, Math.PI * 2); ctx.fill(); - ctx.beginPath(); ctx.ellipse(stageCx, baseTierY, baseTierRx, baseTierRy, 0, 0, Math.PI * 2); ctx.fill(); + // Studio Spotlight Beam + ctx.save(); + ctx.globalCompositeOperation = 'screen'; + const beamGrad = ctx.createLinearGradient(w / 2, 0, w / 2, tableTopY + 60); + beamGrad.addColorStop(0, currentTheme.beamTop || 'rgba(255, 255, 255, 0.4)'); + beamGrad.addColorStop(0.4, currentTheme.beamMid || 'rgba(224, 231, 255, 0.2)'); + beamGrad.addColorStop(1, 'rgba(0, 0, 0, 0)'); + ctx.fillStyle = beamGrad; + ctx.beginPath(); + ctx.moveTo(w * 0.30, 0); ctx.lineTo(w * 0.70, 0); + ctx.lineTo(w * 0.90, tableTopY + 60); ctx.lineTo(w * 0.10, tableTopY + 60); + ctx.closePath(); ctx.fill(); + ctx.restore(); - const topCylGrad = ctx.createLinearGradient(stageCx - topTierRx, 0, stageCx + topTierRx, 0); - topCylGrad.addColorStop(0, currentTheme.cylStart); topCylGrad.addColorStop(0.2, currentTheme.goldRim); - topCylGrad.addColorStop(0.5, currentTheme.goldAccent); topCylGrad.addColorStop(0.8, currentTheme.goldRim); - topCylGrad.addColorStop(1, currentTheme.cylEnd); - ctx.fillStyle = topCylGrad; - ctx.fillRect(stageCx - topTierRx, topTierY, topTierRx * 2, topTierH); - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + topTierH, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); + // Stardust Sparkles + drawSparkleBokeh(ctx, w, tableTopY, currentTheme.goldRim || '#E5B83A'); - const topCapGrad = ctx.createRadialGradient(stageCx, topTierY, 0, stageCx, topTierY, topTierRx); - topCapGrad.addColorStop(0, currentTheme.pedestalTop); topCapGrad.addColorStop(0.6, currentTheme.pedestalMid); topCapGrad.addColorStop(1, currentTheme.pedestalDark); - ctx.fillStyle = topCapGrad; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.fill(); + // Studio Horizon & Table Surface + const stageGrad = ctx.createLinearGradient(0, tableTopY, 0, h); + stageGrad.addColorStop(0, currentTheme.pedestalTop || '#1E293B'); + stageGrad.addColorStop(0.4, currentTheme.pedestalMid || '#0F172A'); + stageGrad.addColorStop(1, currentTheme.pedestalDark || '#020617'); + ctx.fillStyle = stageGrad; + ctx.fillRect(0, tableTopY, w, tableH); - ctx.strokeStyle = currentTheme.goldRim; ctx.lineWidth = 3.5; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY, topTierRx, topTierRy, 0, 0, Math.PI * 2); ctx.stroke(); + // Sleek Podium Disc on Right + const podiumR = aspect === '9:16' ? w * 0.38 : w * 0.32; + ctx.save(); + ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; + ctx.beginPath(); + ctx.ellipse(pCenterX, groundY + 10, podiumR, podiumR * 0.28, 0, 0, Math.PI * 2); + ctx.fill(); + + ctx.fillStyle = currentTheme.pedestalTop || '#1E293B'; + ctx.beginPath(); + ctx.ellipse(pCenterX, groundY - 2, podiumR, podiumR * 0.26, 0, 0, Math.PI * 2); + ctx.fill(); + ctx.strokeStyle = currentTheme.goldRim || '#E5B83A'; + ctx.lineWidth = 2; + ctx.stroke(); + ctx.restore(); } - // 4. Product Scaling & Grounded 3D Render - if (productImg) { - const isBento = theme === 'bento_grid_luxe'; - const isSwiss = theme === 'swiss_modular_grid'; - const pSize = isBento || isSwiss ? (aspect === '9:16' ? 560 : 440) : (aspect === '9:16' ? 680 : 530); - const pLeft = stageCx - pSize / 2; - const pTop = topTierY - pSize + (aspect === '9:16' ? 25 : 18); + // 3. PRODUCT CUTOUT & MATTING / 3D CATEGORY MODEL FALLBACK + const pSize = aspect === '9:16' ? 700 : 540; + const pLeft = pCenterX - pSize / 2; + const pTop = groundY - pSize * 0.88; + + if (productImg && productImg.complete && productImg.naturalWidth > 0) { + // Contact Occlusion Shadow + renderRealisticContactShadow(ctx, pCenterX, groundY, pSize * 0.38, 22, 45); const pCan = document.createElement('canvas'); pCan.width = productImg.width || 600; @@ -4841,569 +3729,360 @@ async function render3DCommercialPoster(canvas, productImg, title, price, badgeT const pCtx = pCan.getContext('2d'); pCtx.drawImage(productImg, 0, 0, pCan.width, pCan.height); - pCtx.globalCompositeOperation = 'destination-in'; - const fadeGrad = pCtx.createRadialGradient( - pCan.width / 2, pCan.height * 0.48, pCan.width * 0.38, - pCan.width / 2, pCan.height * 0.48, pCan.width * 0.495 - ); - fadeGrad.addColorStop(0, 'rgba(0,0,0,1)'); - fadeGrad.addColorStop(0.88, 'rgba(0,0,0,1)'); - fadeGrad.addColorStop(1, 'rgba(0,0,0,0)'); - pCtx.fillStyle = fadeGrad; - pCtx.fillRect(0, 0, pCan.width, pCan.height); + try { + const imgData = pCtx.getImageData(0, 0, pCan.width, pCan.height); + const d = imgData.data; + const pw = pCan.width; + const ph = pCan.height; + const featherDist = 24; - ctx.save(); - const contactShadow = ctx.createRadialGradient(stageCx, topTierY + 2, 8, stageCx, topTierY + 2, topTierRx * 0.75); - contactShadow.addColorStop(0, 'rgba(0,0,0,0.88)'); - contactShadow.addColorStop(0.5, 'rgba(0,0,0,0.45)'); - contactShadow.addColorStop(1, 'transparent'); - ctx.fillStyle = contactShadow; - ctx.beginPath(); ctx.ellipse(stageCx, topTierY + 2, topTierRx * 0.75, topTierRy * 0.75, 0, 0, Math.PI * 2); ctx.fill(); - ctx.restore(); + let sampleR = 0, sampleG = 0, sampleB = 0, sampleCount = 0; + const cornerCoords = [ + [2, 2], [pw - 3, 2], [2, ph - 3], [pw - 3, ph - 3], + [Math.floor(pw / 2), 2], [2, Math.floor(ph / 2)], [pw - 3, Math.floor(ph / 2)] + ]; + cornerCoords.forEach(([cx, cy]) => { + const ci = (cy * pw + cx) * 4; + if (d[ci + 3] > 100) { + sampleR += d[ci]; sampleG += d[ci + 1]; sampleB += d[ci + 2]; + sampleCount++; + } + }); - ctx.save(); - ctx.globalCompositeOperation = 'source-over'; - ctx.shadowColor = 'rgba(0,0,0,0.6)'; - ctx.shadowBlur = 22; - ctx.shadowOffsetY = 10; - ctx.drawImage(pCan, pLeft, pTop, pSize, pSize); - ctx.restore(); - } + const hasBgSample = sampleCount > 0; + const bgR = hasBgSample ? sampleR / sampleCount : 255; + const bgG = hasBgSample ? sampleG / sampleCount : 255; + const bgB = hasBgSample ? sampleB / sampleCount : 255; + const bgBrightness = bgR * 0.299 + bgG * 0.587 + bgB * 0.114; - // 5. RADICALLY DISTINCT THEME HEADER ARCHITECTURES - if (theme === 'bento_grid_luxe') { - ctx.fillStyle = '#0F131C'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = 'rgba(56, 189, 248, 0.4)'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#F8FAFC'; - ctx.font = '900 30px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('🍱 BENTO KEYNOTE SPEC EDITION', w / 2, 50); - ctx.fillStyle = '#38BDF8'; - ctx.font = '700 13px Consolas, monospace'; - ctx.fillText('QUADRANT SPEC SHEET // 100% VERIFIED AUTHENTIC', w / 2, 80); - } else if (theme === 'swiss_modular_grid') { - ctx.fillStyle = '#0D0D10'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#FFFFFF'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '900 32px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('■ SWISS BAUHAUS MODULAR GRID', w / 2, 50); - ctx.fillStyle = '#F43F5E'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('PRECISION ARCHITECTURAL EDITION // 2026', w / 2, 80); - } else if (theme === 'blueprint_cad_grid') { - ctx.fillStyle = '#061727'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#38BDF8'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#38BDF8'; - ctx.font = '900 28px Consolas, monospace'; - ctx.textAlign = 'center'; - ctx.fillText('/// ARCHITECTURAL CAD SCHEMATIC ///', w / 2, 50); - ctx.fillStyle = '#BAE6FD'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('ENGINEERING SPEC_SHEET // SCALE 1:1 // PASS', w / 2, 80); - } else if (theme === 'polaroid_film_grid') { - ctx.fillStyle = '#100C0A'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#D97706'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#FDE68A'; - ctx.font = '900 28px Georgia, serif'; - ctx.textAlign = 'center'; - ctx.fillText('🎞️ 35mm FILMSTRIP CONTACT GRID 🎞️', w / 2, 50); - ctx.fillStyle = '#D97706'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('KODAK 400TX // PRO GALLERY SELECTION', w / 2, 80); - } else if (theme === 'cyber_hud_grid') { - ctx.fillStyle = '#050D1A'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#00FFCC'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#00FFCC'; - ctx.font = '900 28px Consolas, monospace'; - ctx.textAlign = 'center'; - ctx.fillText('[ TRON_HUD // TELEMETRY_GRID_V4 ]', w / 2, 50); - ctx.fillStyle = '#A7F3D0'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('ACTIVE SENSOR ARRAY // 100% QUANTUM SECURE', w / 2, 80); - } else if (theme === 'editorial_vogue') { - ctx.fillStyle = '#0F0E0D'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#E7E5E4'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '900 38px Playfair Display, Georgia, serif'; - ctx.textAlign = 'center'; - ctx.fillText('V O G U E E D I T I O N', w / 2, 52); - ctx.fillStyle = '#A8A29E'; - ctx.font = '700 13px Plus Jakarta Sans, sans-serif'; - ctx.letterSpacing = '3px'; - ctx.fillText('VOL. 26 // AUTUMN / WINTER HAUTE COUTURE', w / 2, 82); - } else if (theme === 'brutalist_street') { - ctx.fillStyle = '#18181B'; - ctx.fillRect(0, 0, w, 100); - ctx.fillStyle = '#FACC15'; - ctx.fillRect(0, 94, w, 6); - ctx.fillStyle = '#FACC15'; - ctx.font = '900 30px Impact, Arial Black, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('/// HEAVYWEIGHT TECHNICAL DIVISION ///', w / 2, 50); - ctx.fillStyle = '#E4E4E7'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('SPEC_OPS // 100% ORIGINAL // STREETWEAR', w / 2, 78); - } else if (theme === 'mughal_heritage') { - ctx.fillStyle = '#180B04'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#F59E0B'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#FDE68A'; - ctx.font = 'bold 32px Hind Siliguri, Playfair Display, serif'; - ctx.textAlign = 'center'; - ctx.fillText('⚜️ রাজকীয় ঐতিহ্য প্রিমিয়াম কালেকশন ⚜️', w / 2, 50); - ctx.fillStyle = '#FCD34D'; - ctx.font = '600 15px Hind Siliguri, sans-serif'; - ctx.fillText('হাতে বোনা আভিজাত্য • শতভাগ খাঁটি ও অরিজিনাল', w / 2, 80); - } else if (theme === 'cyber_neon') { - ctx.fillStyle = '#070E18'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#06B6D4'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#38BDF8'; - ctx.font = '900 28px Consolas, monospace'; - ctx.textAlign = 'center'; - ctx.fillText('[ PROTOCOL // CYBER_MATRIX_V3 ]', w / 2, 50); - ctx.fillStyle = '#22D3EE'; - ctx.font = 'bold 14px Consolas, monospace'; - ctx.fillText('STATUS: ONLINE • AUTHENTIC HARDWARE SECURED', w / 2, 78); - } else if (theme === 'tokyo_synthwave') { - ctx.fillStyle = '#100520'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#F43F5E'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#F43F5E'; - ctx.font = '900 32px Impact, Arial Black, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('/// TOKYO NIGHTS 1984 ///', w / 2, 52); - ctx.fillStyle = '#38BDF8'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('RETRO-WAVE SYNTH // LIMITED EDITION', w / 2, 80); - } else if (theme === 'vip_blackcard') { - ctx.fillStyle = '#0A0A0C'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#D4AF37'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#D4AF37'; - ctx.font = 'bold 30px Cinzel, Times New Roman, serif'; - ctx.textAlign = 'center'; - ctx.fillText('💳 CENTURION BLACK VIP 💳', w / 2, 50); - ctx.fillStyle = '#F3E5AB'; - ctx.font = '600 14px Plus Jakarta Sans, sans-serif'; - ctx.letterSpacing = '2px'; - ctx.fillText('EXCLUSIVELY FOR PRIVILEGED MEMBERS', w / 2, 80); - } else if (theme === 'botanical_eco') { - ctx.fillStyle = '#09140E'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#10B981'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#6EE7B7'; - ctx.font = 'bold 30px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('🌿 100% ORGANIC & BOTANICAL 🌿', w / 2, 50); - ctx.fillStyle = '#A7F3D0'; - ctx.font = '600 14px Plus Jakarta Sans, sans-serif'; - ctx.fillText('SUSTAINABLE HARVEST • PURE & NATURAL', w / 2, 80); - } else if (theme === 'art_deco_gilded') { - ctx.fillStyle = '#0E0B07'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#EAB308'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#FEF08A'; - ctx.font = 'bold 30px Cinzel, Playfair Display, serif'; - ctx.textAlign = 'center'; - ctx.fillText('✦ THE GILDED GATSBY COLLECTION ✦', w / 2, 50); - ctx.fillStyle = '#FDE047'; - ctx.font = '600 13px Plus Jakarta Sans, sans-serif'; - ctx.letterSpacing = '2px'; - ctx.fillText('1920s ART DECO MASTERPIECE', w / 2, 80); - } else if (theme === 'frost_titanium') { - ctx.fillStyle = '#0A131F'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#38BDF8'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#E0F2FE'; - ctx.font = 'bold 30px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('❄️ SUB-ZERO ARCTIC TITANIUM ❄️', w / 2, 50); - ctx.fillStyle = '#BAE6FD'; - ctx.font = '600 14px Plus Jakarta Sans, sans-serif'; - ctx.fillText('AEROSPACE GRADE METALLURGY', w / 2, 80); - } else if (theme === 'flash_sale_matrix') { - ctx.fillStyle = '#140404'; - ctx.fillRect(0, 0, w, 100); - ctx.fillStyle = '#EF4444'; ctx.fillRect(0, 94, w, 6); - ctx.fillStyle = '#FCA5A5'; - ctx.font = '900 32px Impact, Arial Black, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('⚡ MEGA FLASH SALE // LIMITED STOCK ⚡', w / 2, 50); - ctx.fillStyle = '#FECACA'; - ctx.font = 'bold 14px Plus Jakarta Sans, sans-serif'; - ctx.fillText('SPECIAL PROMOTIONAL CAMPAIGN', w / 2, 78); - } else if (theme === 'holographic_prism') { - ctx.fillStyle = '#0E0B1A'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#C084FC'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#F0ABFC'; - ctx.font = 'bold 30px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('✦ CHROMATIC PRISM 3D EDITION ✦', w / 2, 50); - ctx.fillStyle = '#E879F9'; - ctx.font = '600 14px Plus Jakarta Sans, sans-serif'; - ctx.fillText('IRIDESCENT SPECTRUM REFLECTION', w / 2, 80); - } else if (theme === 'cosmic_nebula') { - ctx.fillStyle = '#100624'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#C084FC'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#F3E8FF'; - ctx.font = 'bold 30px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText('🌌 DEEP SPACE ORBITAL EDITION 🌌', w / 2, 50); - ctx.fillStyle = '#D8B4FE'; - ctx.font = '600 14px Plus Jakarta Sans, sans-serif'; - ctx.fillText('CELESTIAL GRAVITY & STELLAR PRECISION', w / 2, 80); - } else if (theme === 'kraft_artisan') { - ctx.fillStyle = '#1A120B'; - ctx.fillRect(0, 0, w, 100); - ctx.strokeStyle = '#D97706'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 100); ctx.lineTo(w, 100); ctx.stroke(); - ctx.fillStyle = '#FDE68A'; - ctx.font = 'bold 30px Georgia, serif'; - ctx.textAlign = 'center'; - ctx.fillText('★ HANDCRAFTED ARTISAN QUALITY ★', w / 2, 50); - ctx.fillStyle = '#FCD34D'; - ctx.font = '600 14px Plus Jakarta Sans, sans-serif'; - ctx.fillText('GENUINE RECLAIMED WORKSHOP EDITION', w / 2, 80); - } else if (theme === 'arcade_retro') { - ctx.fillStyle = '#060B18'; - ctx.fillRect(0, 0, w, 100); - ctx.fillStyle = '#FACC15'; ctx.fillRect(0, 94, w, 6); - ctx.fillStyle = '#38BDF8'; - ctx.font = '900 28px Consolas, monospace'; - ctx.textAlign = 'center'; - ctx.fillText('🕹️ INSERT COIN // LEVEL UP 🕹️', w / 2, 50); - ctx.fillStyle = '#FACC15'; - ctx.font = 'bold 13px Consolas, monospace'; - ctx.fillText('PLAYER 1 READY • 100% RETRO WINNER', w / 2, 78); - } else { - ctx.fillStyle = '#090D14'; - ctx.fillRect(0, 0, w, 94); - ctx.strokeStyle = currentTheme.goldRim; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, 94); ctx.lineTo(w, 94); ctx.stroke(); - ctx.fillStyle = currentTheme.goldAccent; - ctx.font = '900 32px Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(brandInfo.headerTitle, w / 2, 48); - ctx.fillStyle = '#E2E8F0'; - ctx.font = '700 15px Plus Jakarta Sans, sans-serif'; - ctx.letterSpacing = '1.5px'; - ctx.fillText(brandInfo.headerSub, w / 2, 78); - } + for (let y = 0; y < ph; y++) { + for (let x = 0; x < pw; x++) { + const i = (y * pw + x) * 4; + if (d[i + 3] === 0) continue; - // 6. RADICALLY DISTINCT THEME BADGES - // (Skip standard floating badges for Bento & Blueprint grid as they have built-in grid cards) - if (theme !== 'bento_grid_luxe' && theme !== 'cyber_hud_grid') { - function drawBespokeBadge(bx, by, text, isLeft) { - ctx.save(); - ctx.font = 'bold ' + (aspect === '9:16' ? '20px' : '18px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.textAlign = 'left'; - const textW = ctx.measureText(text).width; - const padX = aspect === '9:16' ? 24 : 22; - const badgeH = aspect === '9:16' ? 50 : 46; - const badgeW = textW + padX * 2; - const startX = isLeft ? bx : bx - badgeW; + const r = d[i], g = d[i + 1], b = d[i + 2]; + const brightness = (r * 0.299 + g * 0.587 + b * 0.114); + const maxC = Math.max(r, g, b); + const minC = Math.min(r, g, b); - if (theme === 'brutalist_street') { - ctx.fillStyle = '#FACC15'; - ctx.fillRect(startX, by, badgeW, badgeH); - ctx.strokeStyle = '#000000'; ctx.lineWidth = 2.5; - ctx.strokeRect(startX, by, badgeW, badgeH); - ctx.fillStyle = '#000000'; - ctx.font = '900 ' + (aspect === '9:16' ? '19px' : '17px') + ' Impact, Consolas, monospace'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 32 : 29)); - } else if (theme === 'editorial_vogue' || theme === 'nordic_minimal' || theme === 'swiss_modular_grid') { - ctx.fillStyle = 'rgba(255, 255, 255, 0.96)'; - ctx.fillRect(startX, by, badgeW, badgeH); - ctx.strokeStyle = '#1C1917'; ctx.lineWidth = 1.5; - ctx.strokeRect(startX, by, badgeW, badgeH); - ctx.fillStyle = '#1C1917'; - ctx.font = 'bold ' + (aspect === '9:16' ? '18px' : '16px') + ' Plus Jakarta Sans, sans-serif'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 31 : 28)); - } else if (theme === 'blueprint_cad_grid') { - ctx.fillStyle = 'rgba(8, 47, 73, 0.90)'; - ctx.strokeStyle = '#38BDF8'; ctx.lineWidth = 2; - ctx.strokeRect(startX, by, badgeW, badgeH); - ctx.fillStyle = '#BAE6FD'; - ctx.font = 'bold ' + (aspect === '9:16' ? '17px' : '15px') + ' Consolas, monospace'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 32 : 29)); - } else if (theme === 'cyber_neon' || theme === 'tokyo_synthwave') { - ctx.fillStyle = 'rgba(8, 47, 73, 0.90)'; - ctx.strokeStyle = theme === 'tokyo_synthwave' ? '#F43F5E' : '#06B6D4'; ctx.lineWidth = 2; - ctx.shadowColor = theme === 'tokyo_synthwave' ? '#F43F5E' : '#06B6D4'; ctx.shadowBlur = 12; - ctx.beginPath(); ctx.roundRect(startX, by, badgeW, badgeH, 6); ctx.fill(); ctx.stroke(); - ctx.fillStyle = theme === 'tokyo_synthwave' ? '#FED7AA' : '#38BDF8'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 32 : 29)); - } else if (theme === 'botanical_eco') { - ctx.fillStyle = 'rgba(6, 78, 59, 0.92)'; - ctx.strokeStyle = '#10B981'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.roundRect(startX, by, badgeW, badgeH, badgeH / 2); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#D1FAE5'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 32 : 29)); - } else if (theme === 'flash_sale_matrix') { - ctx.fillStyle = '#EF4444'; - ctx.strokeStyle = '#FACC15'; ctx.lineWidth = 2.5; - ctx.beginPath(); ctx.roundRect(startX, by, badgeW, badgeH, 8); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 32 : 29)); - } else { - ctx.fillStyle = 'rgba(9, 13, 20, 0.92)'; - ctx.strokeStyle = currentTheme.goldRim; ctx.lineWidth = 2; - ctx.beginPath(); ctx.roundRect(startX, by, badgeW, badgeH, badgeH / 2); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.fillText(text, startX + padX, by + (aspect === '9:16' ? 32 : 29)); + if (brightness > 224 && (maxC - minC) < 28) { + if (brightness >= 242) { + d[i + 3] = 0; + } else { + const alphaFactor = (242 - brightness) / 18; + d[i + 3] = Math.round(d[i + 3] * Math.max(0, alphaFactor)); + } + } else if (bgBrightness < 50 && brightness < 45 && (maxC - minC) < 25) { + if (brightness <= 24) { + d[i + 3] = 0; + } else { + const alphaFactor = (brightness - 24) / 21; + d[i + 3] = Math.round(d[i + 3] * Math.max(0, alphaFactor)); + } + } else if (hasBgSample && !isDarkTheme) { + const colorDist = Math.sqrt( + Math.pow(r - bgR, 2) + Math.pow(g - bgG, 2) + Math.pow(b - bgB, 2) + ); + if (colorDist < 28) { + d[i + 3] = 0; + } else if (colorDist < 46) { + const alphaFactor = (colorDist - 28) / 18; + d[i + 3] = Math.round(d[i + 3] * alphaFactor); + } + } + + if (d[i + 3] > 0) { + const distLeft = x; const distRight = pw - 1 - x; + const distTop = y; const distBottom = ph - 1 - y; + const minDist = Math.min(distLeft, distRight, distTop, distBottom); + + if (minDist < featherDist) { + const edgeFade = Math.pow(minDist / featherDist, 1.2); + d[i + 3] = Math.round(d[i + 3] * edgeFade); + } + } + } } - ctx.restore(); + pCtx.putImageData(imgData, 0, 0); + } catch (e) { + pCtx.globalCompositeOperation = 'destination-in'; + const fadeGrad = pCtx.createRadialGradient( + pCan.width / 2, pCan.height * 0.48, pCan.width * 0.38, + pCan.width / 2, pCan.height * 0.48, pCan.width * 0.495 + ); + fadeGrad.addColorStop(0, 'rgba(0,0,0,1)'); + fadeGrad.addColorStop(0.90, 'rgba(0,0,0,1)'); + fadeGrad.addColorStop(1, 'rgba(0,0,0,0)'); + pCtx.fillStyle = fadeGrad; + pCtx.fillRect(0, 0, pCan.width, pCan.height); } - const bY1 = aspect === '9:16' ? 240 : 180; - const bY2 = aspect === '9:16' ? 310 : 245; - drawBespokeBadge(40, bY1, badgeText, true); - drawBespokeBadge(40, bY2, brandInfo.badgeL1, true); - drawBespokeBadge(w - 40, bY1, '⚡ Fast Delivery BD', false); - drawBespokeBadge(w - 40, bY2, brandInfo.badgeL2, false); - } + ctx.save(); + ctx.shadowColor = isDarkTheme ? 'rgba(0, 0, 0, 0.75)' : 'rgba(30, 15, 5, 0.35)'; + ctx.shadowBlur = 26; + ctx.shadowOffsetY = 14; + ctx.drawImage(pCan, pLeft, pTop, pSize, pSize); + ctx.restore(); - // 7. RADICALLY DISTINCT PRODUCT TITLE & PRICE CARDS - const bannerY = aspect === '9:16' ? 1320 : 770; - const bannerH = aspect === '9:16' ? 130 : 110; - const bannerMargin = 40; - const bannerW = w - bannerMargin * 2; - const cleanTitle = title.length > 55 ? title.substring(0, 52) + '...' : title; - - if (theme === 'bento_grid_luxe') { - ctx.fillStyle = 'rgba(15, 23, 42, 0.92)'; - ctx.strokeStyle = 'rgba(56, 189, 248, 0.45)'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.roundRect(bannerMargin, bannerY, bannerW, bannerH, 18); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '34px' : '28px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle, w / 2, bannerY + (aspect === '9:16' ? 52 : 44)); - ctx.fillStyle = '#38BDF8'; - ctx.font = '700 ' + (aspect === '9:16' ? '24px' : '21px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.fillText(`OFFER PRICE: ${price} • AUTHENTIC VERIFIED SPEC`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); - } else if (theme === 'blueprint_cad_grid') { - ctx.fillStyle = 'rgba(6, 23, 39, 0.96)'; - ctx.strokeStyle = '#38BDF8'; ctx.lineWidth = 2.5; - ctx.strokeRect(bannerMargin, bannerY, bannerW, bannerH); - ctx.fillStyle = '#E0F2FE'; - ctx.font = 'bold ' + (aspect === '9:16' ? '30px' : '26px') + ' Consolas, Hind Siliguri, monospace'; - ctx.textAlign = 'center'; - ctx.fillText(`[SPEC_MODEL]: ${cleanTitle.toUpperCase()}`, w / 2, bannerY + (aspect === '9:16' ? 52 : 44)); - ctx.fillStyle = '#38BDF8'; - ctx.font = 'bold ' + (aspect === '9:16' ? '22px' : '20px') + ' Consolas, monospace'; - ctx.fillText(`UNIT_VAL: ${price} // APPROVED PRODUCTION SPEC`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); - } else if (theme === 'brutalist_street') { - ctx.fillStyle = '#18181B'; - ctx.fillRect(bannerMargin, bannerY, bannerW, bannerH); - ctx.strokeStyle = '#FACC15'; ctx.lineWidth = 3; - ctx.strokeRect(bannerMargin, bannerY, bannerW, bannerH); - ctx.fillStyle = '#FFFFFF'; - ctx.font = '900 ' + (aspect === '9:16' ? '34px' : '28px') + ' Impact, Arial Black, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle.toUpperCase(), w / 2, bannerY + (aspect === '9:16' ? 52 : 44)); - ctx.fillStyle = '#FACC15'; - ctx.font = 'bold ' + (aspect === '9:16' ? '24px' : '22px') + ' Consolas, Hind Siliguri, monospace'; - ctx.fillText(`PRICE: ${price} /// 100% ORIGINAL STOCK`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); - } else if (theme === 'editorial_vogue' || theme === 'nordic_minimal' || theme === 'swiss_modular_grid') { - ctx.fillStyle = '#1C1917'; - ctx.fillRect(bannerMargin, bannerY, bannerW, bannerH); - ctx.strokeStyle = '#E7E5E4'; ctx.lineWidth = 1.5; - ctx.strokeRect(bannerMargin, bannerY, bannerW, bannerH); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '32px' : '28px') + ' Playfair Display, Georgia, serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle, w / 2, bannerY + (aspect === '9:16' ? 50 : 42)); - ctx.fillStyle = '#E7E5E4'; - ctx.font = '600 ' + (aspect === '9:16' ? '22px' : '20px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.fillText(`${price} • AUTHENTIC COUTURE SELECTION`, w / 2, bannerY + (aspect === '9:16' ? 96 : 84)); - } else if (theme === 'mughal_heritage') { - ctx.fillStyle = 'rgba(24, 11, 4, 0.96)'; - ctx.strokeStyle = '#F59E0B'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.roundRect(bannerMargin, bannerY, bannerW, bannerH, 16); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FDE68A'; - ctx.font = 'bold ' + (aspect === '9:16' ? '34px' : '28px') + ' Hind Siliguri, Playfair Display, serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle, w / 2, bannerY + (aspect === '9:16' ? 52 : 44)); - ctx.fillStyle = '#F59E0B'; - ctx.font = '700 ' + (aspect === '9:16' ? '24px' : '21px') + ' Hind Siliguri, sans-serif'; - ctx.fillText(`${price} • ১০০% খাঁটি গ্যারান্টি • দ্রুত হোম ডেলিভারি`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); - } else if (theme === 'cyber_neon' || theme === 'tokyo_synthwave' || theme === 'cyber_hud_grid') { - ctx.fillStyle = 'rgba(8, 47, 73, 0.94)'; - ctx.strokeStyle = theme === 'cyber_hud_grid' ? '#00FFCC' : (theme === 'tokyo_synthwave' ? '#F43F5E' : '#06B6D4'); ctx.lineWidth = 2.5; - ctx.shadowColor = theme === 'cyber_hud_grid' ? '#00FFCC' : (theme === 'tokyo_synthwave' ? '#F43F5E' : '#06B6D4'); ctx.shadowBlur = 10; - ctx.beginPath(); ctx.roundRect(bannerMargin, bannerY, bannerW, bannerH, 8); ctx.fill(); ctx.stroke(); - ctx.shadowBlur = 0; - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '32px' : '28px') + ' Consolas, Hind Siliguri, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle, w / 2, bannerY + (aspect === '9:16' ? 52 : 44)); - ctx.fillStyle = theme === 'cyber_hud_grid' ? '#00FFCC' : (theme === 'tokyo_synthwave' ? '#FED7AA' : '#38BDF8'); - ctx.font = 'bold ' + (aspect === '9:16' ? '24px' : '21px') + ' Consolas, sans-serif'; - ctx.fillText(`VAL: ${price} // VERIFIED AUTHENTIC // FAST_EXP`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); - } else if (theme === 'botanical_eco') { - ctx.fillStyle = 'rgba(6, 78, 59, 0.94)'; - ctx.strokeStyle = '#10B981'; ctx.lineWidth = 2.5; - ctx.beginPath(); ctx.roundRect(bannerMargin, bannerY, bannerW, bannerH, 18); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '34px' : '28px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle, w / 2, bannerY + (aspect === '9:16' ? 52 : 44)); - ctx.fillStyle = '#6EE7B7'; - ctx.font = '700 ' + (aspect === '9:16' ? '22px' : '20px') + ' Hind Siliguri, sans-serif'; - ctx.fillText(`${price} • ১০০% অর্গানিক ও ফ্রেশ • হোম ডেলিভারি`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); + if (nType === 'botanical_sun' || nType === 'kbeauty_travertine') { + renderWaterDewDroplets(ctx, pCenterX, groundY + 14, pSize * 0.32, 22); + } } else { - ctx.fillStyle = 'rgba(9, 13, 20, 0.94)'; - ctx.strokeStyle = currentTheme.goldRim; ctx.lineWidth = 2; - ctx.beginPath(); ctx.roundRect(bannerMargin, bannerY, bannerW, bannerH, 18); ctx.fill(); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '36px' : '30px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; - ctx.textAlign = 'center'; - ctx.fillText(cleanTitle, w / 2, bannerY + (aspect === '9:16' ? 54 : 45)); - ctx.fillStyle = currentTheme.goldAccent; - ctx.font = '700 ' + (aspect === '9:16' ? '22px' : '20px') + ' Hind Siliguri, sans-serif'; - ctx.fillText(`${price} • ১০০% আসল গ্যারান্টি • দ্রুত হোম ডেলিভারি`, w / 2, bannerY + (aspect === '9:16' ? 98 : 85)); + // Dynamic 3D Category Fallback + ctx.save(); + renderRealisticContactShadow(ctx, pCenterX, groundY, pSize * 0.38, 22, 45); + ctx.translate(pLeft, pTop); + const scaleF = pSize / 400; + ctx.scale(scaleF, scaleF); + if (brandInfo.category === 'panjabi') { + draw3DPanjabiMannequin(ctx, title); + } else if (brandInfo.category === 'snehalata') { + draw3DSareeMannequin(ctx, title); + } else if (brandInfo.category === 'techvolt') { + draw3DSmartwatch(ctx, title); + } else if (brandInfo.category === 'organic') { + draw3DHoneyJar(ctx, title); + } else if (brandInfo.category === 'sneakerlab') { + draw3DSneaker(ctx, title); + } else if (brandInfo.category === 'royale') { + draw3DPerfumeBottle(ctx, title); + } else { + draw3DCosmeticsSet(ctx, title); + } + ctx.restore(); } - // 8. RADICALLY DISTINCT THEME FOOTERS & HOTLINES - const footerHeight = aspect === '9:16' ? 110 : 100; + // 4. TOP EDITORIAL BRAND MASTHEAD (Always uses real store brand name!) + ctx.save(); + const brandName = (brandInfo.headerTitle || brandInfo.id || "GLAMOUR'S TOUCH") + .replace(/[^\w\s\u0980-\u09FF']/gi, '').trim().toUpperCase(); + + ctx.fillStyle = isDarkTheme ? (currentTheme.goldAccent || '#FDE68A') : '#2A1A0E'; + ctx.font = 'bold 20px Playfair Display, Hind Siliguri, serif'; + ctx.textAlign = 'left'; + ctx.fillText(`◈ ${brandName}`, 42, 45); + + let collectionTag = currentTheme.name ? `${currentTheme.name.toUpperCase()} // 8K COMMERCIAL STUDIO` : '8K COMMERCIAL STUDIO // 100% AUTHENTIC'; + if (isNatural) { + if (nType === 'botanical_sun') collectionTag = 'BOTANICAL MORNING SUN // 100% ORGANIC FORMULA'; + else if (nType === 'kbeauty_travertine') collectionTag = 'K-BEAUTY TRAVERTINE EDITORIAL // GLASS SKIN'; + else if (nType === 'warm_cafe') collectionTag = 'ARTISAN DARK WALNUT // COZY BOUTIQUE LIFESTYLE'; + else if (nType === 'sunlit_sand') collectionTag = 'SUN-KISSED TERRACOTTA // RAW MINERAL CRAFT'; + else if (nType === 'minimal_flatlay') collectionTag = 'STUDIO FLATLAY PRO // SCALE 1:1 AUTHENTIC'; + else if (nType === 'velvet_drape') collectionTag = 'ROYAL MULBERRY SILK // HAUTE COUTURE EDITION'; + else collectionTag = 'SCANDINAVIAN OAK STUDIO // 8K NATURAL LIFESTYLE'; + } + + ctx.fillStyle = isDarkTheme ? 'rgba(253, 230, 138, 0.75)' : (currentTheme.accentColor || '#785734'); + ctx.font = 'bold 11px Consolas, monospace'; + ctx.fillText(`EST. 2026 • ${collectionTag}`, 42, 68); + + ctx.strokeStyle = isDarkTheme ? (currentTheme.goldRim ? currentTheme.goldRim + '55' : 'rgba(245, 158, 11, 0.35)') : 'rgba(160, 125, 84, 0.35)'; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(42, 78); ctx.lineTo(w - 42, 78); + ctx.stroke(); + + // Top-Right Luxury Artisan Medallion Seal + const sealX = w - 80; + const sealY = 48; + ctx.strokeStyle = isDarkTheme ? (currentTheme.goldRim || '#FDE68A') : (currentTheme.goldRim || '#785734'); + ctx.lineWidth = 1.5; + ctx.beginPath(); ctx.arc(sealX, sealY, 26, 0, Math.PI * 2); ctx.stroke(); + ctx.beginPath(); ctx.arc(sealX, sealY, 22, 0, Math.PI * 2); ctx.stroke(); + + ctx.fillStyle = isDarkTheme ? (currentTheme.goldAccent || '#FDE68A') : (currentTheme.accentColor || '#785734'); + ctx.font = 'bold 8.5px Consolas, monospace'; + ctx.textAlign = 'center'; + ctx.fillText('8K PURE', sealX, sealY - 4); + ctx.fillText('STUDIO', sealX, sealY + 7); + ctx.restore(); + + // 5. EDITORIAL PRODUCT TITLE & STORYTELLING + const textLeft = 42; + const titleMaxWidth = aspect === '9:16' ? (w - 84) : (w * 0.44); + let curY = aspect === '9:16' ? 115 : 108; + + ctx.save(); + ctx.fillStyle = isDarkTheme ? (currentTheme.goldRim || '#F59E0B') : (currentTheme.accentColor || '#8C6D46'); + ctx.font = 'bold 11.5px Consolas, monospace'; + ctx.textAlign = 'left'; + ctx.fillText('◈ 01 // FEATURED COMMERCIAL SELECTION', textLeft, curY); + curY += 28; + + ctx.fillStyle = isDarkTheme ? '#FFFFFF' : '#181109'; + ctx.font = 'bold ' + (aspect === '9:16' ? '36px' : '30px') + ' Playfair Display, Hind Siliguri, serif'; + + const words = (title || 'Premium Authentic Product').split(' '); + let currentLine = ''; + const titleLines = []; + for (let i = 0; i < words.length; i++) { + const testLine = currentLine ? `${currentLine} ${words[i]}` : words[i]; + if (ctx.measureText(testLine).width > titleMaxWidth && i > 0) { + titleLines.push(currentLine); + currentLine = words[i]; + if (titleLines.length >= 3) { + currentLine += '...'; + break; + } + } else { + currentLine = testLine; + } + } + if (currentLine && titleLines.length < 3) titleLines.push(currentLine); + + titleLines.forEach(line => { + ctx.fillText(line, textLeft, curY); + curY += aspect === '9:16' ? 44 : 36; + }); + + // Formula Subtitle + curY += 4; + ctx.fillStyle = isDarkTheme ? 'rgba(255, 255, 255, 0.65)' : '#6B543E'; + ctx.font = 'italic ' + (aspect === '9:16' ? '16px' : '14px') + ' Playfair Display, Hind Siliguri, serif'; + ctx.fillText('Pure Formulation • Authentic Quality • Lab Tested', textLeft, curY); + curY += 28; + + // Price & Trust Badge Capsule + const priceW = ctx.measureText(price || '৳ ১,২৫০').width + 50; + const pillH = 34; + ctx.fillStyle = isDarkTheme ? (currentTheme.goldRim || '#F59E0B') : (currentTheme.accentColor || '#8C6D46'); + ctx.beginPath(); + ctx.roundRect(textLeft, curY, Math.max(120, priceW), pillH, 17); + ctx.fill(); + + ctx.fillStyle = isDarkTheme ? '#000000' : '#FFFFFF'; + ctx.font = '900 17px Plus Jakarta Sans, Hind Siliguri, sans-serif'; + ctx.fillText(price || '৳ ১,২৫০', textLeft + 16, curY + 23); + + if (badgeText) { + const badgeX = textLeft + Math.max(120, priceW) + 12; + ctx.fillStyle = isDarkTheme ? 'rgba(255, 255, 255, 0.12)' : 'rgba(140, 109, 70, 0.12)'; + ctx.strokeStyle = isDarkTheme ? (currentTheme.goldRim || '#F59E0B') : (currentTheme.accentColor || '#8C6D46'); + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.roundRect(badgeX, curY, 180, pillH, 17); + ctx.fill(); ctx.stroke(); + + ctx.fillStyle = isDarkTheme ? '#FFFFFF' : '#181109'; + ctx.font = 'bold 12.5px Hind Siliguri, sans-serif'; + ctx.fillText(badgeText, badgeX + 14, curY + 22); + } + curY += pillH + 26; + + // 3 Feature Cards (left column) + const cardW = aspect === '9:16' ? (w - 84) : (w * 0.44); + const cardH = 48; + const features = [ + { icon: '✨', title: '১০০% খাঁটি ও আসল', sub: '১০০% অথেনটিক পণ্য ও পরীক্ষিত গুণমান' }, + { icon: '🚚', title: 'হোম ডেলিভারি সুবিধা', sub: 'সারা বাংলাদেশে দ্রুত ক্যাশ অন ডেলিভারি' }, + { icon: '🛡️', title: 'মানি-ব্যাক গ্যারান্টি', sub: 'পণ্য হাতে পেয়ে দেখে নেওয়ার সুবিধা' } + ]; + + features.forEach((feat, idx) => { + ctx.fillStyle = isDarkTheme ? 'rgba(15, 23, 42, 0.65)' : 'rgba(255, 255, 255, 0.75)'; + ctx.strokeStyle = isDarkTheme ? 'rgba(255, 255, 255, 0.10)' : 'rgba(140, 109, 70, 0.20)'; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.roundRect(textLeft, curY, cardW, cardH, 10); + ctx.fill(); ctx.stroke(); + + ctx.fillStyle = isDarkTheme ? (currentTheme.goldAccent || '#FDE68A') : (currentTheme.accentColor || '#8C6D46'); + ctx.font = 'bold 16px sans-serif'; + ctx.fillText(feat.icon, textLeft + 12, curY + 31); + + ctx.fillStyle = isDarkTheme ? '#FFFFFF' : '#181109'; + ctx.font = 'bold 13px Hind Siliguri, sans-serif'; + ctx.fillText(feat.title, textLeft + 38, curY + 20); + + ctx.fillStyle = isDarkTheme ? 'rgba(255, 255, 255, 0.65)' : '#6B543E'; + ctx.font = '11px Hind Siliguri, sans-serif'; + ctx.fillText(feat.sub, textLeft + 38, curY + 38); + + curY += cardH + 10; + }); + ctx.restore(); + + // 6. BOTTOM VALUE PROPOSITION STRIP (on tabletop / lower surface) + const stripY = aspect === '9:16' ? (h - 220) : (tableTopY + tableH * 0.52); + const stripH = 64; + const colGap = 12; + const stripMargin = 35; + const totalStripW = w - stripMargin * 2; + const colW = (totalStripW - colGap * 2) / 3; + + const valueProps = [ + { icon: '✨', title: '১০০% খাঁটি ও আসল', desc: 'গ্যারান্টিযুক্ত প্রিমিয়াম মান' }, + { icon: '🛡️', title: 'মানি-ব্যাক গ্যারান্টি', desc: '৭ দিনের সহজ রিটার্ন পলিসি' }, + { icon: '🚚', title: 'ক্যাশ অন ডেলিভারি', desc: 'সারা বাংলাদেশে দ্রুত শিপিং' } + ]; + + ctx.save(); + valueProps.forEach((vp, i) => { + const colX = stripMargin + i * (colW + colGap); + ctx.fillStyle = isDarkTheme ? 'rgba(15, 23, 42, 0.78)' : 'rgba(255, 255, 255, 0.82)'; + ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.28)' : 'rgba(140, 109, 70, 0.28)'; + ctx.lineWidth = 1.2; + ctx.beginPath(); + ctx.roundRect(colX, stripY, colW, stripH, 12); + ctx.fill(); ctx.stroke(); + + ctx.fillStyle = isDarkTheme ? (currentTheme.goldAccent || '#FDE68A') : (currentTheme.accentColor || '#8C6D46'); + ctx.font = '18px sans-serif'; + ctx.textAlign = 'center'; + ctx.fillText(vp.icon, colX + 24, stripY + 38); + + ctx.fillStyle = isDarkTheme ? '#FFFFFF' : '#181109'; + ctx.font = 'bold 13px Hind Siliguri, sans-serif'; + ctx.textAlign = 'left'; + ctx.fillText(vp.title, colX + 44, stripY + 26); + + ctx.fillStyle = isDarkTheme ? 'rgba(255, 255, 255, 0.65)' : '#6B543E'; + ctx.font = '11px Hind Siliguri, sans-serif'; + ctx.fillText(vp.desc, colX + 44, stripY + 46); + }); + ctx.restore(); + + // 7. FROSTED GLASS FOOTER & ORDER HOTLINE + const footerHeight = aspect === '9:16' ? 110 : 96; const footerTop = h - footerHeight; - if (theme === 'bento_grid_luxe') { - ctx.fillStyle = '#0B0F17'; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.strokeStyle = 'rgba(56, 189, 248, 0.4)'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.moveTo(0, footerTop); ctx.lineTo(w, footerTop); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '32px' : '28px') + ' Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(`💬 WhatsApp Order: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#38BDF8'; - ctx.font = '600 ' + (aspect === '9:16' ? '18px' : '16px') + ' Consolas, monospace'; - ctx.fillText(`WEB: ${brandInfo.footerSite} • HOTLINE: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); - } else if (theme === 'blueprint_cad_grid') { - ctx.fillStyle = '#061727'; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.strokeStyle = '#38BDF8'; ctx.lineWidth = 2.5; - ctx.beginPath(); ctx.moveTo(0, footerTop); ctx.lineTo(w, footerTop); ctx.stroke(); - ctx.fillStyle = '#38BDF8'; - ctx.font = 'bold ' + (aspect === '9:16' ? '30px' : '26px') + ' Consolas, monospace'; - ctx.textAlign = 'left'; - ctx.fillText(`/// DISPATCH_HOTLINE: ${brandInfo.footerHotline} ///`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#BAE6FD'; - ctx.font = 'bold ' + (aspect === '9:16' ? '18px' : '16px') + ' Consolas, monospace'; - ctx.fillText(`SERVER_STORE: ${brandInfo.footerSite} // STATUS: VERIFIED_OK`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); - } else if (theme === 'brutalist_street') { - ctx.fillStyle = '#FACC15'; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.fillStyle = '#000000'; - ctx.font = '900 ' + (aspect === '9:16' ? '32px' : '30px') + ' Impact, Arial Black, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(`/// WHATSAPP ORDER: ${brandInfo.footerHotline} ///`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#18181B'; - ctx.font = 'bold ' + (aspect === '9:16' ? '18px' : '16px') + ' Consolas, monospace'; - ctx.fillText(`WEB: ${brandInfo.footerSite} // HOTLINE: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); - } else if (theme === 'editorial_vogue' || theme === 'nordic_minimal' || theme === 'swiss_modular_grid') { - ctx.fillStyle = '#0F0E0D'; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.strokeStyle = '#E7E5E4'; ctx.lineWidth = 2; - ctx.beginPath(); ctx.moveTo(0, footerTop); ctx.lineTo(w, footerTop); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '30px' : '28px') + ' Playfair Display, Georgia, serif'; - ctx.textAlign = 'left'; - ctx.fillText(`Private Concierge: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#A8A29E'; - ctx.font = '600 ' + (aspect === '9:16' ? '18px' : '16px') + ' Plus Jakarta Sans, sans-serif'; - ctx.fillText(`Official Boutique: ${brandInfo.footerSite} • Direct Hotline: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); - } else if (theme === 'mughal_heritage') { - const footGrad = ctx.createLinearGradient(0, footerTop, w, footerTop); - footGrad.addColorStop(0, '#78350F'); footGrad.addColorStop(1, '#451A03'); - ctx.fillStyle = footGrad; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.strokeStyle = '#F59E0B'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, footerTop); ctx.lineTo(w, footerTop); ctx.stroke(); - ctx.fillStyle = '#FDE68A'; - ctx.font = 'bold ' + (aspect === '9:16' ? '32px' : '28px') + ' Hind Siliguri, serif'; - ctx.textAlign = 'left'; - ctx.fillText(`💬 হোয়াটসঅ্যাপ অর্ডার: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#FEF3C7'; - ctx.font = '600 ' + (aspect === '9:16' ? '20px' : '17px') + ' Hind Siliguri, sans-serif'; - ctx.fillText(`🌐 ওয়েবসাইট: ${brandInfo.footerSite} • 📞 হটলাইন: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); - } else if (theme === 'botanical_eco') { - const footGrad = ctx.createLinearGradient(0, footerTop, w, footerTop); - footGrad.addColorStop(0, '#064E3B'); footGrad.addColorStop(1, '#022C22'); - ctx.fillStyle = footGrad; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.strokeStyle = '#10B981'; ctx.lineWidth = 3; - ctx.beginPath(); ctx.moveTo(0, footerTop); ctx.lineTo(w, footerTop); ctx.stroke(); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '34px' : '32px') + ' Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(`🌿 Botanical Order: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#A7F3D0'; - ctx.font = '600 ' + (aspect === '9:16' ? '21px' : '19px') + ' Plus Jakarta Sans, sans-serif'; - ctx.fillText(`🌐 Eco Store: ${brandInfo.footerSite} • 📞 Hotline: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); + ctx.save(); + const footGrad = ctx.createLinearGradient(0, footerTop, 0, h); + if (isDarkTheme) { + footGrad.addColorStop(0, 'rgba(15, 8, 4, 0.94)'); + footGrad.addColorStop(1, 'rgba(8, 4, 2, 0.98)'); } else { - const footGrad = ctx.createLinearGradient(0, footerTop, w, footerTop); - footGrad.addColorStop(0, '#10B981'); footGrad.addColorStop(1, '#059669'); - ctx.fillStyle = footGrad; - ctx.fillRect(0, footerTop, w, footerHeight); - ctx.fillStyle = '#FFFFFF'; - ctx.font = 'bold ' + (aspect === '9:16' ? '34px' : '32px') + ' Plus Jakarta Sans, sans-serif'; - ctx.textAlign = 'left'; - ctx.fillText(`💬 WhatsApp Order: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 48 : 44)); - ctx.fillStyle = '#DCFCE7'; - ctx.font = '600 ' + (aspect === '9:16' ? '21px' : '19px') + ' Plus Jakarta Sans, sans-serif'; - ctx.fillText(`🌐 Website: ${brandInfo.footerSite} • 📞 Hotline: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 86 : 78)); + footGrad.addColorStop(0, 'rgba(255, 255, 255, 0.88)'); + footGrad.addColorStop(1, 'rgba(247, 243, 235, 0.96)'); } + ctx.fillStyle = footGrad; + ctx.fillRect(0, footerTop, w, footerHeight); - // QR Code Icon on Footer - const qrS = aspect === '9:16' ? 86 : 80; + ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.50)' : 'rgba(160, 125, 84, 0.40)'; + ctx.lineWidth = 1.2; + ctx.beginPath(); ctx.moveTo(0, footerTop); ctx.lineTo(w, footerTop); ctx.stroke(); + + ctx.fillStyle = isDarkTheme ? '#10B981' : '#047857'; + ctx.font = 'bold ' + (aspect === '9:16' ? '28px' : '24px') + ' Plus Jakarta Sans, Hind Siliguri, sans-serif'; + ctx.textAlign = 'left'; + ctx.fillText(`💬 WhatsApp Order: ${brandInfo.footerHotline}`, 40, footerTop + (aspect === '9:16' ? 46 : 42)); + + ctx.fillStyle = isDarkTheme ? '#94A3B8' : '#64748B'; + ctx.font = '600 ' + (aspect === '9:16' ? '17px' : '14px') + ' Plus Jakarta Sans, sans-serif'; + ctx.fillText(`🌐 ${brandInfo.footerSite} • 📞 ${brandInfo.footerHotline} • 🚚 Cash on Delivery BD`, 40, footerTop + (aspect === '9:16' ? 84 : 76)); + + // Authentic 3-Finder QR Code Matrix + const qrS = aspect === '9:16' ? 82 : 72; const qrX = w - qrS - 40; const qrY = footerTop + (footerHeight - qrS) / 2; - - ctx.fillStyle = '#FFFFFF'; - ctx.fillRect(qrX, qrY, qrS, qrS); - ctx.fillStyle = '#000000'; - ctx.fillRect(qrX + 6, qrY + 6, 24, 24); - ctx.fillStyle = '#FFFFFF'; - ctx.fillRect(qrX + 10, qrY + 10, 16, 16); - ctx.fillStyle = '#000000'; - ctx.fillRect(qrX + 13, qrY + 13, 10, 10); - ctx.fillRect(qrX + qrS - 30, qrY + 6, 24, 24); - ctx.fillStyle = '#FFFFFF'; - ctx.fillRect(qrX + qrS - 26, qrY + 10, 16, 16); - ctx.fillStyle = '#000000'; - ctx.fillRect(qrX + qrS - 23, qrY + 13, 10, 10); + drawQRCodeTile(ctx, qrX, qrY, qrS); // Outer Border Rim - ctx.strokeStyle = currentTheme.goldRim + '99'; - ctx.lineWidth = 6; - ctx.strokeRect(3, 3, w - 6, h - 6); + ctx.strokeStyle = isDarkTheme ? 'rgba(245, 158, 11, 0.45)' : 'rgba(160, 125, 84, 0.35)'; + ctx.lineWidth = 2.5; + ctx.strokeRect(2, 2, w - 4, h - 4); + ctx.restore(); } window.render3DCommercialPoster = render3DCommercialPoster; @@ -5412,6 +4091,11 @@ window.render3DCommercialPoster = render3DCommercialPoster; // 🔲 Multi-Product Grid Commercial Poster Rendering Engine (3-4 Products) // ========================================================================= async function renderMultiProductGridPoster(canvas, products, gridLayout = '2x2_quad', mainHeadline = '✨ 4-IN-1 MEGA COMBO ROUTINE', theme = 'obsidian_gold', aspect = '1:1', brand = 'glamourstouch', customOverrides = null) { + if (!canvas.width || canvas.width <= 300) { + if (aspect === '9:16') { canvas.width = 1080; canvas.height = 1920; } + else if (aspect === '4:5') { canvas.width = 1080; canvas.height = 1350; } + else { canvas.width = 1080; canvas.height = 1080; } + } const ctx = canvas.getContext('2d'); const w = canvas.width; const h = canvas.height;