← back to Wallco Ai
drunk-curator: richer ID cues — density tier, subject+emoji, generator badge, colorway, top-N rank, freshness chip
041d703c691378df10459488269d6b694a11803f · 2026-05-28 05:56:48 -0700 · Steve Abrams
Files touched
M public/admin/drunk-curator.html
Diff
commit 041d703c691378df10459488269d6b694a11803f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu May 28 05:56:48 2026 -0700
drunk-curator: richer ID cues — density tier, subject+emoji, generator badge, colorway, top-N rank, freshness chip
---
public/admin/drunk-curator.html | 83 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 81 insertions(+), 2 deletions(-)
diff --git a/public/admin/drunk-curator.html b/public/admin/drunk-curator.html
index a9c69c6..1e1c575 100644
--- a/public/admin/drunk-curator.html
+++ b/public/admin/drunk-curator.html
@@ -42,7 +42,25 @@
.repbadge{position:absolute;top:8px;right:10px;z-index:7;background:rgba(0,0,0,.62);color:#fff;font:800 10px sans-serif;padding:3px 9px;border-radius:20px;}
.baseboard{position:absolute;left:0;right:0;bottom:24%;height:3.2%;background:#efe9df;border-top:1px solid rgba(0,0,0,.12);box-shadow:0 2px 5px rgba(0,0,0,.18);}
.furn{position:absolute;left:50%;bottom:24%;transform:translateX(-50%);width:64%;z-index:2;filter:drop-shadow(0 8px 14px rgba(0,0,0,.32));}
- .meta{display:flex;justify-content:space-between;width:min(96vw,1100px);font-size:11.5px;color:var(--mut);font-variant-numeric:tabular-nums;}
+ .meta{display:flex;justify-content:space-between;align-items:center;width:min(96vw,1100px);font-size:11.5px;color:var(--mut);font-variant-numeric:tabular-nums;}
+ /* ID-cue chips — let Steve sort the queue by eye: density, subject, generator, colorway */
+ .cues{display:flex;flex-wrap:wrap;gap:6px;align-items:center;}
+ .cue{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:11px;font:600 11px ui-sans-serif,sans-serif;color:#fff;background:#3a3a3a;letter-spacing:.02em;}
+ .cue.id{background:#222;color:#cfcfcf;font-weight:700;}
+ .cue.n-hi{background:#d23a1a;} /* n>=20 — fully wallpaper-density */
+ .cue.n-md{background:#c98a00;} /* 10..19 — solid all-over */
+ .cue.n-lo{background:#6b7280;} /* 3..9 — borderline */
+ .cue.n-none{background:#444;color:#999;}
+ .cue.gen-comfy{background:#2e6f5c;}
+ .cue.gen-replicate{background:#6d4caa;}
+ .cue.gen-bgswap{background:#2c6fbf;}
+ .cue.gen-smartfix{background:#a83232;}
+ .cue.gen-gemini{background:#1976d2;}
+ .cue.gen-other{background:#555;}
+ .cue.subj{background:#1a1a1a;color:#fff;border:1px solid #444;}
+ .cue.colorway{background:#3a2440;color:#f0d8f0;}
+ .cue.fresh{background:#0b6d3a;} /* created within the last 24h — fresh-gen flag */
+ .cue.rank-top{background:#b5891a;color:#1a1a1a;} /* top-20 by density in the current queue */
.prompt{font-size:11px;color:var(--mut);width:min(96vw,1100px);max-height:30px;overflow:hidden;text-align:center;cursor:pointer;}
.prompt.open{max-height:none;}
.btns{display:flex;gap:18px;}
@@ -361,6 +379,67 @@ new MutationObserver(()=>{
function go(delta){ if(busy) return; const ni=i+delta; if(ni<0||ni>QUEUE.length) return; i=ni; render(); }
let autoIdOn = localStorage.getItem('drunk_autoid')==='1'; // Auto-ID is OPT-IN (off by default — saves Gemini cost)
function fmtDate(iso){ if(!iso)return''; try{return new Date(iso).toLocaleString(undefined,{month:'short',day:'numeric',hour:'numeric',minute:'2-digit'});}catch{return iso;} }
+// At-a-glance ID cues: density, subject, generator, colorway, freshness, rank.
+const ANIMAL_EMOJI = {monkey:'🐒',monkeys:'🐒',zebra:'🦓',giraffe:'🦒',lion:'🦁',tiger:'🐅',elephant:'🐘',panda:'🐼',koala:'🐨',bear:'🐻',fox:'🦊',owl:'🦉',octopus:'🐙',sloth:'🦥',rabbit:'🐇',bunny:'🐇',penguin:'🐧',dog:'🐕',cat:'🐈',frog:'🐸',cow:'🐄',pig:'🐖',sheep:'🐑',horse:'🐎',deer:'🦌',flamingo:'🦩',parrot:'🦜',toucan:'🦜',cheetah:'🐆',leopard:'🐆',moose:'🫎',raccoon:'🦝',skunk:'🦨',hedgehog:'🦔',otter:'🦦',squirrel:'🐿',bat:'🦇',shark:'🦈',whale:'🐳',dolphin:'🐬',crab:'🦀',lobster:'🦞',butterfly:'🦋',bee:'🐝',snail:'🐌',hippo:'🦛',rhino:'🦏',camel:'🐪',llama:'🦙',kangaroo:'🦘',badger:'🦡',crocodile:'🐊',turtle:'🐢',snake:'🐍',lizard:'🦎',cactus:'🌵',unicorn:'🦄'};
+function pickSubject(prompt){
+ if(!prompt) return null;
+ const p = prompt.toLowerCase();
+ for(const k of Object.keys(ANIMAL_EMOJI)){
+ if(new RegExp('\\b'+k+'\\b').test(p)) return {name:k, emoji:ANIMAL_EMOJI[k]};
+ }
+ return null;
+}
+function splitCategory(cat){
+ if(!cat) return {base:'', colorway:''};
+ const parts = String(cat).split('·').map(s=>s.trim()).filter(Boolean);
+ return {base: parts[0]||'', colorway: parts.slice(1).join(' · ')||''};
+}
+function genClass(gen){
+ const g = String(gen||'').toLowerCase();
+ if(g.includes('comfy')) return 'gen-comfy';
+ if(g.includes('replicate')) return 'gen-replicate';
+ if(g.includes('bgswap')) return 'gen-bgswap';
+ if(g.includes('smartfix')||g.includes('midheal')||g.includes('edgeheal')) return 'gen-smartfix';
+ if(g.includes('gemini')) return 'gen-gemini';
+ return 'gen-other';
+}
+function genLabel(gen){
+ const g = String(gen||'').toLowerCase();
+ if(g.includes('comfy')) return 'comfy';
+ if(g.includes('replicate-fast')) return 'repl·fast';
+ if(g.includes('replicate')) return 'repl';
+ if(g.includes('bgswap')) return 'bgswap';
+ if(g.includes('smartfix')) return 'smartfix';
+ if(g.includes('midheal')) return 'mid-heal';
+ if(g.includes('edgeheal')) return 'edge-heal';
+ if(g.includes('gemini')) return 'gemini';
+ return (gen||'?').slice(0,12);
+}
+function nClass(n){
+ if(n==null) return 'n-none';
+ if(n>=20) return 'n-hi';
+ if(n>=10) return 'n-md';
+ return 'n-lo';
+}
+function isFresh(iso){
+ if(!iso) return false;
+ try { return (Date.now() - new Date(iso).getTime()) < 24*3600*1000; } catch { return false; }
+}
+function buildCues(d, idx){
+ const subj = pickSubject(d.prompt);
+ const {base, colorway} = splitCategory(d.category);
+ const n = d.auto_hot_n;
+ const cues = [];
+ cues.push(`<span class="cue id" title="design id">#${d.id}</span>`);
+ if(idx < 20) cues.push(`<span class="cue rank-top" title="top-20 by density in this queue">★ top ${idx+1}</span>`);
+ cues.push(`<span class="cue ${nClass(n)}" title="triage instance-count (Gemini composition gate)">🔢 n=${n!=null?n:'—'}</span>`);
+ if(subj) cues.push(`<span class="cue subj" title="subject (parsed from prompt)">${subj.emoji} ${subj.name}</span>`);
+ cues.push(`<span class="cue ${genClass(d.generator)}" title="generator: ${d.generator||'?'}">${genLabel(d.generator)}</span>`);
+ if(colorway) cues.push(`<span class="cue colorway" title="colorway">🎨 ${colorway.replace(/</g,'<')}</span>`);
+ if(base) cues.push(`<span class="cue" title="category base" style="background:#2a2a2a;color:#bbb">${base.replace(/</g,'<')}</span>`);
+ if(isFresh(d.created_at)) cues.push(`<span class="cue fresh" title="created in the last 24h">✨ fresh</span>`);
+ return cues.join('');
+}
function flash(e){ const f=$('#flash'); f.textContent=e; f.classList.add('show'); setTimeout(()=>f.classList.remove('show'),250); }
function render(){
$('#seen').textContent=hot+not; $('#hot').textContent=hot; $('#not').textContent=not;
@@ -405,7 +484,7 @@ function render(){
<span><b id="scalenum">${scaleInches}</b>″ repeat · ruler in inches</span>
<span style="margin-left:18px">🧱 Wall <input type="range" id="wallslider" min="96" max="216" step="6" value="${WALL_INCHES}" oninput="setWallInches(this.value)" style="width:130px;accent-color:var(--hot);vertical-align:middle"> <b id="wallval">${(WALL_INCHES/12).toFixed(WALL_INCHES%12?1:0)}′</b></span>
</div>
- <div class="meta"><span>#${d.id} · ${d.category||''}</span><span>🕓 ${fmtDate(d.created_at)}</span></div>
+ <div class="meta"><span class="cues">${buildCues(d, i)}</span><span title="${d.created_at||''}">🕓 ${fmtDate(d.created_at)}</span></div>
<div class="prompt" onclick="this.classList.toggle('open')">${(d.prompt||'').replace(/</g,'<').slice(0,240)}</div>
<div class="nav"><button class="navb" onclick="go(-1)" ${i<=0?'disabled':''}>‹ Prev</button><span class="pos">${i+1} / ${QUEUE.length}${decided[d.id]?' · '+decided[d.id]:''}</span><button class="navb" onclick="go(1)" ${i>=QUEUE.length-1?'disabled':''}>Next ›</button></div>
<div class="btns"><button class="hot" onclick="decide('hot')">🔥 HOT</button><button class="fix" onclick="decide('fix')">🔧 Fix</button><button class="not" onclick="decide('not')">🗑 Trash</button><button class="extract" onclick="extract()">✂️ Extract</button></div>
← 5a5d6f7 seam-debug: localize ALL joints (4 edge-wrap pairs + 2 inter
·
back to Wallco Ai
·
cactus-curator: gate-held → 200 park (was 422 dropping vote, 37d5e6d →