dippoo Claude Opus 4.5 commited on
Commit
b051fff
·
1 Parent(s): 88af028

Clean up UI: smaller controls, better spacing

Browse files

- Narrower controls panel (340px)
- Smaller form elements (6px padding, 12px font)
- Compact chips (4px padding, square corners)
- Smaller drop zones (16px padding, 100px min-height)
- Section dividers with border-top
- Inline character/template selectors in 2-column grid
- Shorter labels and placeholder text
- Compact reference image previews (70px max)
- Better visual hierarchy with cleaner spacing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Files changed (1) hide show
  1. src/content_engine/api/ui.html +94 -98
src/content_engine/api/ui.html CHANGED
@@ -109,13 +109,13 @@ body {
109
  }
110
 
111
  /* --- Page: Generate --- */
112
- .generate-layout { display: grid; grid-template-columns: 380px 1fr; gap: 24px; height: calc(100vh - 56px); }
113
 
114
  .controls-panel {
115
  background: var(--bg-card);
116
  border: 1px solid var(--border);
117
  border-radius: var(--radius);
118
- padding: 20px;
119
  overflow-y: auto;
120
  }
121
 
@@ -129,35 +129,37 @@ body {
129
  }
130
 
131
  .section-title {
132
- font-size: 13px;
133
  font-weight: 600;
134
  text-transform: uppercase;
135
  letter-spacing: 0.5px;
136
  color: var(--text-secondary);
137
- margin-bottom: 10px;
138
- margin-top: 18px;
 
 
139
  }
140
 
141
- .section-title:first-child { margin-top: 0; }
142
 
143
  label {
144
  display: block;
145
- font-size: 12px;
146
  color: var(--text-secondary);
147
- margin-bottom: 5px;
148
- margin-top: 12px;
149
  }
150
 
151
  label:first-of-type { margin-top: 0; }
152
 
153
  select, input[type="text"], input[type="number"], textarea {
154
  width: 100%;
155
- padding: 8px 12px;
156
  background: var(--bg-primary);
157
  border: 1px solid var(--border);
158
- border-radius: 8px;
159
  color: var(--text-primary);
160
- font-size: 13px;
161
  font-family: inherit;
162
  outline: none;
163
  transition: border-color 0.15s;
@@ -165,7 +167,7 @@ select, input[type="text"], input[type="number"], textarea {
165
 
166
  select:focus, input:focus, textarea:focus { border-color: var(--accent); }
167
 
168
- textarea { resize: vertical; min-height: 80px; }
169
 
170
  select { cursor: pointer; }
171
 
@@ -191,11 +193,11 @@ select { cursor: pointer; }
191
  display: inline-flex;
192
  align-items: center;
193
  justify-content: center;
194
- gap: 8px;
195
- padding: 10px 20px;
196
  border: none;
197
- border-radius: 8px;
198
- font-size: 14px;
199
  font-weight: 600;
200
  cursor: pointer;
201
  transition: all 0.15s;
@@ -206,7 +208,7 @@ select { cursor: pointer; }
206
  background: var(--accent);
207
  color: white;
208
  width: 100%;
209
- margin-top: 20px;
210
  }
211
 
212
  .btn-primary:hover { background: var(--accent-hover); box-shadow: 0 0 20px var(--accent-glow); }
@@ -225,16 +227,15 @@ select { cursor: pointer; }
225
  .chips {
226
  display: flex;
227
  flex-wrap: wrap;
228
- gap: 6px;
229
- margin-top: 6px;
230
  }
231
 
232
  .chip {
233
- padding: 5px 12px;
234
  background: var(--bg-primary);
235
  border: 1px solid var(--border);
236
- border-radius: 20px;
237
- font-size: 12px;
238
  cursor: pointer;
239
  transition: all 0.15s;
240
  color: var(--text-secondary);
@@ -340,18 +341,19 @@ select { cursor: pointer; }
340
 
341
  /* File upload drop zone */
342
  .drop-zone {
343
- border: 2px dashed var(--border);
344
- border-radius: var(--radius);
345
- padding: 24px;
346
  text-align: center;
347
  cursor: pointer;
348
  transition: all 0.2s;
349
  color: var(--text-secondary);
350
- margin-top: 8px;
351
  }
352
  .drop-zone:hover, .drop-zone.dragover { border-color: var(--accent); background: rgba(124,58,237,0.05); }
353
  .drop-zone.has-file { border-color: var(--green); background: rgba(34,197,94,0.05); }
354
- .drop-zone img { max-width: 100%; max-height: 120px; border-radius: 8px; margin-top: 8px; }
 
355
 
356
  /* --- Page: Gallery --- */
357
  .gallery-header {
@@ -958,18 +960,18 @@ select { cursor: pointer; }
958
 
959
  <!-- Image to Video settings -->
960
  <div id="img2video-section" style="display:none">
961
- <div class="section-title">Upload Image</div>
962
  <div class="drop-zone" id="video-drop-zone" onclick="document.getElementById('video-file-input').click()">
963
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:32px;height:32px;opacity:0.5;margin-bottom:8px"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
964
- <div>Drop image or click to upload</div>
965
  </div>
966
  <input type="file" id="video-file-input" accept="image/*" style="display:none" onchange="handleVideoImage(this)">
967
- <div id="video-preview" style="display:none; margin-top:8px">
968
- <img id="video-preview-img" style="max-width:100%; border-radius:6px">
969
  </div>
970
 
971
- <div class="section-title" style="margin-top:16px">Video Model</div>
972
- <select id="video-cloud-model" style="margin-top:0">
973
  <optgroup label="Recommended">
974
  <option value="wan-2.6-i2v-pro" selected>WAN 2.6 Pro ($0.05/s)</option>
975
  <option value="wan-2.6-i2v-flash">WAN 2.6 Flash (Fast)</option>
@@ -999,60 +1001,60 @@ select { cursor: pointer; }
999
  </optgroup>
1000
  </select>
1001
 
1002
- <label style="margin-top:12px">Duration</label>
1003
  <select id="video-duration">
1004
- <option value="41">2 seconds</option>
1005
- <option value="81" selected>3 seconds</option>
1006
- <option value="121">5 seconds</option>
1007
- <option value="241">10 seconds</option>
1008
- <option value="361">15 seconds</option>
1009
  </select>
1010
  </div>
1011
 
1012
  <!-- Reference image upload for img2img -->
1013
  <div id="img2img-section" style="display:none">
1014
- <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
 
1015
  <div>
1016
- <div class="section-title">Character Reference</div>
1017
- <div class="drop-zone" id="ref-drop-zone" onclick="document.getElementById('ref-file-input').click()" style="min-height:140px">
1018
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:28px;height:28px;opacity:0.5;margin-bottom:6px"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1019
- <div style="font-size:12px">Drop or click</div>
1020
- <div style="font-size:10px;margin-top:2px;color:var(--text-secondary)">Main subject</div>
1021
  </div>
1022
  <input type="file" id="ref-file-input" accept="image/*" style="display:none" onchange="handleRefImage(this)">
1023
  </div>
1024
  <div>
1025
- <div class="section-title">Pose/Style Reference <span style="font-weight:400;font-size:10px;color:var(--text-secondary)">(optional)</span></div>
1026
- <div class="drop-zone" id="pose-drop-zone" onclick="document.getElementById('pose-file-input').click()" style="min-height:140px">
1027
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:28px;height:28px;opacity:0.5;margin-bottom:6px"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1028
- <div style="font-size:12px">Drop or click</div>
1029
- <div style="font-size:10px;margin-top:2px;color:var(--text-secondary)">Pose or style</div>
1030
  </div>
1031
  <input type="file" id="pose-file-input" accept="image/*" style="display:none" onchange="handlePoseImage(this)">
1032
  </div>
1033
  </div>
1034
- <div style="font-size:11px;color:var(--text-secondary);margin-top:8px">
1035
- Multi-ref models (SeeDream Sequential, Kling O1) use both images for character consistency.
1036
- </div>
1037
- <label style="margin-top:12px">Denoise Strength (0 = keep original, 1 = ignore reference)</label>
1038
  <div class="slider-row">
1039
  <input type="range" id="gen-denoise" min="0" max="1" step="0.05" value="0.65" oninput="this.nextElementSibling.textContent=this.value">
1040
  <span class="value">0.65</span>
1041
  </div>
1042
  </div>
1043
 
1044
- <div class="section-title">Character <span style="font-weight:400;text-transform:none;font-size:11px;color:var(--text-secondary)">(optional)</span></div>
1045
- <select id="gen-character">
1046
- <option value="">None (free prompt)</option>
1047
- </select>
1048
-
1049
  <div id="local-template-select">
1050
- <div class="section-title">Template <span style="font-weight:400;text-transform:none;font-size:11px;color:var(--text-secondary)">(optional - preset prompt recipe)</span></div>
1051
- <select id="gen-template" onchange="loadTemplateVariables()">
1052
- <option value="">None (use prompt below)</option>
1053
- </select>
 
 
 
 
 
 
 
 
 
 
 
1054
 
1055
- <div class="section-title">Content Rating</div>
1056
  <div class="chips" id="content-rating-chips">
1057
  <div class="chip selected" onclick="selectRating(this, 'sfw')">SFW</div>
1058
  <div class="chip" onclick="selectRating(this, 'nsfw')">NSFW</div>
@@ -1062,40 +1064,38 @@ select { cursor: pointer; }
1062
  </div>
1063
 
1064
  <div class="section-title">Prompt</div>
1065
- <label>Positive Prompt</label>
1066
- <textarea id="gen-positive" placeholder="masterpiece, best quality, photorealistic, a woman standing in a garden..."></textarea>
1067
 
1068
- <label>Negative Prompt</label>
1069
  <textarea id="gen-negative" placeholder="worst quality, blurry, deformed..." rows="2"></textarea>
1070
 
1071
  <div id="local-settings-section">
1072
- <div class="section-title">Settings</div>
1073
- <div class="row" style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
1074
  <div>
1075
- <label>Aspect Ratio</label>
1076
  <select id="gen-aspect" onchange="updateDimensions()">
1077
- <option value="9:16" selected>Portrait (9:16)</option>
1078
- <option value="2:3">Portrait (2:3)</option>
1079
- <option value="1:1">Square (1:1)</option>
1080
- <option value="3:2">Landscape (3:2)</option>
1081
- <option value="16:9">Landscape (16:9)</option>
1082
  </select>
1083
  </div>
1084
  <div>
1085
- <label>Seed (-1 = random)</label>
1086
- <input type="number" id="gen-seed" value="-1">
1087
  </div>
1088
  </div>
1089
- <!-- Hidden fields for actual dimensions -->
1090
  <input type="hidden" id="gen-width" value="832">
1091
  <input type="hidden" id="gen-height" value="1216">
1092
- <!-- Advanced settings (collapsed by default) -->
1093
- <details style="margin-top:12px">
1094
- <summary style="cursor:pointer;color:var(--text-secondary);font-size:12px">Advanced Settings</summary>
1095
- <div style="padding-top:8px">
1096
- <div class="row" style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
1097
  <div>
1098
- <label>Steps</label>
1099
  <input type="number" id="gen-steps" value="28">
1100
  </div>
1101
  <div>
@@ -1726,9 +1726,8 @@ function showRefPreview(file) {
1726
  const reader = new FileReader();
1727
  reader.onload = e => {
1728
  zone.innerHTML = `
1729
- <img src="${e.target.result}" style="max-height:100px;max-width:100%;border-radius:4px">
1730
- <div style="margin-top:4px;font-size:11px">${file.name.substring(0,15)}${file.name.length > 15 ? '...' : ''}</div>
1731
- <button class="btn btn-secondary btn-small" onclick="event.stopPropagation();clearRefImage()" style="margin-top:4px;padding:2px 8px;font-size:10px">Remove</button>
1732
  `;
1733
  };
1734
  reader.readAsDataURL(file);
@@ -1739,9 +1738,8 @@ function clearRefImage() {
1739
  const zone = document.getElementById('ref-drop-zone');
1740
  zone.classList.remove('has-file');
1741
  zone.innerHTML = `
1742
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:28px;height:28px;opacity:0.5;margin-bottom:6px"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1743
- <div style="font-size:12px">Drop or click</div>
1744
- <div style="font-size:10px;margin-top:2px;color:var(--text-secondary)">Main subject</div>
1745
  `;
1746
  document.getElementById('ref-file-input').value = '';
1747
  }
@@ -1759,9 +1757,8 @@ function showPosePreview(file) {
1759
  const reader = new FileReader();
1760
  reader.onload = e => {
1761
  zone.innerHTML = `
1762
- <img src="${e.target.result}" style="max-height:100px;max-width:100%;border-radius:4px">
1763
- <div style="margin-top:4px;font-size:11px">${file.name.substring(0,15)}${file.name.length > 15 ? '...' : ''}</div>
1764
- <button class="btn btn-secondary btn-small" onclick="event.stopPropagation();clearPoseImage()" style="margin-top:4px;padding:2px 8px;font-size:10px">Remove</button>
1765
  `;
1766
  };
1767
  reader.readAsDataURL(file);
@@ -1772,9 +1769,8 @@ function clearPoseImage() {
1772
  const zone = document.getElementById('pose-drop-zone');
1773
  zone.classList.remove('has-file');
1774
  zone.innerHTML = `
1775
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" style="width:28px;height:28px;opacity:0.5;margin-bottom:6px"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1776
- <div style="font-size:12px">Drop or click</div>
1777
- <div style="font-size:10px;margin-top:2px;color:var(--text-secondary)">Pose or style</div>
1778
  `;
1779
  document.getElementById('pose-file-input').value = '';
1780
  }
 
109
  }
110
 
111
  /* --- Page: Generate --- */
112
+ .generate-layout { display: grid; grid-template-columns: 340px 1fr; gap: 20px; height: calc(100vh - 56px); }
113
 
114
  .controls-panel {
115
  background: var(--bg-card);
116
  border: 1px solid var(--border);
117
  border-radius: var(--radius);
118
+ padding: 16px;
119
  overflow-y: auto;
120
  }
121
 
 
129
  }
130
 
131
  .section-title {
132
+ font-size: 11px;
133
  font-weight: 600;
134
  text-transform: uppercase;
135
  letter-spacing: 0.5px;
136
  color: var(--text-secondary);
137
+ margin-bottom: 8px;
138
+ margin-top: 20px;
139
+ padding-top: 12px;
140
+ border-top: 1px solid var(--border);
141
  }
142
 
143
+ .section-title:first-child { margin-top: 0; padding-top: 0; border-top: none; }
144
 
145
  label {
146
  display: block;
147
+ font-size: 11px;
148
  color: var(--text-secondary);
149
+ margin-bottom: 4px;
150
+ margin-top: 10px;
151
  }
152
 
153
  label:first-of-type { margin-top: 0; }
154
 
155
  select, input[type="text"], input[type="number"], textarea {
156
  width: 100%;
157
+ padding: 6px 10px;
158
  background: var(--bg-primary);
159
  border: 1px solid var(--border);
160
+ border-radius: 6px;
161
  color: var(--text-primary);
162
+ font-size: 12px;
163
  font-family: inherit;
164
  outline: none;
165
  transition: border-color 0.15s;
 
167
 
168
  select:focus, input:focus, textarea:focus { border-color: var(--accent); }
169
 
170
+ textarea { resize: vertical; min-height: 60px; }
171
 
172
  select { cursor: pointer; }
173
 
 
193
  display: inline-flex;
194
  align-items: center;
195
  justify-content: center;
196
+ gap: 6px;
197
+ padding: 8px 16px;
198
  border: none;
199
+ border-radius: 6px;
200
+ font-size: 13px;
201
  font-weight: 600;
202
  cursor: pointer;
203
  transition: all 0.15s;
 
208
  background: var(--accent);
209
  color: white;
210
  width: 100%;
211
+ margin-top: 16px;
212
  }
213
 
214
  .btn-primary:hover { background: var(--accent-hover); box-shadow: 0 0 20px var(--accent-glow); }
 
227
  .chips {
228
  display: flex;
229
  flex-wrap: wrap;
230
+ gap: 4px;
 
231
  }
232
 
233
  .chip {
234
+ padding: 4px 10px;
235
  background: var(--bg-primary);
236
  border: 1px solid var(--border);
237
+ border-radius: 4px;
238
+ font-size: 11px;
239
  cursor: pointer;
240
  transition: all 0.15s;
241
  color: var(--text-secondary);
 
341
 
342
  /* File upload drop zone */
343
  .drop-zone {
344
+ border: 1px dashed var(--border);
345
+ border-radius: 8px;
346
+ padding: 16px 12px;
347
  text-align: center;
348
  cursor: pointer;
349
  transition: all 0.2s;
350
  color: var(--text-secondary);
351
+ font-size: 11px;
352
  }
353
  .drop-zone:hover, .drop-zone.dragover { border-color: var(--accent); background: rgba(124,58,237,0.05); }
354
  .drop-zone.has-file { border-color: var(--green); background: rgba(34,197,94,0.05); }
355
+ .drop-zone img { max-width: 100%; max-height: 80px; border-radius: 6px; margin-top: 6px; }
356
+ .drop-zone svg { width: 24px; height: 24px; opacity: 0.4; margin-bottom: 4px; }
357
 
358
  /* --- Page: Gallery --- */
359
  .gallery-header {
 
960
 
961
  <!-- Image to Video settings -->
962
  <div id="img2video-section" style="display:none">
963
+ <div class="section-title">Source Image</div>
964
  <div class="drop-zone" id="video-drop-zone" onclick="document.getElementById('video-file-input').click()">
965
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
966
+ <div>Drop or click to upload</div>
967
  </div>
968
  <input type="file" id="video-file-input" accept="image/*" style="display:none" onchange="handleVideoImage(this)">
969
+ <div id="video-preview" style="display:none; margin-top:6px">
970
+ <img id="video-preview-img" style="max-width:100%; max-height:100px; border-radius:6px">
971
  </div>
972
 
973
+ <label style="margin-top:12px">Video Model</label>
974
+ <select id="video-cloud-model">
975
  <optgroup label="Recommended">
976
  <option value="wan-2.6-i2v-pro" selected>WAN 2.6 Pro ($0.05/s)</option>
977
  <option value="wan-2.6-i2v-flash">WAN 2.6 Flash (Fast)</option>
 
1001
  </optgroup>
1002
  </select>
1003
 
1004
+ <label>Duration</label>
1005
  <select id="video-duration">
1006
+ <option value="41">2s</option>
1007
+ <option value="81" selected>3s</option>
1008
+ <option value="121">5s</option>
1009
+ <option value="241">10s</option>
1010
+ <option value="361">15s</option>
1011
  </select>
1012
  </div>
1013
 
1014
  <!-- Reference image upload for img2img -->
1015
  <div id="img2img-section" style="display:none">
1016
+ <div class="section-title">Reference Images</div>
1017
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
1018
  <div>
1019
+ <div class="drop-zone" id="ref-drop-zone" onclick="document.getElementById('ref-file-input').click()" style="min-height:100px">
1020
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1021
+ <div>Character</div>
 
 
1022
  </div>
1023
  <input type="file" id="ref-file-input" accept="image/*" style="display:none" onchange="handleRefImage(this)">
1024
  </div>
1025
  <div>
1026
+ <div class="drop-zone" id="pose-drop-zone" onclick="document.getElementById('pose-file-input').click()" style="min-height:100px">
1027
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1028
+ <div>Pose <span style="color:var(--text-secondary)">(opt)</span></div>
 
 
1029
  </div>
1030
  <input type="file" id="pose-file-input" accept="image/*" style="display:none" onchange="handlePoseImage(this)">
1031
  </div>
1032
  </div>
1033
+ <label style="margin-top:10px">Denoise (0=keep, 1=ignore ref)</label>
 
 
 
1034
  <div class="slider-row">
1035
  <input type="range" id="gen-denoise" min="0" max="1" step="0.05" value="0.65" oninput="this.nextElementSibling.textContent=this.value">
1036
  <span class="value">0.65</span>
1037
  </div>
1038
  </div>
1039
 
 
 
 
 
 
1040
  <div id="local-template-select">
1041
+ <div class="section-title">Character & Template</div>
1042
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px">
1043
+ <div>
1044
+ <label style="margin-top:0">Character</label>
1045
+ <select id="gen-character">
1046
+ <option value="">None</option>
1047
+ </select>
1048
+ </div>
1049
+ <div>
1050
+ <label style="margin-top:0">Template</label>
1051
+ <select id="gen-template" onchange="loadTemplateVariables()">
1052
+ <option value="">None</option>
1053
+ </select>
1054
+ </div>
1055
+ </div>
1056
 
1057
+ <label>Rating</label>
1058
  <div class="chips" id="content-rating-chips">
1059
  <div class="chip selected" onclick="selectRating(this, 'sfw')">SFW</div>
1060
  <div class="chip" onclick="selectRating(this, 'nsfw')">NSFW</div>
 
1064
  </div>
1065
 
1066
  <div class="section-title">Prompt</div>
1067
+ <label style="margin-top:0">Positive</label>
1068
+ <textarea id="gen-positive" placeholder="masterpiece, best quality, photorealistic..." rows="3"></textarea>
1069
 
1070
+ <label>Negative</label>
1071
  <textarea id="gen-negative" placeholder="worst quality, blurry, deformed..." rows="2"></textarea>
1072
 
1073
  <div id="local-settings-section">
1074
+ <div class="section-title">Output Settings</div>
1075
+ <div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
1076
  <div>
1077
+ <label style="margin-top:0">Aspect</label>
1078
  <select id="gen-aspect" onchange="updateDimensions()">
1079
+ <option value="9:16" selected>9:16</option>
1080
+ <option value="2:3">2:3</option>
1081
+ <option value="1:1">1:1</option>
1082
+ <option value="3:2">3:2</option>
1083
+ <option value="16:9">16:9</option>
1084
  </select>
1085
  </div>
1086
  <div>
1087
+ <label style="margin-top:0">Seed</label>
1088
+ <input type="number" id="gen-seed" value="-1" placeholder="-1 = random">
1089
  </div>
1090
  </div>
 
1091
  <input type="hidden" id="gen-width" value="832">
1092
  <input type="hidden" id="gen-height" value="1216">
1093
+ <details style="margin-top:10px">
1094
+ <summary style="cursor:pointer;color:var(--text-secondary);font-size:11px">Advanced</summary>
1095
+ <div style="padding-top:6px">
1096
+ <div style="display:grid; grid-template-columns:1fr 1fr; gap:8px;">
 
1097
  <div>
1098
+ <label style="margin-top:0">Steps</label>
1099
  <input type="number" id="gen-steps" value="28">
1100
  </div>
1101
  <div>
 
1726
  const reader = new FileReader();
1727
  reader.onload = e => {
1728
  zone.innerHTML = `
1729
+ <img src="${e.target.result}" style="max-height:70px;max-width:100%;border-radius:4px">
1730
+ <button class="btn btn-secondary" onclick="event.stopPropagation();clearRefImage()" style="margin-top:4px;padding:2px 6px;font-size:9px">Remove</button>
 
1731
  `;
1732
  };
1733
  reader.readAsDataURL(file);
 
1738
  const zone = document.getElementById('ref-drop-zone');
1739
  zone.classList.remove('has-file');
1740
  zone.innerHTML = `
1741
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1742
+ <div>Character</div>
 
1743
  `;
1744
  document.getElementById('ref-file-input').value = '';
1745
  }
 
1757
  const reader = new FileReader();
1758
  reader.onload = e => {
1759
  zone.innerHTML = `
1760
+ <img src="${e.target.result}" style="max-height:70px;max-width:100%;border-radius:4px">
1761
+ <button class="btn btn-secondary" onclick="event.stopPropagation();clearPoseImage()" style="margin-top:4px;padding:2px 6px;font-size:9px">Remove</button>
 
1762
  `;
1763
  };
1764
  reader.readAsDataURL(file);
 
1769
  const zone = document.getElementById('pose-drop-zone');
1770
  zone.classList.remove('has-file');
1771
  zone.innerHTML = `
1772
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
1773
+ <div>Pose <span style="color:var(--text-secondary)">(opt)</span></div>
 
1774
  `;
1775
  document.getElementById('pose-file-input').value = '';
1776
  }