[object Object]

← 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

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,'&lt;')}</span>`);
+  if(base) cues.push(`<span class="cue" title="category base" style="background:#2a2a2a;color:#bbb">${base.replace(/</g,'&lt;')}</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,'&lt;').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 →