| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <title>Branded Image Edit Prompt Builder</title> |
| |
| <script src="https://cdn.tailwindcss.com"></script> |
|
|
| <style> |
| |
| |
| |
| |
| :root { |
| |
| --primary-purple: #8A2BE2; |
| --accent-purple: #F3E5F5; |
| --text-color: #6A1B9A; |
| --main-background: #ffffff; |
| --container-background: #f9f9f9; |
| --button-border: #D1C4E9; |
| |
| |
| --max-width: 450px; |
| --border-radius: 15px; |
| --button-radius: 8px; |
| --padding: 30px; |
| } |
| |
| body { |
| font-family: sans-serif; |
| background-color: var(--main-background) !important; |
| color: #333; |
| min-height: 100vh; |
| } |
| |
| |
| header { |
| border-bottom: 1px solid var(--button-border) !important; |
| background-color: var(--main-background) !important; |
| } |
| |
| header h1 { |
| color: var(--primary-purple); |
| font-size: 2em !important; |
| font-weight: bold; |
| } |
| |
| |
| main { |
| max-width: 1000px; |
| margin: 0 auto; |
| padding: 24px 1rem; |
| } |
| |
| .builder-card, .output-card { |
| background-color: var(--container-background) !important; |
| padding: var(--padding) !important; |
| border-radius: var(--border-radius) !important; |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1) !important; |
| border-top: 5px solid var(--primary-purple); |
| } |
| |
| .builder-card h2, .output-card h2 { |
| color: var(--primary-purple); |
| font-size: 1.5em !important; |
| margin-bottom: 15px; |
| } |
| |
| |
| select, input[type="text"], textarea { |
| width: 100%; |
| padding: 20px !important; |
| border-radius: var(--button-radius) !important; |
| border: 1px solid var(--button-border) !important; |
| background-color: var(--main-background) !important; |
| color: #333 !important; |
| font-size: 1em !important; |
| box-sizing: border-box; |
| transition: border-color 0.2s, box-shadow 0.2s; |
| outline: none; |
| } |
| |
| select:focus, input[type="text"]:focus, textarea:focus { |
| border-color: var(--primary-purple) !important; |
| box-shadow: 0 0 0 3px rgba(138, 43, 226, 0.2) !important; |
| } |
| |
| |
| #output { |
| background-color: var(--accent-purple) !important; |
| color: var(--text-color) !important; |
| font-size: 1.1em !important; |
| font-weight: bold; |
| resize: none; |
| } |
| |
| |
| .btn { |
| padding: 10px 15px !important; |
| border-radius: var(--button-radius) !important; |
| font-size: 0.9em !important; |
| font-weight: bold !important; |
| transition: all 0.2s ease-in-out; |
| border: 1px solid var(--button-border); |
| cursor: pointer; |
| text-decoration: none; |
| display: inline-block; |
| } |
| |
| |
| .btn-primary { |
| background-color: var(--primary-purple) !important; |
| color: var(--main-background) !important; |
| } |
| |
| .btn-primary:hover { |
| background-color: #6A1B9A !important; |
| color: var(--main-background) !important; |
| } |
| |
| |
| .btn-secondary { |
| background-color: var(--accent-purple) !important; |
| color: var(--text-color) !important; |
| } |
| |
| .btn-secondary:hover { |
| background-color: var(--primary-purple) !important; |
| color: var(--main-background) !important; |
| border-color: var(--primary-purple); |
| } |
| |
| |
| #copyBtnHeader { |
| padding: 15px 20px !important; |
| font-size: 1em !important; |
| } |
| |
| |
| details summary { |
| cursor: pointer; |
| font-weight: 500; |
| color: var(--text-color); |
| transition: color 0.2s; |
| } |
| details summary:hover { |
| color: var(--primary-purple); |
| } |
| |
| .text-sm-info { |
| font-size: 0.75rem; |
| color: #888; |
| margin-top: 5px; |
| } |
| </style> |
| </head> |
| <body class="min-h-screen bg-slate-50 text-slate-800"> |
| <header class="sticky top-0 z-10 bg-white/80 backdrop-blur border-b border-slate-200"> |
| <div class="max-w-5xl mx-auto px-4 py-4 flex items-center justify-between"> |
| <h1 class="text-xl sm:text-2xl font-bold tracking-tight">Adding & Removing Elements</h1> |
| <a href="#" id="copyBtnHeader" class="btn btn-primary">Copy Prompt</a> |
| </div> |
| </header> |
|
|
| <main class="max-w-5xl mx-auto px-4 py-6 grid lg:grid-cols-2 gap-6"> |
| <section class="builder-card p-5"> |
| <div class="flex items-start justify-between"> |
| <h2>Minimal Selections</h2> |
| <button id="resetBtn" class="btn btn-secondary">Reset</button> |
| </div> |
|
|
| <div class="mt-4 grid gap-5"> |
| <div> |
| <label for="editType" class="block text-sm font-medium" style="color: var(--text-color);">Edit Type</label> |
| <select id="editType" class="mt-2 w-full p-3"> |
| <option value="add">Add</option> |
| <option value="remove">Remove</option> |
| <option value="modify">Modify</option> |
| </select> |
| </div> |
|
|
| <div> |
| <label for="element" class="block text-sm font-medium" style="color: var(--text-color);">Element (what to add/remove/modify)</label> |
| <input id="element" type="text" placeholder="e.g., a red umbrella / the logo on the wall / background sky" class="mt-2 w-full p-3" /> |
| </div> |
|
|
| <div> |
| <label for="integration" class="block text-sm font-medium" style="color: var(--text-color);">Integration (how it should fit)</label> |
| <select id="integration" class="mt-2 w-full p-3"> |
| <option value="blends naturally and looks realistic">Blend naturally and look realistic</option> |
| <option value="matches the scene lighting and perspective">Match lighting and perspective</option> |
| <option value="keeps consistent color and texture with the scene">Keep consistent color and texture</option> |
| <option value="appears slightly stylized but remains believable">Slightly stylized but natural</option> |
| </select> |
| </div> |
|
|
| <details class="mt-1"> |
| <summary>Optional: brief context</summary> |
| <div class="mt-3 grid gap-3"> |
| <input id="context" type="text" placeholder="e.g., indoor daylight / cinematic low‑light / product photo" class="p-3" /> |
| <input id="locationHint" type="text" placeholder="Optional location hint (e.g., left side / near window)" class="p-3" /> |
| </div> |
| </details> |
| </div> |
| </section> |
|
|
| <section class="output-card p-5"> |
| <div class="flex items-start justify-between"> |
| <h2>Prompt Output</h2> |
| <div class="flex gap-2"> |
| <button id="copyBtn" class="btn btn-primary">Copy</button> |
| <button id="downloadBtn" class="btn btn-secondary">Download .txt</button> |
| </div> |
| </div> |
| <p class="text-sm-info">Prompt updates automatically as you type.</p> |
| <textarea id="output" rows="12" class="mt-3 w-full p-4 font-mono text-sm"></textarea> |
|
|
| <div class="mt-4 text-sm-info"> |
| <p><strong>Template</strong>: Using the provided image, <em>[add/remove/modify]</em> <em>[element]</em>, ensuring it <em>[integration]</em> within the scene. <em>(Optional: context/location)</em>.</p> |
| </div> |
| </section> |
| </main> |
|
|
| <footer class="max-w-5xl mx-auto px-4 pb-10 text-center text-xs" style="color: #888;">Coach Pro AI</footer> |
|
|
| <script> |
| const getEl = id => document.getElementById(id); |
| const editTypeEl = getEl('editType'); |
| const elementEl = getEl('element'); |
| const integrationEl = getEl('integration'); |
| const contextEl = getEl('context'); |
| const locationHintEl = getEl('locationHint'); |
| |
| const outputEl = getEl('output'); |
| const copyBtn = getEl('copyBtn'); |
| const copyBtnHeader = getEl('copyBtnHeader'); |
| const downloadBtn = getEl('downloadBtn'); |
| const resetBtn = getEl('resetBtn'); |
| |
| function buildPrompt(){ |
| const t = editTypeEl.value || 'add'; |
| const el = (elementEl.value || '[element]').trim(); |
| const integ = integrationEl.value || 'blends naturally and looks realistic'; |
| const ctx = (contextEl.value || '').trim(); |
| const loc = (locationHintEl.value || '').trim(); |
| |
| let prompt = `Using the provided image, ${t} ${el}, ensuring it ${integ} within the scene.`; |
| const extras = []; |
| if(ctx) extras.push(ctx); |
| if(loc) extras.push(`place near ${loc}`); |
| |
| if(extras.length) { |
| prompt += ` Context: ${extras.join('; ')}.`; |
| } else { |
| prompt += ` Please ensure a photorealistic result.`; |
| } |
| |
| outputEl.value = prompt; |
| } |
| |
| function copyPrompt(){ |
| outputEl.select(); |
| document.execCommand('copy'); |
| const toast = document.createElement('div'); |
| toast.textContent = 'Prompt copied!'; |
| toast.className = 'fixed bottom-6 right-6 px-4 py-2 rounded-xl shadow-lg'; |
| toast.style.cssText = ` |
| background-color: var(--primary-purple); |
| color: white; |
| z-index: 1000; |
| transition: opacity 0.3s; |
| `; |
| document.body.appendChild(toast); |
| setTimeout(() => { |
| toast.style.opacity = '0'; |
| setTimeout(() => toast.remove(), 300); |
| }, 1500); |
| } |
| |
| function downloadPrompt(){ |
| const blob = new Blob([outputEl.value], { type: 'text/plain' }); |
| const url = URL.createObjectURL(blob); |
| const a = document.createElement('a'); |
| a.href = url; |
| a.download = 'image-edit-prompt.txt'; |
| a.click(); |
| URL.revokeObjectURL(url); |
| } |
| |
| function resetAll(){ |
| editTypeEl.value = 'add'; |
| elementEl.value = ''; |
| integrationEl.value = 'blends naturally and looks realistic'; |
| contextEl.value = ''; |
| locationHintEl.value = ''; |
| buildPrompt(); |
| } |
| |
| |
| [editTypeEl, elementEl, integrationEl, contextEl, locationHintEl].forEach(el=>{ |
| el.addEventListener('input', buildPrompt); |
| el.addEventListener('change', buildPrompt); |
| }); |
| |
| copyBtn.addEventListener('click', copyPrompt); |
| copyBtnHeader.addEventListener('click', (e)=>{ e.preventDefault(); copyPrompt(); }); |
| downloadBtn.addEventListener('click', downloadPrompt); |
| |
| if(resetBtn) resetBtn.addEventListener('click', resetAll); |
| |
| |
| buildPrompt(); |
| </script> |
| </body> |
| </html> |