eubottura commited on
Commit
58d2e3c
·
verified ·
1 Parent(s): 66039ae

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +224 -234
index.html CHANGED
@@ -4,10 +4,10 @@
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>AI Prompt Generator | Variable Injection Specialist</title>
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
11
  <style>
12
  :root {
13
  --bg-body: #0f172a;
@@ -18,6 +18,7 @@
18
  --primary: #3b82f6;
19
  --primary-hover: #2563eb;
20
  --accent: #10b981;
 
21
  --border: #334155;
22
  --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
23
  --radius: 12px;
@@ -59,6 +60,9 @@
59
  -webkit-background-clip: text;
60
  -webkit-text-fill-color: transparent;
61
  letter-spacing: -0.025em;
 
 
 
62
  }
63
 
64
  .anycoder-link {
@@ -79,12 +83,12 @@
79
  /* Main Layout */
80
  main {
81
  flex: 1;
82
- max-width: 1400px;
83
  margin: 0 auto;
84
  width: 100%;
85
  padding: 2rem;
86
  display: grid;
87
- grid-template-columns: 350px 1fr;
88
  gap: 2rem;
89
  }
90
 
@@ -137,7 +141,7 @@
137
 
138
  textarea {
139
  resize: vertical;
140
- min-height: 100px;
141
  }
142
 
143
  input:focus,
@@ -186,6 +190,9 @@
186
  display: flex;
187
  justify-content: space-between;
188
  align-items: center;
 
 
 
189
  }
190
 
191
  .status-badge {
@@ -198,7 +205,7 @@
198
 
199
  .grid {
200
  display: grid;
201
- grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
202
  gap: 1.5rem;
203
  }
204
 
@@ -206,7 +213,7 @@
206
  background-color: var(--bg-card);
207
  border: 1px solid var(--border);
208
  border-radius: var(--radius);
209
- padding: 1.5rem;
210
  display: flex;
211
  flex-direction: column;
212
  transition: transform 0.2s, box-shadow 0.2s;
@@ -223,36 +230,51 @@
223
  .card-header {
224
  display: flex;
225
  justify-content: space-between;
226
- align-items: flex-start;
227
- margin-bottom: 1rem;
 
 
228
  }
229
 
230
  .card-title {
231
- font-size: 0.9rem;
232
  font-weight: 700;
233
  color: var(--primary);
234
  text-transform: uppercase;
235
  letter-spacing: 0.05em;
 
 
 
 
 
 
 
 
 
 
 
 
236
  }
237
 
238
  .card-content {
239
- background-color: rgba(0, 0, 0, 0.2);
240
- padding: 1rem;
241
- border-radius: 8px;
242
- font-family: 'Courier New', Courier, monospace;
243
  font-size: 0.85rem;
244
  color: #e2e8f0;
245
  white-space: pre-wrap;
246
  word-break: break-word;
247
- max-height: 300px;
248
  overflow-y: auto;
249
- border: 1px solid rgba(255, 255, 255, 0.05);
 
250
  }
251
 
252
  .card-actions {
253
- margin-top: 1rem;
 
254
  display: flex;
255
  justify-content: flex-end;
 
256
  }
257
 
258
  .btn-copy {
@@ -278,7 +300,7 @@
278
  /* Empty State */
279
  .empty-state {
280
  text-align: center;
281
- padding: 4rem 2rem;
282
  color: var(--text-muted);
283
  border: 2px dashed var(--border);
284
  border-radius: var(--radius);
@@ -316,6 +338,7 @@
316
  opacity: 0;
317
  transform: translateY(10px);
318
  }
 
319
  to {
320
  opacity: 1;
321
  transform: translateY(0);
@@ -347,13 +370,31 @@
347
  padding: 1rem;
348
  }
349
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
350
  </style>
351
  </head>
352
 
353
  <body>
354
 
355
  <header>
356
- <div class="brand">PromptGen AI</div>
 
 
 
357
  <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with
358
  anycoder</a>
359
  </header>
@@ -371,15 +412,15 @@
371
  </h2>
372
 
373
  <div class="form-group">
374
- <label for="productName">Nome do Produto</label>
375
- <textarea id="productName" placeholder="e.g. Bermuda Viena Feminina em Algodão com Brinde"></textarea>
376
- <p class="helper-text">Inclua material, gênero e dicas de quantidade.</p>
377
  </div>
378
 
379
  <div class="form-group">
380
- <label for="colorList">Lista de Cores</label>
381
- <input type="text" id="colorList" placeholder="e.g. Green, Khaki, Beige, White">
382
- <p class="helper-text">Separe as cores com vírgulas.</p>
383
  </div>
384
 
385
  <button class="btn-primary" id="generateBtn">Gerar Prompts</button>
@@ -388,7 +429,7 @@
388
  <!-- Output Section -->
389
  <section class="output-container">
390
  <div class="results-header">
391
- <h2>Templates Gerados</h2>
392
  <span class="status-badge" id="statusBadge">Aguardando entrada...</span>
393
  </div>
394
 
@@ -406,41 +447,60 @@
406
 
407
  <script>
408
  // --- Constants & Templates ---
 
409
  const TEMPLATES = [
410
  {
 
411
  title: "DETALHE DO PRODUTO",
 
412
  content: `STRICT VISUAL MATCH TAKEN WITH IPHONE. 1:1 Square format. The subject is the EXACT "Bermuda Viena Feminina" in Linen and Cotton. The design must be IDENTICAL to the reference: high-waisted structure with precise vertical front seams (nervuras). A feminine hand is gently pinching the fabric on the front seam to display the exact ribbing detail and texture. Extreme close-up focus on the material weave and seam construction. Natural sunlight, casual Brazilian atmosphere, amateur raw photo style, beige color. DO NOT ALTER THE SILHOUETTE OR DETAILS. --ar 1:1 --style raw --v 6.0`
413
  },
414
  {
 
415
  title: "DETALHE DO PRODUTO 2",
 
416
  content: `Commercial macro photography, extreme close-up focus on fabric texture, women's high-waisted bermuda shorts made of premium linen and cotton blend, detailed visible front ribs/nervuras, natural beige color, soft diffused studio lighting to enhance fabric grain, tactile surface quality, shallow depth of field with bokeh neutral background, ultra-realistic, 8k resolution, shot on Sony A7R IV, 100mm macro lens, cinematic style, luxury e-commerce aesthetic, visible fiber details, no text, no watermark. --ar 4:5 --style raw --v 6.0`
417
  },
418
  {
 
419
  title: "PESSOA USANDO",
 
420
  content: `Square 1:1 photo taken on an iPhone, candid street photography style. A female model stands on a bright Brazilian street, neck down, wearing shorts that are an exact visual match to the reference image: High-waisted 'Bermuda Viena' made of Linen and Cotton. Key details: Prominent vertical front seams/ribs (nervuras frontais), structured high waist, and a textured natural fabric weave that looks like linen. The shorts fit is relaxed but tailored. The color is natural beige. The lighting is harsh natural sunlight typical of Brazil, emphasizing the fabric texture. Background is a blurred concrete wall or sidewalk. The shot is raw and unposed, focused on capturing the precise cut and design of the product.`
421
  },
422
  {
 
423
  title: "PESSOA USANDO 2",
 
424
  content: `A raw, candid square photo taken on an iPhone 15 Pro Max. STRICT VISUAL REPLICATION REQUIRED. The subject is wearing the EXACT 'Bermuda Viena Feminina' shorts. MUST FEATURE: High-waisted cut, distinctive vertical front ribs/nervuras seams running down the front, straight leg silhouette made of premium linen and cotton blend. The fabric texture is clearly visible, highlighting the natural earthy beige color and coarse weave. DO NOT ALTER THE DESIGN OR SILHOUETTE. Setting: Vibrant Brazilian urban street, textured white concrete wall, Portuguese stone sidewalk, intense midday sun casting sharp natural shadows. The vibe is effortless, tropical, and relaxed 'bem básico' style. High definition, authentic iPhone camera aesthetic, unposed, street photography style. --ar 1:1 --style raw --v 6.0`
425
  },
426
  {
 
427
  title: "AVALIAÇÃO ESPELHO",
 
428
  content: `Authentic Shopee-style customer review photo, raw vertical mirror selfie, 9:18 aspect ratio. A female model is standing in front of a bathroom mirror, framed from the neck up (no face visible, hiding face). She is wearing the EXACT "Bermuda Viena" high-waisted shorts. STRICT VISUAL FIDELITY: The shorts must feature the specific vertical front ribs/nervuras seams, linen and cotton fabric texture, beige color. The setting is a typical Brazilian home bathroom with natural ambient light. The image must look like a real amateur photo taken by a customer, realistic phone camera grain, showing the fit of the high waist and the straight leg cut. Candid, unposed, honest product demonstration. --ar 9:16 --style raw --v 6.0`
429
  },
430
  {
 
431
  title: "AVALIAÇÃO CAMA",
 
432
  content: `Authentic Brazilian Shopee customer review photo, raw vertical mobile shot, 9:16 aspect ratio. THE SCENE: A messy, unorganized pile of exactly 5 pairs of 'Bermuda Viena' shorts thrown casually across a bedroom bed. The shorts are fully unfolded and lying in a heap. COLOR CRITICAL: The pile must display the specific 5 colors from the product listing: Green, Khaki, White, Black, and Bege. STICT FIDELITY: Exact 'Bermuda Viena' model, high-waisted, vertical front ribs/nervuras, linen texture. LOGO: Brand tag visible. VIBE: Honest amateur photo, natural daylight, typical home setting, showing the variety of the purchase. --ar 9:16 --style raw --v 6.0`
433
  },
434
  {
 
435
  title: "FOTO PRINCIPAL",
 
436
  content: `Professional 1:1 square e-commerce product photograph featuring a charismatic, confident Brazilian woman standing behind a horizontal clothing rail. She has a warm, sun-kissed Brazilian complexion, natural hair texture, and distinctively Brazilian facial features. Her expression is authentic, engaging, and confident, with realistic human skin texture to avoid an artificial look. The rail displays exactly 5 identical pairs of "Bermuda Viena Feminina" shorts hanging perfectly flat, straight side-by-side, and FULLY UNCROPPED. STRICT DESIGN SPECIFICATIONS: The shorts must be exact replicas: high-waisted structure, distinctive vertical front ribs/nervuras seams, premium linen and cotton blend texture, straight leg cut. LOGO: A visible brand logo is present on the waistband or label of the shorts. COLOR PALETTE: Verde (Green), Cáqui (Khaki), Branco (White), Preto (Black), Beige. COMPOSITION: Hands gripping the rail, clear full view of all 5 shorts in the foreground without obstruction. BACKGROUND: Minimalist white studio backdrop, soft uniform lighting. Hyper-realistic texture focus, commercial catalog quality. --ar 1:1 --v 6.0 --style raw`
437
  },
438
  {
 
439
  title: "TEXTO FOTO PRINCIPAL",
 
440
  content: `Ensure the promotional text "Pague 3, Leve 5". Preserve exact original image position. Maintain flat lighting, no visible JPEG artifacts, Ultra-realistic, 8k resolution, photographic clarity, sharp focus, high fidelity textures, crisp details. Simple composition, use of symmetry, shallow depth of field, background blurred, leading lines created by clothes rack, no other objects, minimalist style. Add bold, sharp graphic text overlays seamlessly integrated without altering the photography subject.`
441
  },
442
  {
 
443
  title: "SOMENTE O PRODUTO (PNG)",
 
444
  content: `Professional product photography of exactly 5 identical copies of the source image product arranged in a tight horizontal row. COLOR PALETTE EXACT: The five shorts must display the following distinct colors: Green (Verde), Khaki (Cáki), White (Branco), Black (Preto), and Beige. The shorts are suspended in mid-air as if on invisible hangers, maintaining a stiff, perfectly straight structured shape. The legs are pressing tightly against each other with zero space or gaps between the items. NO HARDWARE: Absolutely no visible hangers, hooks, or strings, only the shorts floating. CRITICAL: The texture, fabric, stitching nervuras, and logo must be an exact duplication of the reference image provided. Product photography, pure white background, studio light. --ar 5:1 --style raw --iw 3`
445
  }
446
  ];
@@ -448,24 +508,52 @@
448
  // --- Logic Functions ---
449
 
450
  /**
451
- * Step 1: Analyze Input 1 (INPUT_PRODUCT_NAME)
452
  */
453
- function analyzeProductName(input) {
454
  // 1. PRODUCT_NAME: Clean input
455
- const productName = input.trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
456
 
457
- // 2. MATERIAL: Identify keywords and translate
458
  const materialMap = {
459
  'algodão': 'Cotton',
 
460
  'linho': 'Linen',
461
  'poliéster': 'Polyester',
 
462
  'seda': 'Silk',
463
  'jeans': 'Denim',
464
- 'denim': 'Denim'
 
465
  };
466
 
467
- let material = 'Cotton'; // Default fallback or original if not found
468
- const lowerInput = input.toLowerCase();
469
 
470
  for (const [key, value] of Object.entries(materialMap)) {
471
  if (lowerInput.includes(key)) {
@@ -476,232 +564,134 @@
476
 
477
  // 3. TARGET_AUDIENCE
478
  let gender = 'Female'; // Default
479
- if (/masculina|masculino|homem|menino/i.test(input)) {
480
  gender = 'Male';
481
  }
482
 
483
- // 4. GIVEAWAYS
484
- const hasGiveaways = /brinde|bônus|presente|kit/i.test(input);
485
 
486
- // 5. TOTAL_QUANTITY
487
- let quantity = 0;
488
- const explicitNumberMatch = input.match(/(?:pack|pack de|conjunto|kit)?\s*(\d+)\s*(?:unidades|pares|pcs|units)?/i);
489
-
490
- if (explicitNumberMatch) {
491
- quantity = parseInt(explicitNumberMatch[1], 10);
492
  }
493
 
494
- // Extract "Pay X Take Y" text for the overlay
495
- const promoMatch = input.match(/pague\s*\d+\s*leve\s*\d+/i);
496
- const promoText = promoMatch ? promoMatch[0] : null;
497
-
498
- return {
499
- productName,
500
- material,
501
- gender,
502
- hasGiveaways,
503
- quantity,
504
- promoText
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  };
506
- }
507
 
508
- /**
509
- * Step 2: Analyze Input 2 (INPUT_COLORS)
510
- */
511
- function analyzeColors(input) {
512
- if (!input) return { list: [], first: '', formattedList: '' };
513
 
514
- const colors = input.split(',').map(c => c.trim()).filter(c => c.length > 0);
 
 
 
515
 
516
- // Format list: "Green, Khaki, White, Black, and Bege"
517
- let formattedList = '';
518
- if (colors.length === 1) {
519
- formattedList = colors[0];
520
- } else if (colors.length === 2) {
521
- formattedList = `${colors[0]} and ${colors[1]}`;
 
 
522
  } else {
523
- const last = colors[colors.length - 1];
524
- const rest = colors.slice(0, -1).join(', ');
525
- formattedList = `${rest}, and ${last}`;
526
  }
527
 
528
  return {
529
- list: colors,
530
- first: colors[0] || '',
531
- formattedList
 
 
 
 
 
 
 
532
  };
533
  }
534
 
535
  /**
536
- * Step 3: Substitution Execution & Step 4: Output Generation
537
  */
538
- function generatePrompts(productData, colorData) {
539
- // Determine final quantity
540
- let totalQuantity = productData.quantity;
541
- if (totalQuantity === 0) {
542
- totalQuantity = colorData.list.length > 0 ? colorData.list.length : 1;
543
- }
544
 
545
- // Quantity string replacements
546
- const quantityString = totalQuantity.toString();
547
- const pluralPairs = `${totalQuantity} pairs`;
548
- const pluralCopies = `${totalQuantity} identical copies`;
549
-
550
- const results = TEMPLATES.map(template => {
551
  let text = template.content;
552
 
553
- // 1. Replace Product Name
554
- text = text.replace(/Bermuda Viena Feminina/g, productData.productName);
555
- text = text.replace(/'Bermuda Viena'/g, `'${productData.productName}'`);
556
- text = text.replace(/Bermuda Viena/g, productData.productName);
557
-
558
- // 2. Replace Material
559
- const matRegex = /linen and cotton/gi;
560
- text = text.replace(matRegex, productData.material);
561
-
562
- const blendRegex = /linen and cotton blend/gi;
563
- text = text.replace(blendRegex, `${productData.material} blend`);
564
-
565
- // 3. Replace Color List
566
- text = text.replace(/Green, Khaki, White, Black, and Bege/g, colorData.formattedList);
567
-
568
- // 4. Replace Singular Color
569
- text = text.replace(/\bbeige\b/g, colorData.first);
570
-
571
- // 5. Replace Quantity References
572
- text = text.replace(/5 pairs/g, pluralPairs);
573
- text = text.replace(/5 identical copies/g, pluralCopies);
574
-
575
- if (template.title === "TEXTO FOTO PRINCIPAL") {
576
- if (productData.promoText) {
577
- text = text.replace(/"Pague 3, Leve 5"/g, `"${productData.promoText}"`);
578
- text = text.replace(/Pague 3, Leve 5/g, productData.promoText);
579
- } else {
580
- text = text.replace(/Leve 5/g, `Leve ${quantityString}`);
581
- }
582
  } else {
583
- text = text.replace(/Leve 5/g, `Leve ${quantityString}`);
584
- }
585
-
586
- text = text.replace(/exactly 5 pairs/g, `exactly ${pluralPairs}`);
587
- text = text.replace(/exactly 5 identical/g, `exactly ${totalQuantity} identical`);
588
-
589
- // 6. Gender Adaptation
590
- if (productData.gender === 'Male') {
591
- text = text.replace(/female model/g, 'male model');
592
- text = text.replace(/women's/g, "men's");
593
- text = text.replace(/\bwomen\b/g, 'men');
594
- text = text.replace(/\bwoman\b/g, 'man');
595
- text = text.replace(/feminine hand/g, 'masculine hand');
596
- text = text.replace(/Brazilian woman/g, 'Brazilian man');
597
- text = text.replace(/A female model/g, 'A male model');
598
  }
599
 
600
- return {
601
- title: template.title,
602
- content: text
603
- };
604
- });
605
-
606
- return results;
607
- }
608
-
609
- // --- UI Interactions ---
610
-
611
- const generateBtn = document.getElementById('generateBtn');
612
- const productNameInput = document.getElementById('productName');
613
- const colorListInput = document.getElementById('colorList');
614
- const resultsGrid = document.getElementById('resultsGrid');
615
- const statusBadge = document.getElementById('statusBadge');
616
- const toast = document.getElementById('toast');
617
-
618
- function showToast(message) {
619
- toast.textContent = message;
620
- toast.classList.add('show');
621
- setTimeout(() => {
622
- toast.classList.remove('show');
623
- }, 3000);
624
- }
625
 
626
- function copyToClipboard(text) {
627
- navigator.clipboard.writeText(text).then(() => {
628
- showToast('Copiado para a área de transferência!');
629
- }).catch(err => {
630
- showToast('Falha ao copiar');
631
- });
632
- }
633
-
634
- function renderResults(results) {
635
- resultsGrid.innerHTML = '';
636
-
637
- if (results.length === 0) {
638
- resultsGrid.innerHTML = `<div class="empty-state" style="grid-column: 1 / -1;"><p>Nenhum resultado gerado.</p></div>`;
639
- return;
640
- }
641
-
642
- results.forEach((item, index) => {
643
- const card = document.createElement('div');
644
- card.className = 'card';
645
- card.style.animation = `fadeIn 0.5s ease forwards ${index * 0.1}s`;
646
- card.style.opacity = '0'; // For animation
647
-
648
- const header = document.createElement('div');
649
- header.className = 'card-header';
650
-
651
- const title = document.createElement('div');
652
- title.className = 'card-title';
653
- title.textContent = item.title;
654
-
655
- header.appendChild(title);
656
-
657
- const content = document.createElement('div');
658
- content.className = 'card-content';
659
- content.textContent = item.content;
660
-
661
- const actions = document.createElement('div');
662
- actions.className = 'card-actions';
663
-
664
- const copyBtn = document.createElement('button');
665
- copyBtn.className = 'btn-copy';
666
- copyBtn.innerHTML = `
667
- <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
668
- Copiar
669
- `;
670
- copyBtn.onclick = () => copyToClipboard(item.content);
671
-
672
- actions.appendChild(copyBtn);
673
- card.appendChild(header);
674
- card.appendChild(content);
675
- card.appendChild(actions);
676
-
677
- resultsGrid.appendChild(card);
678
- });
679
- }
680
-
681
- generateBtn.addEventListener('click', () => {
682
- const pName = productNameInput.value;
683
- const cList = colorListInput.value;
684
-
685
- if (!pName || !cList) {
686
- showToast('Por favor, preencha ambos os campos.');
687
- return;
688
- }
689
-
690
- // 1. Analyze Data
691
- const pData = analyzeProductName(pName);
692
- const cData = analyzeColors(cList);
693
-
694
- // 2. Generate Prompts
695
- const results = generatePrompts(pData, cData);
696
 
697
- // 3. Render Results
698
- renderResults(results);
 
 
 
 
 
 
 
 
 
 
 
699
 
700
- // 4. Update Status Badge
701
- statusBadge.textContent = `${results.length} prompts gerados`;
702
- statusBadge.style.color = 'var(--accent)';
703
- statusBadge.style.backgroundColor = 'rgba(16, 185, 129, 0.1)';
704
- });
705
- </script>
706
- </body>
707
- </html>
 
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>AI Prompt Gen | E-Commerce Specialist</title>
8
  <link rel="preconnect" href="https://fonts.googleapis.com">
9
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11
  <style>
12
  :root {
13
  --bg-body: #0f172a;
 
18
  --primary: #3b82f6;
19
  --primary-hover: #2563eb;
20
  --accent: #10b981;
21
+ --danger: #ef4444;
22
  --border: #334155;
23
  --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
24
  --radius: 12px;
 
60
  -webkit-background-clip: text;
61
  -webkit-text-fill-color: transparent;
62
  letter-spacing: -0.025em;
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 0.5rem;
66
  }
67
 
68
  .anycoder-link {
 
83
  /* Main Layout */
84
  main {
85
  flex: 1;
86
+ max-width: 1600px;
87
  margin: 0 auto;
88
  width: 100%;
89
  padding: 2rem;
90
  display: grid;
91
+ grid-template-columns: 400px 1fr;
92
  gap: 2rem;
93
  }
94
 
 
141
 
142
  textarea {
143
  resize: vertical;
144
+ min-height: 120px;
145
  }
146
 
147
  input:focus,
 
190
  display: flex;
191
  justify-content: space-between;
192
  align-items: center;
193
+ border-bottom: 1px solid var(--border);
194
+ padding-bottom: 1rem;
195
+ margin-bottom: 1rem;
196
  }
197
 
198
  .status-badge {
 
205
 
206
  .grid {
207
  display: grid;
208
+ grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
209
  gap: 1.5rem;
210
  }
211
 
 
213
  background-color: var(--bg-card);
214
  border: 1px solid var(--border);
215
  border-radius: var(--radius);
216
+ padding: 0;
217
  display: flex;
218
  flex-direction: column;
219
  transition: transform 0.2s, box-shadow 0.2s;
 
230
  .card-header {
231
  display: flex;
232
  justify-content: space-between;
233
+ align-items: center;
234
+ padding: 1rem 1.5rem;
235
+ border-bottom: 1px solid var(--border);
236
+ background-color: rgba(255, 255, 255, 0.02);
237
  }
238
 
239
  .card-title {
240
+ font-size: 0.85rem;
241
  font-weight: 700;
242
  color: var(--primary);
243
  text-transform: uppercase;
244
  letter-spacing: 0.05em;
245
+ display: flex;
246
+ align-items: center;
247
+ gap: 0.5rem;
248
+ }
249
+
250
+ .card-type {
251
+ font-size: 0.7rem;
252
+ padding: 2px 6px;
253
+ border-radius: 4px;
254
+ background: var(--bg-input);
255
+ color: var(--text-muted);
256
+ text-transform: uppercase;
257
  }
258
 
259
  .card-content {
260
+ padding: 1.5rem;
261
+ font-family: 'JetBrains Mono', monospace;
 
 
262
  font-size: 0.85rem;
263
  color: #e2e8f0;
264
  white-space: pre-wrap;
265
  word-break: break-word;
266
+ max-height: 400px;
267
  overflow-y: auto;
268
+ background-color: rgba(0, 0, 0, 0.2);
269
+ flex: 1;
270
  }
271
 
272
  .card-actions {
273
+ padding: 0.75rem 1.5rem;
274
+ border-top: 1px solid var(--border);
275
  display: flex;
276
  justify-content: flex-end;
277
+ background-color: rgba(255, 255, 255, 0.02);
278
  }
279
 
280
  .btn-copy {
 
300
  /* Empty State */
301
  .empty-state {
302
  text-align: center;
303
+ padding: 5rem 2rem;
304
  color: var(--text-muted);
305
  border: 2px dashed var(--border);
306
  border-radius: var(--radius);
 
338
  opacity: 0;
339
  transform: translateY(10px);
340
  }
341
+
342
  to {
343
  opacity: 1;
344
  transform: translateY(0);
 
370
  padding: 1rem;
371
  }
372
  }
373
+
374
+ /* Scrollbar styling */
375
+ ::-webkit-scrollbar {
376
+ width: 8px;
377
+ }
378
+ ::-webkit-scrollbar-track {
379
+ background: transparent;
380
+ }
381
+ ::-webkit-scrollbar-thumb {
382
+ background: var(--border);
383
+ border-radius: 4px;
384
+ }
385
+ ::-webkit-scrollbar-thumb:hover {
386
+ background: var(--text-muted);
387
+ }
388
  </style>
389
  </head>
390
 
391
  <body>
392
 
393
  <header>
394
+ <div class="brand">
395
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 1 0 10 10 4 4 0 0 1-5-5 4 4 0 0 1-5-5"></path><path d="M8.5 8.5v.01"></path><path d="M16 12l-2-2"></path><path d="M16 16l-2-2"></path><path d="M12 12l-2-2"></path><path d="M12 16l-2-2"></path></svg>
396
+ PromptGen AI
397
+ </div>
398
  <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with
399
  anycoder</a>
400
  </header>
 
412
  </h2>
413
 
414
  <div class="form-group">
415
+ <label for="productName">Nome do Produto (INPUT_PRODUCT_NAME)</label>
416
+ <textarea id="productName" placeholder="e.g. Bermuda Viena Feminina em Algodão High-Waisted Pague 3 Leve 5"></textarea>
417
+ <p class="helper-text">Inclua material, gênero, recursos estruturais e oferta promocional.</p>
418
  </div>
419
 
420
  <div class="form-group">
421
+ <label for="colorList">Lista de Cores (INPUT_COLORS)</label>
422
+ <input type="text" id="colorList" placeholder="e.g. Black/Grey/Blue/Green">
423
+ <p class="helper-text">Use vírgulas, barras ou + para separar (ex: Green, Khaki, White).</p>
424
  </div>
425
 
426
  <button class="btn-primary" id="generateBtn">Gerar Prompts</button>
 
429
  <!-- Output Section -->
430
  <section class="output-container">
431
  <div class="results-header">
432
+ <h2>Resultados Gerados</h2>
433
  <span class="status-badge" id="statusBadge">Aguardando entrada...</span>
434
  </div>
435
 
 
447
 
448
  <script>
449
  // --- Constants & Templates ---
450
+
451
  const TEMPLATES = [
452
  {
453
+ id: "detail_1",
454
  title: "DETALHE DO PRODUTO",
455
+ type: "SINGLE",
456
  content: `STRICT VISUAL MATCH TAKEN WITH IPHONE. 1:1 Square format. The subject is the EXACT "Bermuda Viena Feminina" in Linen and Cotton. The design must be IDENTICAL to the reference: high-waisted structure with precise vertical front seams (nervuras). A feminine hand is gently pinching the fabric on the front seam to display the exact ribbing detail and texture. Extreme close-up focus on the material weave and seam construction. Natural sunlight, casual Brazilian atmosphere, amateur raw photo style, beige color. DO NOT ALTER THE SILHOUETTE OR DETAILS. --ar 1:1 --style raw --v 6.0`
457
  },
458
  {
459
+ id: "detail_2",
460
  title: "DETALHE DO PRODUTO 2",
461
+ type: "SINGLE",
462
  content: `Commercial macro photography, extreme close-up focus on fabric texture, women's high-waisted bermuda shorts made of premium linen and cotton blend, detailed visible front ribs/nervuras, natural beige color, soft diffused studio lighting to enhance fabric grain, tactile surface quality, shallow depth of field with bokeh neutral background, ultra-realistic, 8k resolution, shot on Sony A7R IV, 100mm macro lens, cinematic style, luxury e-commerce aesthetic, visible fiber details, no text, no watermark. --ar 4:5 --style raw --v 6.0`
463
  },
464
  {
465
+ id: "person_1",
466
  title: "PESSOA USANDO",
467
+ type: "SINGLE",
468
  content: `Square 1:1 photo taken on an iPhone, candid street photography style. A female model stands on a bright Brazilian street, neck down, wearing shorts that are an exact visual match to the reference image: High-waisted 'Bermuda Viena' made of Linen and Cotton. Key details: Prominent vertical front seams/ribs (nervuras frontais), structured high waist, and a textured natural fabric weave that looks like linen. The shorts fit is relaxed but tailored. The color is natural beige. The lighting is harsh natural sunlight typical of Brazil, emphasizing the fabric texture. Background is a blurred concrete wall or sidewalk. The shot is raw and unposed, focused on capturing the precise cut and design of the product.`
469
  },
470
  {
471
+ id: "person_2",
472
  title: "PESSOA USANDO 2",
473
+ type: "SINGLE",
474
  content: `A raw, candid square photo taken on an iPhone 15 Pro Max. STRICT VISUAL REPLICATION REQUIRED. The subject is wearing the EXACT 'Bermuda Viena Feminina' shorts. MUST FEATURE: High-waisted cut, distinctive vertical front ribs/nervuras seams running down the front, straight leg silhouette made of premium linen and cotton blend. The fabric texture is clearly visible, highlighting the natural earthy beige color and coarse weave. DO NOT ALTER THE DESIGN OR SILHOUETTE. Setting: Vibrant Brazilian urban street, textured white concrete wall, Portuguese stone sidewalk, intense midday sun casting sharp natural shadows. The vibe is effortless, tropical, and relaxed 'bem básico' style. High definition, authentic iPhone camera aesthetic, unposed, street photography style. --ar 1:1 --style raw --v 6.0`
475
  },
476
  {
477
+ id: "mirror",
478
  title: "AVALIAÇÃO ESPELHO",
479
+ type: "SINGLE",
480
  content: `Authentic Shopee-style customer review photo, raw vertical mirror selfie, 9:18 aspect ratio. A female model is standing in front of a bathroom mirror, framed from the neck up (no face visible, hiding face). She is wearing the EXACT "Bermuda Viena" high-waisted shorts. STRICT VISUAL FIDELITY: The shorts must feature the specific vertical front ribs/nervuras seams, linen and cotton fabric texture, beige color. The setting is a typical Brazilian home bathroom with natural ambient light. The image must look like a real amateur photo taken by a customer, realistic phone camera grain, showing the fit of the high waist and the straight leg cut. Candid, unposed, honest product demonstration. --ar 9:16 --style raw --v 6.0`
481
  },
482
  {
483
+ id: "bed",
484
  title: "AVALIAÇÃO CAMA",
485
+ type: "GLOBAL",
486
  content: `Authentic Brazilian Shopee customer review photo, raw vertical mobile shot, 9:16 aspect ratio. THE SCENE: A messy, unorganized pile of exactly 5 pairs of 'Bermuda Viena' shorts thrown casually across a bedroom bed. The shorts are fully unfolded and lying in a heap. COLOR CRITICAL: The pile must display the specific 5 colors from the product listing: Green, Khaki, White, Black, and Bege. STICT FIDELITY: Exact 'Bermuda Viena' model, high-waisted, vertical front ribs/nervuras, linen texture. LOGO: Brand tag visible. VIBE: Honest amateur photo, natural daylight, typical home setting, showing the variety of the purchase. --ar 9:16 --style raw --v 6.0`
487
  },
488
  {
489
+ id: "main",
490
  title: "FOTO PRINCIPAL",
491
+ type: "GLOBAL",
492
  content: `Professional 1:1 square e-commerce product photograph featuring a charismatic, confident Brazilian woman standing behind a horizontal clothing rail. She has a warm, sun-kissed Brazilian complexion, natural hair texture, and distinctively Brazilian facial features. Her expression is authentic, engaging, and confident, with realistic human skin texture to avoid an artificial look. The rail displays exactly 5 identical pairs of "Bermuda Viena Feminina" shorts hanging perfectly flat, straight side-by-side, and FULLY UNCROPPED. STRICT DESIGN SPECIFICATIONS: The shorts must be exact replicas: high-waisted structure, distinctive vertical front ribs/nervuras seams, premium linen and cotton blend texture, straight leg cut. LOGO: A visible brand logo is present on the waistband or label of the shorts. COLOR PALETTE: Verde (Green), Cáqui (Khaki), Branco (White), Preto (Black), Beige. COMPOSITION: Hands gripping the rail, clear full view of all 5 shorts in the foreground without obstruction. BACKGROUND: Minimalist white studio backdrop, soft uniform lighting. Hyper-realistic texture focus, commercial catalog quality. --ar 1:1 --v 6.0 --style raw`
493
  },
494
  {
495
+ id: "text_overlay",
496
  title: "TEXTO FOTO PRINCIPAL",
497
+ type: "GLOBAL",
498
  content: `Ensure the promotional text "Pague 3, Leve 5". Preserve exact original image position. Maintain flat lighting, no visible JPEG artifacts, Ultra-realistic, 8k resolution, photographic clarity, sharp focus, high fidelity textures, crisp details. Simple composition, use of symmetry, shallow depth of field, background blurred, leading lines created by clothes rack, no other objects, minimalist style. Add bold, sharp graphic text overlays seamlessly integrated without altering the photography subject.`
499
  },
500
  {
501
+ id: "png",
502
  title: "SOMENTE O PRODUTO (PNG)",
503
+ type: "GLOBAL",
504
  content: `Professional product photography of exactly 5 identical copies of the source image product arranged in a tight horizontal row. COLOR PALETTE EXACT: The five shorts must display the following distinct colors: Green (Verde), Khaki (Cáki), White (Branco), Black (Preto), and Beige. The shorts are suspended in mid-air as if on invisible hangers, maintaining a stiff, perfectly straight structured shape. The legs are pressing tightly against each other with zero space or gaps between the items. NO HARDWARE: Absolutely no visible hangers, hooks, or strings, only the shorts floating. CRITICAL: The texture, fabric, stitching nervuras, and logo must be an exact duplication of the reference image provided. Product photography, pure white background, studio light. --ar 5:1 --style raw --iw 3`
505
  }
506
  ];
 
508
  // --- Logic Functions ---
509
 
510
  /**
511
+ * Step 1: Advanced Variable Extraction
512
  */
513
+ function extractData(productNameInput, colorsInput) {
514
  // 1. PRODUCT_NAME: Clean input
515
+ // Remove promotional text for the core name, but keep it for PROMOTIONAL_OFFER extraction
516
+ // However, the prompt says "PRODUCT_NAME: The core product name (cleaned of promotional text)."
517
+ // We need to extract promo text first, then remove it.
518
+
519
+ let rawName = productNameInput.trim();
520
+ let promoOffer = null;
521
+ let totalQuantity = 0;
522
+
523
+ // Extract Promotional Offer (e.g., "Pague 3, Leve 5")
524
+ // Regex looks for "Pague X, Leve Y" variations
525
+ const promoRegex = /pague\s*\d+\s*(?:,|e)?\s*leve\s*\d+/i;
526
+ const promoMatch = rawName.match(promoRegex);
527
+
528
+ if (promoMatch) {
529
+ promoOffer = promoMatch[0];
530
+ // Extract Quantity from offer
531
+ const qtyMatch = promoOffer.match(/leve\s*(\d+)/i);
532
+ if (qtyMatch) {
533
+ totalQuantity = parseInt(qtyMatch[1], 10);
534
+ }
535
+ }
536
+
537
+ // Clean Product Name (Remove promo text)
538
+ let productName = rawName.replace(promoRegex, '').trim();
539
+ // Remove trailing commas or artifacts
540
+ productName = productName.replace(/,\s*$/, '').trim();
541
 
542
+ // 2. MATERIAL: Identify and translate
543
  const materialMap = {
544
  'algodão': 'Cotton',
545
+ 'algodon': 'Cotton',
546
  'linho': 'Linen',
547
  'poliéster': 'Polyester',
548
+ 'poliester': 'Polyester',
549
  'seda': 'Silk',
550
  'jeans': 'Denim',
551
+ 'denim': 'Denim',
552
+ 'couro': 'Leather'
553
  };
554
 
555
+ let material = 'Cotton'; // Default
556
+ const lowerInput = rawName.toLowerCase(); // Check raw input for material keywords
557
 
558
  for (const [key, value] of Object.entries(materialMap)) {
559
  if (lowerInput.includes(key)) {
 
564
 
565
  // 3. TARGET_AUDIENCE
566
  let gender = 'Female'; // Default
567
+ if (/masculina|masculino|homem|menino|male/i.test(rawName)) {
568
  gender = 'Male';
569
  }
570
 
571
+ // 4. HAS_GIFTS
572
+ const hasGifts = /brinde|bônus|presente|bonus/i.test(rawName);
573
 
574
+ // 5. TOTAL_QUANTITY (Fallback if no promo offer)
575
+ if (totalQuantity === 0) {
576
+ // Will be calculated from color array later if 0
 
 
 
577
  }
578
 
579
+ // 6. STRUCTURAL_FEATURES
580
+ const hasHighWaisted = /(?:high-waisted|alta cintura|cintura alta)/i.test(rawName);
581
+ const hasRibs = /(?:nervuras|ribs|costuras)/i.test(rawName);
582
+
583
+ // 7. COLORS
584
+ // Split delimiters (/, ,, or +)
585
+ const rawColors = colorsInput.split(/[\/,+]/).map(c => c.trim()).filter(c => c.length > 0);
586
+
587
+ // Color Translation Map
588
+ const colorMap = {
589
+ 'verde': 'Green',
590
+ 'vermelho': 'Red',
591
+ 'azul': 'Blue',
592
+ 'amarelo': 'Yellow',
593
+ 'laranja': 'Orange',
594
+ 'roxo': 'Purple',
595
+ 'rosa': 'Pink',
596
+ 'marrom': 'Brown',
597
+ 'preto': 'Black',
598
+ 'branco': 'White',
599
+ 'cinza': 'Grey',
600
+ 'grey': 'Grey',
601
+ 'bege': 'Beige',
602
+ 'khaki': 'Khaki',
603
+ 'cáqui': 'Khaki',
604
+ 'dourado': 'Gold',
605
+ 'prata': 'Silver'
606
  };
 
607
 
608
+ const colorArray = rawColors.map(c => {
609
+ const lowerC = c.toLowerCase();
610
+ // If it's already in the map, translate. Otherwise keep as is (assuming English or proper noun).
611
+ return colorMap[lowerC] || c;
612
+ });
613
 
614
+ // Calculate Total Quantity from colors if not set by promo
615
+ if (totalQuantity === 0) {
616
+ totalQuantity = colorArray.length > 0 ? colorArray.length : 1;
617
+ }
618
 
619
+ // Format List String (e.g., "Green, Khaki, White, Black, and Beige")
620
+ let colorListString = '';
621
+ if (colorArray.length === 0) {
622
+ colorListString = 'Assorted Colors';
623
+ } else if (colorArray.length === 1) {
624
+ colorListString = colorArray[0];
625
+ } else if (colorArray.length === 2) {
626
+ colorListString = `${colorArray[0]} and ${colorArray[1]}`;
627
  } else {
628
+ const last = colorArray[colorArray.length - 1];
629
+ const rest = colorArray.slice(0, -1).join(', ');
630
+ colorListString = `${rest}, and ${last}`;
631
  }
632
 
633
  return {
634
+ productName,
635
+ material,
636
+ gender,
637
+ promoOffer,
638
+ totalQuantity,
639
+ hasGifts,
640
+ hasHighWaisted,
641
+ hasRibs,
642
+ colorArray,
643
+ colorListString
644
  };
645
  }
646
 
647
  /**
648
+ * Step 2, 3, & 4: Logic, Substitution & Output Generation
649
  */
650
+ function generateFinalPrompts(data) {
651
+ let singleColorIndex = 0;
 
 
 
 
652
 
653
+ return TEMPLATES.map(template => {
 
 
 
 
 
654
  let text = template.content;
655
 
656
+ // --- Step 3: Color Distribution Logic ---
657
+ let assignedColor = '';
658
+ if (template.type === "GLOBAL") {
659
+ // Use Color List String
660
+ assignedColor = data.colorListString;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
661
  } else {
662
+ // Use Unique Color Rotation
663
+ assignedColor = data.colorArray[singleColorIndex % data.colorArray.length] || 'Assorted';
664
+ singleColorIndex++;
 
 
 
 
 
 
 
 
 
 
 
 
665
  }
666
 
667
+ // --- Step 3: Template Substitution (Global Replacements) ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
 
669
+ // 1. Replace Product Name
670
+ // Replace "Bermuda Viena Feminina", "'Bermuda Viena'", "Bermuda Viena"
671
+ const nameVariations = [
672
+ /Bermuda Viena Feminina/g,
673
+ /'Bermuda Viena'/g,
674
+ /Bermuda Viena/g
675
+ ];
676
+ nameVariations.forEach(regex => {
677
+ text = text.replace(regex, data.productName);
678
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
679
 
680
+ // 2. Replace Material
681
+ // "Linen and Cotton", "linen and cotton", "Linen", "Cotton"
682
+ // We replace the specific blend mention first, then individual if needed,
683
+ // but usually, we map the input material to the blend.
684
+ const matRegex = /linen and cotton/gi;
685
+ text = text.replace(matRegex, data.material);
686
+
687
+ // Also catch standalone "linen" or "cotton" if the input is just one
688
+ if (data.material === 'Linen') {
689
+ text = text.replace(/\bcotton\b/gi, 'Linen');
690
+ } else if (data.material === 'Cotton') {
691
+ text = text.replace(/\blinen\b/gi, 'Cotton');
692
+ }
693
 
694
+ // 3. Replace Quantity
695
+ // "5 pairs", "5 identical copies", "exactly 5 pairs"
696
+ const qStr = data.totalQuantity.toString();
697
+ text = text.replace(/5 pairs/g,