[object Object]

← back to Wallco Ai

curator A1: HSB Adjust presets (Neutral/Vivid/Muted/Warm/Cool/B&W) with exclusive active-chip highlight

b02506fd78c5cfa3b12fb7367537b329518285f7 · 2026-05-31 21:06:23 -0700 · Steve Abrams

Files touched

Diff

commit b02506fd78c5cfa3b12fb7367537b329518285f7
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sun May 31 21:06:23 2026 -0700

    curator A1: HSB Adjust presets (Neutral/Vivid/Muted/Warm/Cool/B&W) with exclusive active-chip highlight
---
 YOLO_BACKLOG_2026-05-31.md       | 38 ++++++++++++++++++++++++++++++++++++++
 public/admin/cactus-curator.html | 39 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/YOLO_BACKLOG_2026-05-31.md b/YOLO_BACKLOG_2026-05-31.md
new file mode 100644
index 0000000..4a281dc
--- /dev/null
+++ b/YOLO_BACKLOG_2026-05-31.md
@@ -0,0 +1,38 @@
+# YOLO loop backlog — 2026-05-31 overnight · Curator Adjust/Bake hardening
+
+Focus (DTD verdict A, 2/2): **deepen tonight's new curator HSB+contrast Adjust/Bake feature.**
+Self-contained in `public/admin/cactus-curator.html` — zero `server.js` risk, fully reversible.
+
+## Standing rules (per `feedback_yolo_overnight_rules` + global "approvals → ask up front")
+
+- ScheduleWakeup @ ~1800s pacing
+- `/dtd` decides any judgment-call fork
+- LOCAL git commits only — one logical commit per item
+- **PARK anything gated** (deploy to prod, publish, DB deletes, sends, spend, DNS, pushes) → write to `~/.claude/yolo-queue/pending-approval/`, never execute unattended
+- Each tick reversible + idempotent (re-check done before re-running)
+- **Validation-loop mandatory** — after each edit: extract inline JS → `node -c`, curl the local page, confirm markup served, before marking `[x]`
+- Deploy of the night's accumulated curator commits = ONE parked item for Steve's morning approval
+
+## Backlog (prioritized)
+
+- [x] **A1 · Adjustment presets** — browser-verified (Vivid sat1.40 / B&W sat0 / Neutral→none, chips exclusive) — preset chips in the panel (Vivid / Muted / Warm / Cool / B&W / Neutral) that set the four sliders to curated HSB+contrast combos; persists like the sliders.
+- [ ] **A2 · Percent readouts** — show the real filter math next to each slider (e.g. `Sat 158 · 124%`, `Hue +18°`, `Con 100%`) so the value is legible, not just the raw 0–255.
+- [ ] **A3 · Live before/after chip** — a small sample swatch in the panel showing the current design (or a representative card) with vs without the filter, updating live as sliders move.
+- [ ] **A4 · Apply filter to family-stack images** — the `--img-adjust` filter currently hits `#grid img` + `#modal img`; extend to `#bbstack img` so the by-base colorway stack previews the adjustment too.
+- [ ] **A5 · Per-card Bake from grid** — a hover "⤓ Bake" affordance on each card that bakes the current adjustment for that design without opening the modal (reuses `bakeAdjustment`).
+- [ ] **A6 · Copy-filter-CSS dev aid** — a tiny "copy CSS" button that copies the current `filter:` string to clipboard (useful for porting the look elsewhere).
+- [ ] **A7 · Bake confirmation guard** — when baking, if the adjustment is extreme (e.g. saturate >2× or brightness <0.5×), show a one-line "looks extreme — bake anyway?" inline confirm before POSTing, to avoid accidental wild bakes.
+- [ ] **A8 · Reset-all + keyboard** — `0` key (when panel open) resets to neutral; `[`/`]` nudge the focused slider; document in the panel's note line.
+
+## Parked-for-Steve (created by the loop as items arise)
+- Deploy the night's curator commits to prod (`scp public/admin/cactus-curator.html`) — gated, morning approval.
+
+## Stop condition
+When all `[ ]` are `[x]`: author 2–3 further safe refinement items via `/dtd`, or if genuinely exhausted, write a session-recap memory entry and stop scheduling.
+
+## Ledger
+```
+TICK · TIMESTAMP · ITEM · STATUS · COMMIT
+```
+- T0 · 2026-05-31 21:02 · loop-init (DTD focus=A) · scheduled · n/a
+- T1 · 2026-05-31 21:05 · A1 presets · done · (commit below)
diff --git a/public/admin/cactus-curator.html b/public/admin/cactus-curator.html
index b683955..60436b8 100644
--- a/public/admin/cactus-curator.html
+++ b/public/admin/cactus-curator.html
@@ -175,6 +175,10 @@
   #adjPanel .adj input[type=range] { width:120px; }
   #adjPanel .adjval { display:inline-block; min-width:34px; text-align:right; color:var(--ink); font-variant-numeric:tabular-nums; }
   #adjPanel .adjnote { font-size:11px; color:var(--mut); }
+  #adjPanel .adj-presets { display:flex; gap:5px; align-items:center; }
+  #adjPanel .adj-preset { font:600 11px inherit; padding:4px 9px; border-radius:6px; border:1px solid var(--line); background:#1d2023; color:var(--ink); cursor:pointer; }
+  #adjPanel .adj-preset:hover { border-color:var(--accent); }
+  #adjPanel .adj-preset.on { background:#1f3a4d; color:#7fe3ff; border-color:#1f4a5a; }
   #adjToggle.on { background:#1f4d2a; color:#9ff0a6; border-color:#1f4d2a; }
   #grid img, #modal img { filter: var(--img-adjust, none); }
 </style>
@@ -226,6 +230,14 @@
   <label class="adj">Sat <input type="range" id="adjSat" min="0" max="255" step="1"><span class="adjval" id="adjSatV"></span></label>
   <label class="adj">Bri <input type="range" id="adjBri" min="0" max="255" step="1"><span class="adjval" id="adjBriV"></span></label>
   <label class="adj">Con <input type="range" id="adjCon" min="0" max="200" step="1"><span class="adjval" id="adjConV"></span></label>
+  <span class="adj-presets" id="adjPresets" title="quick-apply curated HSB+contrast combos">
+    <button class="adj-preset" data-preset="neutral">Neutral</button>
+    <button class="adj-preset" data-preset="vivid">Vivid</button>
+    <button class="adj-preset" data-preset="muted">Muted</button>
+    <button class="adj-preset" data-preset="warm">Warm</button>
+    <button class="adj-preset" data-preset="cool">Cool</button>
+    <button class="adj-preset" data-preset="bw">B&amp;W</button>
+  </span>
   <button id="adjReset" class="ctl-btn" title="back to neutral (Hue 127 · Sat 127 · Bri 127 · Con 100)">Reset</button>
   <span class="adjnote">live preview only — non-destructive, doesn't touch the stored image</span>
 </div>
@@ -1660,6 +1672,7 @@ load();
     var neutral = (s.hue===NEUTRAL.hue && s.sat===NEUTRAL.sat && s.bri===NEUTRAL.bri && s.con===NEUTRAL.con);
     document.documentElement.style.setProperty('--img-adjust', neutral ? 'none' : filterStr(s));
     for (var k in ids){ var r=el(ids[k]); if(r){ r.value=s[k]; } var v=el(ids[k]+'V'); if(v){ v.textContent=s[k]; } }
+    if (typeof markActivePreset === 'function') markActivePreset();
   }
   function bind(k){
     var r = el(ids[k]); if(!r) return;
@@ -1676,10 +1689,34 @@ load();
       return filterStr(s);
     }
   };
+  // A1 — curated presets (neutral = hue127/sat127/bri127/con100).
+  var PRESETS = {
+    neutral: { hue:127, sat:127, bri:127, con:100 },
+    vivid:   { hue:127, sat:178, bri:132, con:118 },
+    muted:   { hue:127, sat:92,  bri:126, con:92  },
+    warm:    { hue:110, sat:148, bri:131, con:106 },
+    cool:    { hue:150, sat:140, bri:124, con:106 },
+    bw:      { hue:127, sat:0,   bri:128, con:112 }
+  };
+  function markActivePreset(){
+    var v = { hue:get('hue'), sat:get('sat'), bri:get('bri'), con:get('con') };
+    document.querySelectorAll('#adjPresets .adj-preset').forEach(function(b){
+      var p = PRESETS[b.getAttribute('data-preset')];
+      b.classList.toggle('on', !!p && p.hue===v.hue && p.sat===v.sat && p.bri===v.bri && p.con===v.con);
+    });
+  }
+  function applyPreset(name){
+    var p = PRESETS[name]; if(!p) return;
+    for (var k in p) set(k, p[k]);
+    apply(); markActivePreset();
+  }
   function init(){
     for (var k in ids) bind(k);
+    document.querySelectorAll('#adjPresets .adj-preset').forEach(function(b){
+      b.addEventListener('click', function(){ applyPreset(b.getAttribute('data-preset')); });
+    });
     var reset = el('adjReset');
-    if (reset) reset.addEventListener('click', function(){ for (var k in NEUTRAL) set(k, NEUTRAL[k]); apply(); });
+    if (reset) reset.addEventListener('click', function(){ for (var k in NEUTRAL) set(k, NEUTRAL[k]); apply(); markActivePreset(); });
     var panel = el('adjPanel'), toggle = el('adjToggle');
     function show(on){
       if (panel) panel.classList.toggle('on', on);

← 51134a8 dogs cohort review — 214 breed-aware title renames (--no-ver  ·  back to Wallco Ai  ·  curator A2: show derived filter math next to each slider (hu 7431b12 →