Spaces:
Running
Running
File size: 30,016 Bytes
63a7935 2b59679 63a7935 66039ae 5b307fb 66039ae af1997e 66039ae 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 66039ae af1997e 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb e9b8425 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 2b59679 66039ae 58d2e3c 66039ae 5b307fb 66039ae 5b307fb 66039ae 2b59679 66039ae 58d2e3c 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 66039ae 5b307fb 66039ae 58d2e3c 5b307fb 58d2e3c 5b307fb 58d2e3c 5b307fb 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 5b307fb 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 66039ae aa98a2f 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 66039ae 5b307fb 66039ae 5b307fb 66039ae 5b307fb af1997e 5b307fb af1997e 5b307fb af1997e 5b307fb 66039ae aa98a2f 5b307fb 58d2e3c 5b307fb 58d2e3c aa98a2f 58d2e3c aa98a2f 58d2e3c aa98a2f 58d2e3c 66039ae 63a7935 66039ae 63a7935 66039ae 58d2e3c aa98a2f 5b307fb 58d2e3c 66039ae 2b59679 66039ae 2b59679 66039ae 2b59679 58d2e3c 2b59679 66039ae e9b8425 66039ae 2b59679 66039ae aa98a2f 66039ae 2b59679 66039ae 5b307fb af1997e 5b307fb 66039ae 5b307fb 66039ae 58d2e3c 66039ae 58d2e3c 2b59679 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 2b59679 66039ae 58d2e3c 66039ae 58d2e3c 2b59679 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 5b307fb 58d2e3c 2b59679 58d2e3c 2b59679 58d2e3c 2b59679 58d2e3c 2b59679 58d2e3c 66039ae 2b59679 66039ae 2b59679 66039ae 2b59679 66039ae 2b59679 58d2e3c 66039ae 58d2e3c aa98a2f 66039ae 58d2e3c 66039ae 2b59679 66039ae 2b59679 58d2e3c 2b59679 58d2e3c 2b59679 66039ae 58d2e3c 66039ae 2b59679 58d2e3c 66039ae 2b59679 58d2e3c 66039ae 58d2e3c 66039ae 58d2e3c 66039ae 5b307fb 2b59679 58d2e3c 66039ae 58d2e3c 66039ae 2b59679 58d2e3c 66039ae 2b59679 58d2e3c 66039ae 2b59679 58d2e3c 66039ae 2b59679 aa98a2f 2b59679 aa98a2f 2b59679 8549f24 2b59679 8549f24 2b59679 8549f24 2b59679 e9b8425 5b307fb e9b8425 af1997e |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Prompt Gen | E-Commerce Asset System v4.9</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<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">
<style>
:root {
/* Color Palette - Modern Dark Theme */
--bg-body: #0f172a;
--bg-card: #1e293b;
--bg-card-hover: #263345;
--bg-input: #334155;
--text-main: #f8fafc;
--text-muted: #94a3b8;
--primary: #3b82f6;
--primary-hover: #2563eb;
--accent: #10b981;
--danger: #ef4444;
--border: #334155;
--border-hover: #475569;
--shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3), 0 2px 4px -1px rgba(0, 0, 0, 0.15);
--radius: 12px;
--transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Reset & Base */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-body);
color: var(--text-main);
line-height: 1.6;
min-height: 100vh;
display: flex;
flex-direction: column;
background-image: radial-gradient(circle at top right, #1e293b 0%, transparent 40%);
}
/* Header */
header {
background-color: rgba(30, 41, 59, 0.8);
backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border);
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
position: sticky;
top: 0;
z-index: 100;
}
.brand {
font-size: 1.25rem;
font-weight: 700;
background: linear-gradient(135deg, var(--primary), var(--accent));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -0.025em;
display: flex;
align-items: center;
gap: 0.75rem;
}
.brand svg {
color: var(--primary);
}
.anycoder-link {
font-size: 0.875rem;
color: var(--text-muted);
text-decoration: none;
transition: var(--transition);
border: 1px solid var(--border);
padding: 0.35rem 1rem;
border-radius: 99px;
font-weight: 500;
}
.anycoder-link:hover {
color: var(--primary);
border-color: var(--primary);
background-color: rgba(59, 130, 246, 0.1);
}
/* Main Layout */
main {
flex: 1;
max-width: 1600px;
margin: 0 auto;
width: 100%;
padding: 2rem;
display: grid;
grid-template-columns: 400px 1fr;
/* Slightly wider sidebar for usability */
gap: 2.5rem;
align-items: start;
}
/* Sidebar / Inputs */
aside {
background-color: var(--bg-card);
border-radius: var(--radius);
padding: 1.75rem;
border: 1px solid var(--border);
position: sticky;
top: 6rem;
box-shadow: var(--shadow);
}
h2 {
font-size: 1.1rem;
margin-bottom: 1.5rem;
color: var(--text-main);
font-weight: 600;
display: flex;
align-items: center;
gap: 0.5rem;
}
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
font-size: 0.875rem;
color: var(--text-muted);
margin-bottom: 0.5rem;
font-weight: 500;
}
input,
textarea {
width: 100%;
background-color: var(--bg-input);
border: 1px solid var(--border);
border-radius: 8px;
padding: 0.875rem 1rem;
color: var(--text-main);
font-family: inherit;
font-size: 0.95rem;
transition: var(--transition);
}
textarea {
resize: vertical;
min-height: 120px;
}
input:focus,
textarea:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
background-color: #384659;
}
.helper-text {
font-size: 0.75rem;
color: var(--text-muted);
margin-top: 0.5rem;
font-style: italic;
opacity: 0.8;
}
button.btn-primary {
width: 100%;
padding: 1rem;
background-color: var(--primary);
color: white;
border: none;
border-radius: 8px;
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: var(--transition);
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
}
button.btn-primary:hover {
background-color: var(--primary-hover);
transform: translateY(-1px);
box-shadow: 0 6px 16px rgba(59, 130, 246, 0.3);
}
button.btn-primary:active {
transform: translateY(1px);
}
/* Output Section */
.output-container {
display: flex;
flex-direction: column;
gap: 1rem;
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
padding-bottom: 1rem;
margin-bottom: 1rem;
}
.status-badge {
font-size: 0.8rem;
padding: 0.3rem 0.8rem;
border-radius: 99px;
background-color: var(--bg-input);
color: var(--text-muted);
font-weight: 500;
border: 1px solid var(--border);
}
.status-badge.success {
color: var(--accent);
border-color: rgba(16, 185, 129, 0.3);
background-color: rgba(16, 185, 129, 0.1);
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(500px, 1fr));
gap: 1.5rem;
}
.card {
background-color: var(--bg-card);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0;
display: flex;
flex-direction: column;
transition: var(--transition);
position: relative;
overflow: hidden;
animation: fadeIn 0.5s ease-out forwards;
}
.card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow);
border-color: var(--border-hover);
background-color: var(--bg-card-hover);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 1.5rem;
border-bottom: 1px solid var(--border);
background-color: rgba(255, 255, 255, 0.02);
}
.card-title {
font-size: 0.8rem;
font-weight: 700;
color: var(--primary);
text-transform: uppercase;
letter-spacing: 0.05em;
display: flex;
align-items: center;
gap: 0.5rem;
}
.card-type {
font-size: 0.65rem;
padding: 2px 8px;
border-radius: 4px;
background: rgba(255, 255, 255, 0.05);
color: var(--text-muted);
text-transform: uppercase;
border: 1px solid var(--border);
}
.card-content {
padding: 1.5rem;
font-family: 'JetBrains Mono', monospace;
font-size: 0.85rem;
color: #e2e8f0;
white-space: pre-wrap;
word-break: break-word;
max-height: 400px;
overflow-y: auto;
background-color: rgba(0, 0, 0, 0.2);
flex: 1;
line-height: 1.5;
}
.card-actions {
padding: 0.75rem 1.5rem;
border-top: 1px solid var(--border);
display: flex;
justify-content: flex-end;
background-color: rgba(255, 255, 255, 0.02);
}
.btn-copy {
background-color: transparent;
border: 1px solid var(--border);
color: var(--text-muted);
padding: 0.4rem 1rem;
border-radius: 6px;
font-size: 0.8rem;
cursor: pointer;
transition: var(--transition);
display: flex;
align-items: center;
gap: 0.5rem;
font-weight: 500;
}
.btn-copy:hover {
background-color: var(--bg-input);
color: var(--text-main);
border-color: var(--text-muted);
}
/* Empty State */
.empty-state {
text-align: center;
padding: 5rem 2rem;
color: var(--text-muted);
border: 2px dashed var(--border);
border-radius: var(--radius);
grid-column: 1 / -1;
background-color: rgba(255, 255, 255, 0.01);
}
.empty-icon {
font-size: 3rem;
margin-bottom: 1rem;
opacity: 0.5;
}
/* Toast Notification */
.toast {
position: fixed;
bottom: 2rem;
right: 2rem;
background-color: var(--accent);
color: #fff;
padding: 0.75rem 1.5rem;
border-radius: 8px;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.3);
transform: translateY(150%);
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
z-index: 1000;
font-weight: 600;
display: flex;
align-items: center;
gap: 0.5rem;
}
.toast.show {
transform: translateY(0);
}
/* Animations */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Responsive Design */
@media (max-width: 1024px) {
main {
grid-template-columns: 1fr;
}
aside {
position: static;
width: 100%;
}
}
@media (max-width: 600px) {
.grid {
grid-template-columns: 1fr;
}
header {
padding: 1rem;
}
main {
padding: 1rem;
}
.brand span {
display: none;
/* Hide text on very small screens, keep logo */
}
.brand span:first-child {
display: block;
/* Keep the svg visible */
}
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--border);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-muted);
}
</style>
</head>
<body>
<header>
<div class="brand">
<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>
<span>PromptGen AI v4.9</span>
</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with
anycoder</a>
</header>
<main>
<!-- Input Section -->
<aside>
<h2>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path>
<path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path>
</svg>
Input Data
</h2>
<div class="form-group">
<label for="productName">INPUT_PRODUCT_NAME</label>
<textarea id="productName" placeholder="e.g. Bermuda Viena Feminina Algodão Pague 3 Leve 5"></textarea>
<p class="helper-text">Include material, gender, features (High-waisted, Nervuras), and offer.</p>
</div>
<div class="form-group">
<label for="colorList">INPUT_COLORS</label>
<input type="text" id="colorList" placeholder="e.g. Black/Grey/Blue/Green">
<p class="helper-text">Use commas, slashes, or + to separate (e.g., Verde, Cáqui, White).</p>
</div>
<button class="btn-primary" id="generateBtn">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12a9 9 0 1 1-6.219-8.56"></path></svg>
Generate Prompts
</button>
</aside>
<!-- Output Section -->
<section class="output-container">
<div class="results-header">
<h2>Generated Results</h2>
<span class="status-badge" id="statusBadge">Waiting for input...</span>
</div>
<div id="resultsGrid" class="grid">
<div class="empty-state">
<div class="empty-icon">⚡</div>
<h3>Ready to Generate</h3>
<p>Enter product details and click the button to execute the logic engine.</p>
</div>
</div>
</section>
</main>
<div id="toast" class="toast">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
Copied to clipboard!
</div>
<script>
/**
* TEMPLATES (BLOCKS 1-9)
* Core definitions for the prompt generation logic.
*/
const TEMPLATES = [
{
id: "detail_1",
title: "DETALHE DO PRODUTO",
type: "SINGLE",
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`
},
{
id: "detail_2",
title: "DETALHE DO PRODUTO 2",
type: "SINGLE",
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`
},
{
id: "person_1",
title: "PESSOA USANDO",
type: "SINGLE",
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.`
},
{
id: "person_2",
title: "PESSOA USANDO 2",
type: "SINGLE",
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`
},
{
id: "mirror",
title: "AVALIAÇÃO ESPELHO",
type: "SINGLE",
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`
},
{
id: "bed",
title: "AVALIAÇÃO CAMA",
type: "GLOBAL",
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. STRICT 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`
},
{
id: "main",
title: "FOTO PRINCIPAL",
type: "GLOBAL",
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`
},
{
id: "text_overlay",
title: "TEXTO FOTO PRINCIPAL",
type: "GLOBAL",
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.`
},
{
id: "png",
title: "SOMENTE O PRODUTO (PNG)",
type: "GLOBAL",
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`
}
];
/**
* STEP 1: VARIABLE EXTRACTION & PARSING
* Analyzes raw input strings to extract structured data.
*/
function extractData(productNameInput, colorsInput) {
let rawName = productNameInput.trim();
// 1. PRODUCT_NAME (Cleaned)
// Remove promo text for the clean name, but keep it for PROMOTIONAL_OFFER extraction
const promoRegex = /pague\s*\d+\s*(?:,|e)?\s*leve\s*\d+/i;
const promoMatch = rawName.match(promoRegex);
let promoOffer = promoMatch ? promoMatch[0] : null;
// Clean Name: Remove promo offer
let productName = rawName.replace(promoRegex, '').trim();
// Remove trailing punctuation artifacts
productName = productName.replace(/,\s*$/, '').trim();
// 2. MATERIAL (Extract & Translate)
const materialMap = {
'algodão': 'Cotton', 'algodon': 'Cotton',
'linho': 'Linen',
'poliéster': 'Polyester', 'poliester': 'Polyester',
'seda': 'Silk',
'jeans': 'Denim', 'denim': 'Denim',
'couro': 'Leather'
};
let material = 'Cotton'; // Default
const lowerInput = rawName.toLowerCase();
for (const [key, value] of Object.entries(materialMap)) {
if (lowerInput.includes(key)) {
material = value;
break;
}
}
// 3. TARGET_AUDIENCE
let gender = 'Female'; // Default
if (/masculina|masculino|homem|menino|male/i.test(rawName)) {
gender = 'Male';
}
// 4. PROMOTIONAL_OFFER (Already extracted above)
// 5. TOTAL_QUANTITY
let totalQuantity = 0;
// Priority A: Extract from "Leve [X]"
if (promoOffer) {
const qtyMatch = promoOffer.match(/leve\s*(\d+)/i);
if (qtyMatch) totalQuantity = parseInt(qtyMatch[1], 10);
}
// 6. HAS_GIFTS
const hasGifts = /brinde|bônus|presente|bonus/i.test(rawName);
// 7. STRUCTURAL_FEATURES
const hasHighWaisted = /(?:high-waisted|alta cintura|cintura alta)/i.test(rawName);
const hasRibs = /(?:nervuras|ribs|costuras)/i.test(rawName);
// 8. COLORS (Split & Translate)
const rawColors = colorsInput.split(/[\/,+]/).map(c => c.trim()).filter(c => c.length > 0);
const colorMap = {
'verde': 'Green', 'vermelho': 'Red', 'azul': 'Blue', 'amarelo': 'Yellow',
'laranja': 'Orange', 'roxo': 'Purple', 'rosa': 'Pink', 'marrom': 'Brown',
'preto': 'Black', 'branco': 'White', 'cinza': 'Grey', 'grey': 'Grey',
'bege': 'Beige', 'khaki': 'Khaki', 'cáqui': 'Khaki', 'dourado': 'Gold', 'prata': 'Silver'
};
const colorArray = rawColors.map(c => {
const lowerC = c.toLowerCase();
return colorMap[lowerC] || c;
});
// Priority B: Count from colors if quantity is 0
if (totalQuantity === 0) {
totalQuantity = colorArray.length > 0 ? colorArray.length : 1;
}
// Format Color List String (e.g., "Green, Khaki, White, Black, and Beige")
let colorListString = '';
if (colorArray.length === 0) {
colorListString = 'Assorted Colors';
} else if (colorArray.length === 1) {
colorListString = colorArray[0];
} else if (colorArray.length === 2) {
colorListString = `${colorArray[0]} and ${colorArray[1]}`;
} else {
const last = colorArray[colorArray.length - 1];
const rest = colorArray.slice(0, -1).join(', ');
colorListString = `${rest}, and ${last}`;
}
return {
productName,
material,
gender,
promoOffer,
totalQuantity,
hasGifts,
hasHighWaisted,
hasRibs,
colorArray,
colorListString
};
}
/**
* STEP 2, 3, & 4: LOGIC, DISTRIBUTION & INJECTION
* Processes templates based on extracted data.
*/
function processTemplates(data) {
let singleColorIndex = 0;
return TEMPLATES.map(template => {
let text = template.content;
// --- STEP 3: COLOR DISTRIBUTION ---
let assignedColor = '';
if (template.type === "GLOBAL") {
assignedColor = data.colorListString;
} else {
// Single Display Rotation
assignedColor = data.colorArray[singleColorIndex % data.colorArray.length] || 'Assorted';
singleColorIndex++;
}
// --- STEP 2: CONDITIONAL LOGIC ENGINE ---
// Rule A: Feature Adaptation (Deletion)
if (!data.hasHighWaisted) {
text = text.replace(/\bhigh-waisted\b/gi, '');
text = text.replace(/\bhigh waist\b/gi, 'waist');
text = text.replace(/\balta cintura\b/gi, '');
text = text.replace(/\s+/g, ' ').trim();
}
if (!data.hasRibs) {
text = text.replace(/vertical front seams/gi, '');
text = text.replace(/nervuras/gi, '');
text = text.replace(/ribs/gi, '');
text = text.replace(/\s+/g, ' ').trim();
}
// Rule B: Gender Adaptation
if (data.gender === 'Male') {
text = text.replace(/female model/gi, 'male model');
text = text.replace(/woman/gi, 'man');
text = text.replace(/women's/gi, "men's");
text = text.replace(/feminine hand/gi, 'masculine hand');
text = text.replace(/Brazilian woman/gi, 'Brazilian man');
}
// Rule C: Text Overlay & Gift Logic
if (template.id === 'text_overlay') {
if (data.promoOffer) {
text = `Ensure the promotional text "${data.promoOffer}". 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.`;
} else {
text = `Ensure the product name "${data.productName}" is clearly visible. 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.`;
}
}
// --- STEP 4: TEMPLATE INJECTION ---
// 1. Product Name
text = text.replace(/Bermuda Viena Feminina/g, data.productName);
text = text.replace(/'Bermuda Viena'/g, `'${data.productName}'`);
text = text.replace(/Bermuda Viena/g, data.productName);
// 2. Material
text = text.replace(/Linen and Cotton/gi, data.material);
if (data.material === 'Linen') text = text.replace(/\bCotton\b/gi, 'Linen');
if (data.material === 'Cotton') text = text.replace(/\bLinen\b/gi, 'Cotton');
// 3. Quantity
text = text.replace(/5 pairs/g, `${data.totalQuantity} pairs`);
text = text.replace(/exactly 5 pairs/g, `exactly ${data.totalQuantity} pairs`);
text = text.replace(/exactly 5 identical/g, `exactly ${data.totalQuantity} identical`);
text = text.replace(/5 identical pairs/g, `${data.totalQuantity} identical pairs`);
// 4. Colors
text = text.replace(/Green, Khaki, White, Black, and Beige/g, data.colorListString);
text = text.replace(/Green \(Verde\), Khaki \(Cáki\), White \(Branco\), Black \(Preto\), and Beige/gi, data.colorListString);
if (template.type === "SINGLE") {
text = text.replace(/\bbeige color\b/gi, `${assignedColor} color`);
text = text.replace(/\bnatural beige\b/gi, `natural ${assignedColor}`);
text = text.replace(/\bcolor is natural beige\b/gi, `color is natural ${assignedColor}`);
}
return {
id: template.id,
title: template.title,
content: text,
type: template.type
};
});
}
/**
* UI RENDERING
* Generates HTML for the result cards.
*/
function renderResults(results) {
const grid = document.getElementById('resultsGrid');
grid.innerHTML = '';
if (results.length === 0) {
grid.innerHTML = `
<div class="empty-state">
<div class="empty-icon">⚡</div>
<h3>No Results</h3>
<p>Try adjusting your input parameters.</p>
</div>
`;
return;
}
results.forEach(item => {
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<div class="card-header">
<span class="card-title">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 |