[object Object]

← back to Wallco Ai

wallco.ai: /designs cards show DW SKU + color name + AI-Designed badge + style; density slider 1-12 default 6; wisteria-animals prompt library

f582e1231b34393a8fd73d4e08bbf0f0f2dc854e · 2026-05-13 11:59:20 -0700 · SteveStudio2

Files touched

Diff

commit f582e1231b34393a8fd73d4e08bbf0f0f2dc854e
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 13 11:59:20 2026 -0700

    wallco.ai: /designs cards show DW SKU + color name + AI-Designed badge + style; density slider 1-12 default 6; wisteria-animals prompt library
---
 public/css/site.css                |  61 ++++++++++--
 scripts/wisteria_animal_prompts.js | 192 +++++++++++++++++++++++++++++++++++++
 server.js                          |  25 ++++-
 3 files changed, 269 insertions(+), 9 deletions(-)

diff --git a/public/css/site.css b/public/css/site.css
index 5b1b3e5..7a7e3cd 100644
--- a/public/css/site.css
+++ b/public/css/site.css
@@ -287,7 +287,7 @@ main { padding-top: 73px; }
   padding: 24px 12px 40px;     /* tight side gutters — cards stretch wider */
 }
 .featured-grid { --cols: 4; }
-.catalog-grid  { --cols: var(--cols, 3); }    /* default to 3-up (wider cards) */
+.catalog-grid  { --cols: var(--cols, 6); }    /* default 6-up; density slider runs 1–12 */
 
 .design-card {
   display: block;
@@ -361,19 +361,66 @@ main { padding-top: 73px; }
 
 .card-meta {
   display: flex;
-  align-items: center;
-  gap: 8px;
-  padding: 10px 12px;
+  flex-direction: column;
+  align-items: stretch;
+  gap: 3px;
+  padding: 8px 10px 10px;
   border-top: 1px solid var(--line);
 }
 .card-title {
-  flex: 1;
   font-family: var(--serif);
   font-size: 13px;
   color: var(--ink);
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
+  line-height: 1.2;
+}
+.card-sku {
+  font: 9px/1 ui-monospace, Menlo, monospace;
+  letter-spacing: 0.06em;
+  color: var(--ink-faint);
+  text-transform: uppercase;
+}
+.card-colorname {
+  display: inline-flex;
+  align-items: center;
+  gap: 5px;
+  font-size: 10px;
+  color: var(--ink-soft, #555);
+  text-transform: capitalize;
+  line-height: 1.2;
+}
+.card-hex {
+  font: 9px/1 ui-monospace, Menlo, monospace;
+  color: var(--ink-faint);
+  letter-spacing: 0.04em;
+}
+.card-tags {
+  display: inline-flex;
+  align-items: center;
+  gap: 5px;
+  flex-wrap: wrap;
+  margin-top: 2px;
+}
+.card-ai-badge {
+  display: inline-block;
+  font: 600 8.5px/1 var(--sans, system-ui);
+  letter-spacing: 0.07em;
+  text-transform: uppercase;
+  color: var(--accent, #0d0d0d);
+  background: var(--gold, #c9a14b);
+  padding: 3px 6px 2px;
+  border-radius: 3px;
+}
+.card-style {
+  font: 9px/1 var(--sans, system-ui);
+  letter-spacing: 0.07em;
+  text-transform: uppercase;
+  color: var(--ink-faint);
+  padding: 3px 6px 2px;
+  border: 1px solid var(--line);
+  border-radius: 3px;
 }
 .card-cat {
   font-size: 10px;
@@ -382,10 +429,12 @@ main { padding-top: 73px; }
   color: var(--ink-faint);
 }
 .color-dot {
-  width: 10px; height: 10px;
+  width: 9px; height: 9px;
   border-radius: 50%;
   flex-shrink: 0;
   border: 1px solid var(--line);
+  display: inline-block;
+  vertical-align: middle;
 }
 
 /* ── CTA BAND */
diff --git a/scripts/wisteria_animal_prompts.js b/scripts/wisteria_animal_prompts.js
new file mode 100644
index 0000000..8b09273
--- /dev/null
+++ b/scripts/wisteria_animal_prompts.js
@@ -0,0 +1,192 @@
+#!/usr/bin/env node
+/**
+ * Wisteria + drunk/stoned animals prompt library — drinking animals hanging
+ * from cascading wisteria racemes with bamboo-leaf canopy. All animals MUST
+ * face UP (chin tipped toward sky / racemes / leaf canopy). Inherits the
+ * butterfly-trellis aesthetic palette (heritage botanical, refined, no Warhol
+ * neon) rather than the pop-art drunk-animals palette.
+ *
+ * IMPORTANT — legal note: drunk-animals had a standing FLOWERS-ONLY rule
+ * ("NO leaves, NO foliage, NO bamboo") to dodge Hinson/Cole banana-leaf
+ * trademark waters. This brief intentionally overrides that with BAMBOO
+ * LEAVES + WISTERIA at Steve's direction. Bamboo-leaf prints are non-
+ * trademarkable as a motif so the risk is low, but anything resembling
+ * an existing commercial pattern (Schumacher Chiang Mai, Hinson
+ * Beverly Hills Banana, Brunschwig Le Singe) needs designer eyes
+ * before publish. Generator outputs go in as is_published=false until
+ * a human approves.
+ *
+ * Used by:
+ *   - scripts/generate-wisteria-animals-batch.js  (10 hand-curated designs)
+ *   - direct CLI: node scripts/wisteria_animal_prompts.js 100  (dump 100 ideas)
+ */
+
+// Drinking states — drunk = sloshed/swaying, stoned = blissed-out/half-lidded.
+// All tableaux force "face/chin tipped UP toward the racemes" because the
+// brief is non-negotiable on that.
+const DRUNK_TABLEAUX = [
+  'chin tipped up to the racemes, mouth wide, mid-guzzle from a long-stemmed wine glass — burgundy sloshing down its throat',
+  'face turned skyward, draining a frosted vodka bottle held in both paws, condensation dripping onto its chest',
+  'looking straight up at the wisteria, mid-toast with a champagne flute, golden bubbles cascading',
+  'head tilted back, gulping from an emerald-green beer bottle, foam sliding down its chin',
+  'gazing up through the petals, sipping rosé from a coupe glass, pink liquid clinging to its lip',
+  'mouth agape toward the canopy, pouring a martini directly into its open jaw, two olives mid-air',
+  'snout aimed at the sky, draining a crystal whiskey tumbler, last amber drops trailing',
+  'chin up, both paws gripping a tequila bottle, lime wedge falling from its lips',
+  'tipsy, head lolled back staring at racemes, half-empty cognac snifter dangling',
+  'face skyward, mid-swig from a stout pint, cream head smeared across its muzzle',
+];
+
+const STONED_TABLEAUX = [
+  'eyes half-closed and turned upward to the racemes, slow contented sip from a coupe glass',
+  'face beatifically upturned to the canopy, slow-motion drink from a wine glass, dreamy smile',
+  'chin lifted toward the petals, blissed-out, savoring a slow pour of amber whiskey down its throat',
+  'eyes lidded, gazing up through the wisteria, languid sip from a tall pilsner',
+  'mellow, head tilted back, slow guzzle from a frosted vodka bottle, deeply at peace',
+  'face dreamily upturned, sucking on a long curly straw rooted in a magnum of champagne',
+  'eyes soft and skyward, savoring a slow sip from a martini glass, cheeks rosy',
+  'tranquil, gazing up, both paws hugging a bottle of rosé tipped into its mouth',
+  'mouth lazily open to the racemes, slow sip from a cognac snifter, blissful trance',
+  'eyes closed, chin up, contented sigh mid-sip from a champagne flute',
+];
+
+// Wisteria-only botanical anchors, varied by color. Bamboo leaves are added
+// separately in BAMBOO_LAYER so each prompt always carries both.
+const WISTERIA_COLORS = [
+  'cascading lavender-purple wisteria racemes, dense pendulous clusters',
+  'pale-blush pink wisteria racemes, soft and ethereal',
+  'deep amethyst wisteria racemes, almost violet, regal',
+  'ivory-white wisteria racemes streaked with faint lilac',
+  'butter-yellow wisteria racemes (Japanese golden chain hybrid), warm honey tones',
+  'soft sky-blue wisteria racemes, dusted with periwinkle',
+  'rose-coral wisteria racemes, sunset-toned',
+  'jade-green wisteria racemes, unusual and exotic',
+  'antique champagne wisteria racemes, pale gold-tinged ivory',
+  'rich plum wisteria racemes shading to violet at the petal tips',
+];
+
+const BAMBOO_LAYER =
+  'set behind a delicate canopy of bamboo leaves — long lanceolate green blades arching above the wisteria, the leaves layered but never crowding the animals, soft dappled light filtering through';
+
+// Refined heritage-botanical palettes — inherited from butterfly-trellis,
+// NOT the Warhol drunk-animals neon palette.
+const PALETTES = [
+  'emerald and bone-ivory background, gold-leaf accents, archival watercolor',
+  'sage green and cream, blush-pink highlights, soft dusty rose accents',
+  'deep navy ink on bone white, monochromatic indigo gradient',
+  'champagne on midnight navy, subtle metallic shimmer',
+  'forest green with iridescent jewel-tone accents — sapphire, amethyst, emerald, ruby',
+  'soft watercolor pastels — peach, lavender, mint, sky blue — on warm cream',
+  'antique gold and matte black, ivory background',
+  'powder blue and parchment, faded sepia accents',
+  'oxblood and cream, dark olive accents',
+  'pale-celadon green on bone-white, faded coral accents, vintage botanical',
+];
+
+// Composition cues — emphasizes the UP-facing rule and seamless repeat.
+const COMPOSITIONS = [
+  'allover seamless repeat, animals scattered among the wisteria racemes, ALL faces tipped UP toward the leaf canopy',
+  'half-drop repeat, animals nested in pendulous racemes, ALL chins lifted upward',
+  'tight 24-inch tile repeat, dense scatter of upward-gazing animals among bamboo blades',
+  'mirrored axis repeat, animals in pairs facing skyward, kaleidoscopic wisteria',
+  'cascading vertical repeat following raceme drops, animals climbing and looking up',
+  'tossed-bouquet repeat, animals interspersed with cut wisteria stems, all faces lifted',
+  'large-scale mural repeat, hero animal centered face-up, racemes radiating',
+  'striped column repeat, animals in vertical bands gazing upward through bamboo',
+  'diagonal flow repeat, racemes guiding the eye upward, animals turned to follow',
+  'allover botanical repeat with breathing space, every animal’s gaze tilted toward the petals above',
+];
+
+const STYLES = [
+  'fine archival watercolor in the style of a 19th-century botanical plate',
+  'gouache illustration with crisp ink linework, gallery-quality',
+  'hand-pulled silkscreen wallpaper, soft layered tones, refined repeat',
+  'chinoiserie-inspired brushwork on aged silk, mineral pigment',
+  'block-printed wallpaper feel, hand-carved edges, archival paper grain',
+  'pen-and-watercolor garden journal aesthetic, refined and personal',
+  'mid-century botanical lithograph, slight halftone, archival print',
+  'modern fine-art illustration with luminous color washes, no neon',
+  'painterly gouache with confident brushwork, fabric-pattern feel',
+  'antique decorator wallpaper, bone-paper texture, slightly faded',
+];
+
+const ANIMALS_FACE_UP = [
+  'long-armed Bornean orangutan hanging by one arm, chin tipped UP',
+  'small gibbon dangling from a raceme, face skyward',
+  'fluffy red panda balancing on a bamboo culm, gazing up through petals',
+  'spider monkey looped by its prehensile tail, mouth open to the canopy',
+  'capuchin monkey perched on a bamboo node, head tilted back',
+  'sloth hugging a bamboo stem, slow blink upward at the wisteria',
+  'lemur with ringed tail wrapped around a stem, ears forward, looking up',
+  'small lar gibbon swinging from a raceme, face turned to the sky',
+  'colobus monkey draped over a bamboo branch, gaze tipped upward',
+  'wide-eyed tarsier clinging to a bamboo node, neck craned skyward',
+  'koala wedged in a wisteria-bamboo cradle, face turned up',
+  'tipsy raccoon balancing on a bamboo node, snout up, eyes on the racemes',
+];
+
+function pickRand(arr, exclude = new Set()) {
+  for (let tries = 0; tries < 50; tries++) {
+    const v = arr[Math.floor(Math.random() * arr.length)];
+    if (!exclude.has(v)) return v;
+  }
+  return arr[Math.floor(Math.random() * arr.length)];
+}
+
+// Build a single prompt — `state` is 'drunk' | 'stoned'; defaults to random.
+function buildPrompt({ state = null, seed = null } = {}) {
+  const rng = (seed != null)
+    ? (() => { let s = seed >>> 0; return () => { s = (s * 1664525 + 1013904223) >>> 0; return s / 2 ** 32; }; })()
+    : Math.random;
+  const pick = arr => arr[Math.floor(rng() * arr.length)];
+  const s = state || (rng() < 0.5 ? 'drunk' : 'stoned');
+  const tableau = s === 'drunk' ? pick(DRUNK_TABLEAUX) : pick(STONED_TABLEAUX);
+  return [
+    pick(ANIMALS_FACE_UP),
+    tableau,
+    `cascading from ${pick(WISTERIA_COLORS)}`,
+    BAMBOO_LAYER,
+    `palette: ${pick(PALETTES)}`,
+    pick(STYLES),
+    pick(COMPOSITIONS),
+    'CRITICAL: every animal MUST be facing UP toward the wisteria canopy — chin lifted, eyes/snout skyward, no animals looking down or sideways',
+    'seamless wallpaper repeat, archival quality, refined heritage botanical aesthetic, no neon, no text, no watermark',
+  ].join(', ');
+}
+
+function buildN(n, opts = {}) {
+  const out = [];
+  const usedAnimals = new Set();
+  const usedWisteria = new Set();
+  for (let i = 0; i < n; i++) {
+    if (usedAnimals.size >= ANIMALS_FACE_UP.length - 1) usedAnimals.clear();
+    if (usedWisteria.size >= WISTERIA_COLORS.length - 1) usedWisteria.clear();
+    const animal = pickRand(ANIMALS_FACE_UP, usedAnimals);  usedAnimals.add(animal);
+    const wisteria = pickRand(WISTERIA_COLORS, usedWisteria); usedWisteria.add(wisteria);
+    const state = opts.state || (Math.random() < 0.5 ? 'drunk' : 'stoned');
+    const tableau = state === 'drunk' ? pickRand(DRUNK_TABLEAUX) : pickRand(STONED_TABLEAUX);
+    out.push([
+      animal, tableau,
+      `cascading from ${wisteria}`,
+      BAMBOO_LAYER,
+      `palette: ${pickRand(PALETTES)}`,
+      pickRand(STYLES),
+      pickRand(COMPOSITIONS),
+      'CRITICAL: every animal MUST be facing UP toward the wisteria canopy — chin lifted, eyes/snout skyward',
+      'seamless wallpaper repeat, archival quality, refined heritage botanical, no neon, no text, no watermark',
+    ].join(', '));
+  }
+  return out;
+}
+
+module.exports = {
+  buildPrompt, buildN,
+  DRUNK_TABLEAUX, STONED_TABLEAUX, WISTERIA_COLORS, BAMBOO_LAYER,
+  PALETTES, STYLES, COMPOSITIONS, ANIMALS_FACE_UP,
+};
+
+if (require.main === module) {
+  const n = parseInt(process.argv[2] || '100', 10);
+  const prompts = buildN(n);
+  for (const p of prompts) console.log('---\n' + p + '\n');
+}
diff --git a/server.js b/server.js
index 39eac53..cf4c2bf 100644
--- a/server.js
+++ b/server.js
@@ -3109,6 +3109,21 @@ app.get('/designs', (req, res) => {
       const createdMs = Date.parse(d.created_at || '') || 0;
       const isNew = createdMs && (Date.now() - createdMs < 72 * 3600 * 1000);
       const newBadge = isNew ? `<span class="card-new-badge" aria-label="Newly added">NEW</span>` : '';
+      // DW-style SKU — derived from the design id with a stable two-letter prefix
+      // for the wallco.ai sub-label (WC). Designer Wallcoverings catalog convention
+      // is DW-<vendor-code>-<numeric>, so wallco.ai pieces become DW-WC-####.
+      const sku = `DW-WC-${String(d.id).padStart(4, '0')}`;
+      // Color name — interior-designer-skill style: derive a poetic color name
+      // from the dominant_hex by binning into the same hue buckets the page
+      // filter uses, then prefer the leading word of the title (Honey/Amber/
+      // Rose/Sage/…) when the generator already gave us one — that's the
+      // canonical color family per the prompt library. Falls back to the
+      // hue bucket if the title doesn't lead with one.
+      const colorNameFromTitle = (String(d.title || '').match(/^(Honey|Amber|Rose|Sage|Olive|Marine|Sapphire|Mauve|Plum|Neutral|Bone|Champagne|Ivory|Emerald|Navy|Coral|Blush|Indigo|Charcoal)/i) || [])[1];
+      const colorName = colorNameFromTitle || (hueBucketOf(d.dominant_hex) || 'neutral').replace(/^./, c => c.toUpperCase());
+      // Style tag — category is the closest thing to a style category in the
+      // data model (damask, butterfly-trellis, stoned-animals, mural-scenic).
+      const styleTag = String(d.category || 'mixed').replace(/-/g, ' ');
       return `
     <a href="/design/${d.id}" class="design-card${roomKey ? ' has-room' : ''}${isNew ? ' is-new' : ''}" aria-label="${cardAriaLabel(d)}" data-design-id="${d.id}">
       <button type="button" class="fav-btn" data-fav-id="${d.id}" aria-pressed="false" aria-label="Save ${d.title} to favorites" title="Favorite"><span class="fav-icon"></span></button>
@@ -3116,8 +3131,12 @@ app.get('/designs', (req, res) => {
       <div class="card-img" style="background-image:url('${d.image_url}')" role="img" aria-label="${d.title} pattern thumbnail">${roomOverlay}</div>
       <div class="card-meta">
         <span class="card-title">${d.title}</span>
-        <span class="card-cat">${d.category}</span>
-        <span class="color-dot" style="background:${d.dominant_hex}" aria-hidden="true"></span>
+        <span class="card-sku" title="DW catalog SKU">${sku}</span>
+        <span class="card-colorname">${colorName} <span class="color-dot" style="background:${d.dominant_hex}" aria-hidden="true"></span><span class="card-hex">${(d.dominant_hex || '').toUpperCase()}</span></span>
+        <span class="card-tags">
+          <span class="card-ai-badge" title="AI-designed pattern">✦ AI-Designed</span>
+          <span class="card-style">${styleTag}</span>
+        </span>
       </div>
     </a>`;
     }
@@ -3304,7 +3323,7 @@ ${cat === 'mural-scenic' ? `
           }).join('')}
         </div>
         <label class="density-label" style="display:inline-flex;align-items:center;gap:8px;font:11px var(--sans);text-transform:uppercase;letter-spacing:.1em;color:var(--ink-faint)">Density
-          <input type="range" id="density-slider" min="1" max="8" step="1" value="3" class="density-range" style="flex:0 0 110px">
+          <input type="range" id="density-slider" min="1" max="12" step="1" value="6" class="density-range" style="flex:0 0 140px">
         </label>
         <button type="button" id="surprise-btn" class="filter-select"
           style="background:var(--gold,#c9a14b);color:var(--accent,#0d0d0d);border:0;font-weight:500;padding:8px 14px;cursor:pointer;border-radius:6px;letter-spacing:.04em"

← da2aabc wallco.ai homepage: pin newest 6 butterflies above Featured,  ·  back to Wallco Ai  ·  wisteria-animals: drop bamboo from brief; wisteria racemes a 09ad34c →