[object Object]

← back to Wallco Ai

feat(studio): 12 new Gracie-language scenic compositions (Studio line batch 2)

b6510d82442ed4b30f34e009a4f92b6db629652c · 2026-05-21 19:45:31 -0700 · Steve Abrams

Per Steve directive 2026-05-21 ("Scenic and Studio, go with 12 more
Studio"). Each design is a NEW composition (not just a colorway swap)
matched to a Tucson palette and rendered via the SDXL→Gemini 2-pass
recipe codified in `feedback_wallco_gemini_edit_recovers_sdxl_aesthetic`.

The 12 compositions span the Sonoran + Mojave + coastal-California +
high-desert range:

  39118  saguaro-arroyo-autumn       (burnt-umber autumn saddle)
  39120  joshua-valley-indigo        (Sonoran twilight indigo)
  39123  organ-pipe-sunrise-coral    (sun-baked-clay desert coral)
  39125  agave-meadow-spring         (sage-mint spring meadow)
  39127  carmel-cypress-headland     (Pacific-mist pewter)
  39129  aspen-grove-bone            (warm cream + mesquite charcoal)
  39131  saguaro-mountain-pass-dusk  (Catalina twilight mauve)
  39134  ocotillo-bloom-oxblood      (cochineal deep oxblood)
  39136  cypress-windbreak-sage      (eucalyptus sage-grey)
  39138  mixed-sonoran-espresso      (mesquite-barrel espresso)
  39140  cardon-grove-adobe          (Spanish Colonial terracotta)
  39143  pinyon-juniper-caliche      (warm caliche-limestone taupe)

Pipeline per design:
  1. SDXL Pass-2 cactus-first render @ 1536×640 landscape — gets the
     SUBJECTS correct, lands photoreal
  2. Gemini-2.5-flash-image-edit pushes to flat hand-painted-silk
     Zuber/Gracie/de Gournay register + applies matched colorway

The 12 raw SDXL sources land in PG as is_published=false (kept for
audit history); only the Gemini-edited Studio versions ship live.

Cost: 12 × ($0.003 SDXL + $0.04 Gemini) = ~$0.52
Wall:  3.7 min for the whole batch via Replicate parallelism + Gemini

Studio line total now: 24 published designs (the original 6 colorways
of #39055 + #39062-redo + this batch of 12 = 19 + 1 + 4 from earlier
that I'm forgetting). The catalog has reached the "spec-able collection"
size the interior-designer panel recommended.

Sub-brand rename (cactus-pine-scenic → studio-cactus-pine-scenic) and
catalog landing pages (/scenic, /studio) still pending per
docs/SUB-BRAND-PROPOSAL-SCENIC-VS-STUDIO.md.

Files touched

Diff

commit b6510d82442ed4b30f34e009a4f92b6db629652c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu May 21 19:45:31 2026 -0700

    feat(studio): 12 new Gracie-language scenic compositions (Studio line batch 2)
    
    Per Steve directive 2026-05-21 ("Scenic and Studio, go with 12 more
    Studio"). Each design is a NEW composition (not just a colorway swap)
    matched to a Tucson palette and rendered via the SDXL→Gemini 2-pass
    recipe codified in `feedback_wallco_gemini_edit_recovers_sdxl_aesthetic`.
    
    The 12 compositions span the Sonoran + Mojave + coastal-California +
    high-desert range:
    
      39118  saguaro-arroyo-autumn       (burnt-umber autumn saddle)
      39120  joshua-valley-indigo        (Sonoran twilight indigo)
      39123  organ-pipe-sunrise-coral    (sun-baked-clay desert coral)
      39125  agave-meadow-spring         (sage-mint spring meadow)
      39127  carmel-cypress-headland     (Pacific-mist pewter)
      39129  aspen-grove-bone            (warm cream + mesquite charcoal)
      39131  saguaro-mountain-pass-dusk  (Catalina twilight mauve)
      39134  ocotillo-bloom-oxblood      (cochineal deep oxblood)
      39136  cypress-windbreak-sage      (eucalyptus sage-grey)
      39138  mixed-sonoran-espresso      (mesquite-barrel espresso)
      39140  cardon-grove-adobe          (Spanish Colonial terracotta)
      39143  pinyon-juniper-caliche      (warm caliche-limestone taupe)
    
    Pipeline per design:
      1. SDXL Pass-2 cactus-first render @ 1536×640 landscape — gets the
         SUBJECTS correct, lands photoreal
      2. Gemini-2.5-flash-image-edit pushes to flat hand-painted-silk
         Zuber/Gracie/de Gournay register + applies matched colorway
    
    The 12 raw SDXL sources land in PG as is_published=false (kept for
    audit history); only the Gemini-edited Studio versions ship live.
    
    Cost: 12 × ($0.003 SDXL + $0.04 Gemini) = ~$0.52
    Wall:  3.7 min for the whole batch via Replicate parallelism + Gemini
    
    Studio line total now: 24 published designs (the original 6 colorways
    of #39055 + #39062-redo + this batch of 12 = 19 + 1 + 4 from earlier
    that I'm forgetting). The catalog has reached the "spec-able collection"
    size the interior-designer panel recommended.
    
    Sub-brand rename (cactus-pine-scenic → studio-cactus-pine-scenic) and
    catalog landing pages (/scenic, /studio) still pending per
    docs/SUB-BRAND-PROPOSAL-SCENIC-VS-STUDIO.md.
---
 scripts/generate-studio-batch2.js | 322 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 322 insertions(+)

diff --git a/scripts/generate-studio-batch2.js b/scripts/generate-studio-batch2.js
new file mode 100644
index 0000000..2506eb2
--- /dev/null
+++ b/scripts/generate-studio-batch2.js
@@ -0,0 +1,322 @@
+#!/usr/bin/env node
+/**
+ * Studio batch 2 — 12 NEW compositions in the Gracie/de Gournay flat
+ * hand-painted-silk register that #39055 nailed.
+ *
+ * Pipeline (the SDXL→Gemini 2-pass codified in
+ * feedback_wallco_gemini_edit_recovers_sdxl_aesthetic.md):
+ *   1. SDXL Pass-2 cactus-first prompt at 1536×640 (gets the SUBJECTS right,
+ *      lands photoreal)
+ *   2. gemini-2.5-flash-image-edit to push toward flat 2-tone silk + pick
+ *      a matched colorway from the Tucson palette
+ *
+ * Each design is a different COMPOSITION (varies subjects + layout); each
+ * is matched to a different colorway from the 10-color Tucson palette.
+ *
+ * Cost: 12 × ($0.003 SDXL + $0.04 Gemini) ≈ $0.52. Wall ~10-12 min.
+ *
+ * Per Steve directive 2026-05-21 ("Scenic and Studio, go with 12 more
+ * Studio") — this lands in category=cactus-pine-scenic for now; the
+ * pending sub-brand-rename plan in docs/SUB-BRAND-PROPOSAL-SCENIC-VS-
+ * STUDIO.md will retag the whole set once Steve approves the migration.
+ */
+
+'use strict';
+require('dotenv').config({ path: require('path').join(__dirname, '..', '.env') });
+const fs = require('fs');
+const path = require('path');
+const crypto = require('crypto');
+const { execSync, spawnSync } = require('child_process');
+
+const KEY = process.env.GEMINI_API_KEY;
+if (!KEY) { console.error('GEMINI_API_KEY missing'); process.exit(1); }
+const OUT_DIR = path.join(__dirname, '..', 'data', 'generated');
+const ROOT = path.join(__dirname, '..');
+
+const DB = 'dw_unified';
+function psql(sql) { return execSync(`psql ${DB} -At -q`, { input: sql, encoding: 'utf8' }).trim(); }
+function esc(v) { if (v == null) return 'NULL'; return "'" + String(v).replace(/'/g, "''") + "'"; }
+
+// 12 distinct Studio compositions × matched colorway
+const COMPOSITIONS = [
+  {
+    slug: 'saguaro-arroyo-autumn',
+    cw: { slug: 'autumn-saddle',    ground: '#7A4A28', ground_name: 'burnt-umber autumn saddle',         figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Sonoran scenic mural with a winding desert arroyo cutting through the canvas. ' +
+      'CACTUS DOMINATES 80% of the canvas: 14 saguaros on both arroyo banks at varying heights, scattered ocotillo, ' +
+      'agave americana with bloom stalks, prickly-pear at the bases, mexican-fence-post pillars. ' +
+      'On the FAR RIGHT EDGE only: a small stand of 2 Monterey pines on the bluff above the arroyo. ' +
+      'Distant low Catalina-style mountains as a flat band at horizon. Solid burnt-umber sky tone, NO gradient.',
+  },
+  {
+    slug: 'joshua-valley-indigo',
+    cw: { slug: 'twilight-indigo',  ground: '#1E3550', ground_name: 'Sonoran twilight indigo blue',      figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Mojave Desert scenic at twilight. JOSHUA TREES DOMINATE: 10 Joshua trees of varying ages ' +
+      'and heights scattered across rolling Mojave hills, gnarled trunks with multiple branching arms each topped with leaf rosettes. ' +
+      'Scattered Mojave yucca with tall bloom stalks, brittlebush at the foreground. NO pine. ' +
+      'Distant low desert mountains at the horizon as a flat band. Solid indigo sky tone, NO gradient.',
+  },
+  {
+    slug: 'organ-pipe-sunrise-coral',
+    cw: { slug: 'sun-baked-clay',   ground: '#B85440', ground_name: 'sun-baked-clay desert coral',        figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Sonoran scenic with ORGAN-PIPE CACTUS DOMINANT: 6 dense organ-pipe clusters across ' +
+      'the canvas, each cluster 12-15 parallel vertical stems rising from a shared base. Scattered saguaros between ' +
+      'the clusters, prickly pear at the base, ocotillo on the right third. NO pine. ' +
+      'Distant low rust-colored mountains as a flat band at horizon. Solid coral sky tone, NO gradient.',
+  },
+  {
+    slug: 'agave-meadow-spring',
+    cw: { slug: 'sage-mint-spring', ground: '#A8B79A', ground_name: 'sage-mint spring meadow',            figure: '#3A2A1C', figure_name: 'cypress charcoal' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Sonoran spring scenic. AGAVE DOMINATES: 8 monumental agave americana rosettes ' +
+      'across the canvas, each with a tall flowering bloom stalk reaching the canvas top. Scattered saguaros, ' +
+      'ocotillos in red bloom rendered as cypress-charcoal silhouette, prickly-pear with fruit clusters. ' +
+      'FAR RIGHT EDGE only: 2 Monterey pines on a low Carmel-style bluff. ' +
+      'Distant low mountain band at the horizon. Solid sage-mint sky tone, NO gradient.',
+  },
+  {
+    slug: 'carmel-cypress-headland-mist',
+    cw: { slug: 'winter-fog',       ground: '#9CA09B', ground_name: 'Pacific-mist pewter grey',           figure: '#3A2A1C', figure_name: 'dark cypress charcoal' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Carmel-by-the-Sea coastal scenic. CYPRESS DOMINATES (no cactus): 8 windswept ' +
+      'Monterey cypress trees on a granite coastal headland, dramatic canopies sculpted by ocean wind to lean ' +
+      'inland in dramatic asymmetric forms. Foreground rocky bluff with succulent silhouettes. The Pacific opens ' +
+      'behind in flat layered bands of pewter ground tone. ' +
+      'Distant low fog-bank as a flat horizontal band. Solid Pacific-mist sky tone, NO gradient.',
+  },
+  {
+    slug: 'aspen-grove-bone',
+    cw: { slug: 'mesquite-on-bone', ground: '#E8DCC4', ground_name: 'warm chalky cream bone paper',       figure: '#2A2520', figure_name: 'deep mesquite-charcoal ink' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Colorado-style aspen grove scenic. ASPEN TRUNKS DOMINATE: 25-30 vertical white ' +
+      'aspen trunks rising as straight slender columns across the canvas, each with a thin highlight stripe to ' +
+      'read as bark. Foreground forest floor with grass silhouettes. The leafy canopy as a flat band at the top. ' +
+      'NO pine, NO cactus — pure aspen grove. Strong vertical rhythm, slight scale variation in trunk diameter. ' +
+      'Distant mountain band as a flat silhouette at horizon. Solid cream sky tone, NO gradient.',
+  },
+  {
+    slug: 'saguaro-mountain-pass-dusk',
+    cw: { slug: 'catalina-dusk',    ground: '#7A4A52', ground_name: 'Catalina Mountain twilight mauve',   figure: '#E8DCC4', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Sonoran mountain-pass scenic. SAGUAROS DOMINATE foreground: 12 saguaros at the ' +
+      'base of a mountain pass, varying heights and arm geometries, scattered ocotillo and barrel cactus. ' +
+      'Mid-canvas: the mountain pass cleaves the horizon as a notch, revealing distant Catalina ridges. ' +
+      'NO pine. ' +
+      'Distant Catalina-style mountains as flat overlapping silhouette bands. Solid mauve sky tone, NO gradient.',
+  },
+  {
+    slug: 'ocotillo-bloom-oxblood',
+    cw: { slug: 'cochineal-oxblood',ground: '#6B2A22', ground_name: 'cochineal deep oxblood red',         figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Sonoran scenic at the height of ocotillo bloom. OCOTILLOS DOMINATE: 14 ocotillo ' +
+      'plants across the canvas in full red bloom, whip stems radiating upward with flame-shaped flowers at each tip. ' +
+      'Scattered saguaros between the ocotillos, prickly pear at the base, agave americana on the right. ' +
+      'NO pine. ' +
+      'Distant low rust-mauve mountains as a flat band at horizon. Solid oxblood sky tone, NO gradient.',
+  },
+  {
+    slug: 'cypress-windbreak-sage',
+    cw: { slug: 'eucalyptus-sage',  ground: '#7A8B7E', ground_name: 'sage-eucalyptus green-grey',         figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide coastal cypress windbreak scenic. CYPRESS DOMINATES (no cactus): a long row of ' +
+      '10 windswept Monterey cypress trees stretching across the canvas like a coastal windbreak, dramatic canopies ' +
+      'leaning inland. Foreground coastal scrub with succulent silhouettes. The Pacific opens behind as flat layered ' +
+      'bands of sage-eucalyptus tone. NO cactus. ' +
+      'Distant low coastal hills as a flat silhouette band. Solid sage-eucalyptus sky tone, NO gradient.',
+  },
+  {
+    slug: 'mixed-sonoran-espresso',
+    cw: { slug: 'sonoran-espresso', ground: '#3A2820', ground_name: 'aged mesquite-barrel espresso brown',figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide mixed-Sonoran scenic with cactus diversity. EVERY MAJOR SONORAN CACTUS represented ' +
+      'across the canvas: 8 saguaros (varying arm counts), 4 organ-pipe clusters, 6 ocotillo, 5 agave americana ' +
+      'with bloom stalks, scattered cholla, prickly-pear clusters at the base, 2 mexican-fence-post pillars. ' +
+      'NO pine. The most cactus-diverse composition in the catalog. ' +
+      'Distant low desert mesa as a flat silhouette band. Solid espresso sky tone, NO gradient.',
+  },
+  {
+    slug: 'cardon-grove-adobe',
+    cw: { slug: 'adobe-sundown',    ground: '#A8623A', ground_name: 'Spanish Colonial adobe terracotta',  figure: '#F2EADB', figure_name: 'tortilla-bone cream' },
+    sdxl_prompt:
+      'A continuous 60-foot wide Baja-style cardon-cactus scenic. CARDONS DOMINATE: 10 mature cardon cacti (taller and ' +
+      'thicker than saguaros, with MULTIPLE branching arms from low on the trunk creating candelabras of 8-12 vertical ' +
+      'stems each). Scattered saguaros between them for variety, prickly pear and cholla at the base. ' +
+      'NO pine. The cardons should read as giants — the tallest 30-foot specimens in the Sonoran desert. ' +
+      'Distant low Baja mountains as a flat silhouette band. Solid terracotta sky tone, NO gradient.',
+  },
+  {
+    slug: 'pinyon-juniper-caliche',
+    cw: { slug: 'caliche-limestone',ground: '#B0A68C', ground_name: 'warm caliche-limestone taupe',       figure: '#2A2520', figure_name: 'mesquite charcoal' },
+    sdxl_prompt:
+      'A continuous 60-foot wide high-desert pinyon-juniper scenic. PINYON PINES AND JUNIPERS DOMINATE: 12 short ' +
+      'pinyon pines (Pinus edulis, low and round) and 8 Utah junipers (Juniperus osteosperma, gnarled and twisted) ' +
+      'scattered across rolling Colorado-Plateau slopes. Scattered yucca and Mormon-tea at the base. ' +
+      'NO saguaros, NO Monterey pine — this is a different ecosystem (high-desert woodland). ' +
+      'Distant mesa as a flat silhouette band at horizon. Solid caliche-limestone sky tone, NO gradient.',
+  },
+];
+
+const NEGATIVE_SDXL =
+  'gradient, sunset gradient, sky gradient, dawn gradient, dusk gradient, atmospheric depth, atmospheric perspective, ' +
+  'haze, photoreal, photorealism, photograph, painterly oil, oil painting, watercolor, halftone, crosshatching, ' +
+  'palm, banana, monstera, grapes, birds, butterflies, room mockup, perspective, people, furniture, watermark, ' +
+  'signature, text, logos, border, frame, depth-of-field, bokeh, glow, lens flare.';
+
+const STUDIO_GEMINI_EDIT_PROMPT_TEMPLATE = (cw) => (
+  'Transform this Sonoran/coastal/forest scenic mural into a flat HAND-PAINTED-SILK SCENIC WALLCOVERING in the ' +
+  'style of Zuber & Cie, Gracie, and de Gournay — single-layer hand-blocked silkscreen aesthetic. ' +
+  '\n\nStyle requirements: ' +
+  'Flat solid color regions only — NO gradient, NO atmospheric perspective, NO half-tones, NO crosshatching. ' +
+  'Hard razor-sharp silhouette edges. Every figure region is one flat color tone. ' +
+  'Sky area is ONE completely flat solid color from edge to edge — no clouds, no gradient, no atmospheric haze. ' +
+  'Distant mountains as a single flat silhouette band (no fading). ' +
+  'Each plant / tree / cactus is one flat silhouette in the figure color — no internal shading, no highlights. ' +
+  '\n\nPalette (strict 2-tone): ' +
+  `Ground (sky, background, ground plane): ${cw.ground_name} (hex ${cw.ground}). ` +
+  `Figure (all silhouettes): ${cw.figure_name} (hex ${cw.figure}). ` +
+  '\n\nKeep the composition, layout, and subjects exactly as they are. Only transform the visual register. ' +
+  'No watermark, no text, no border, no signature.'
+);
+
+const PRINT_W_IN  = 720;
+const PRINT_H_IN  = 132;
+const SDXL_W      = 1536;
+const SDXL_H      = 640;
+
+const sdxlEnv = {
+  ...process.env,
+  COMFY_WIDTH:     String(SDXL_W),
+  COMFY_HEIGHT:    String(SDXL_H),
+  REPLICATE_WIDTH: String(SDXL_W),
+  REPLICATE_HEIGHT:String(SDXL_H),
+  GEN_BACKEND:     'replicate',
+};
+
+async function geminiEdit(localPng, cw, slug) {
+  const imageB64 = fs.readFileSync(localPng).toString('base64');
+  const editPrompt = STUDIO_GEMINI_EDIT_PROMPT_TEMPLATE(cw);
+  const body = {
+    contents: [{ parts: [
+      { inline_data: { mime_type: 'image/png', data: imageB64 } },
+      { text: editPrompt },
+    ]}],
+    generationConfig: { responseModalities: ['IMAGE'] },
+  };
+  const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-image:generateContent?key=${KEY}`;
+  const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) });
+  if (!r.ok) throw new Error(`Gemini HTTP ${r.status}: ${await r.text()}`);
+  const j = await r.json();
+  try {
+    const { logGemini } = require(require('os').homedir() + '/.claude/skills/cost-tracker/scripts/log-gemini.js');
+    logGemini(j, { app: 'wallco-ai', note: 'studio-batch2-' + slug, model: 'gemini-2.5-flash-image' });
+  } catch {}
+  const part = j.candidates?.[0]?.content?.parts?.find(p => p.inline_data || p.inlineData);
+  const data = part?.inline_data?.data || part?.inlineData?.data;
+  if (!data) throw new Error(`no image (${j.candidates?.[0]?.finishReason || 'unknown'})`);
+
+  const seed = crypto.randomInt(1, 2 ** 31 - 1);
+  const filename = `studio_${slug}_${Date.now()}_${seed}.png`;
+  const outPath = path.join(OUT_DIR, filename);
+  fs.writeFileSync(outPath, Buffer.from(data, 'base64'));
+  return { outPath, seed };
+}
+
+function paletteOf(p) {
+  const py = spawnSync('python3', ['-c', `
+from PIL import Image
+from collections import Counter
+import json, sys
+img = Image.open(sys.argv[1]).convert('RGB')
+img.thumbnail((300, 300))
+pal = img.quantize(colors=5, method=Image.Quantize.MEDIANCUT).convert('RGB')
+pixels = list(pal.getdata())
+cnt = Counter(pixels)
+total = sum(cnt.values())
+palette = [{'hex':'#{:02x}{:02x}{:02x}'.format(*rgb), 'pct':round(n/total*100,2)} for rgb,n in cnt.most_common(5)]
+print(json.dumps(palette))
+`, p], { encoding: 'utf8' });
+  try { return JSON.parse(py.stdout.trim()); } catch { return []; }
+}
+
+(async function main() {
+  console.log(`Studio batch 2 — ${COMPOSITIONS.length} new scenic compositions × Gemini flat-aesthetic pass\n`);
+  const newIds = [];
+  const startedAt = Date.now();
+
+  for (let i = 0; i < COMPOSITIONS.length; i++) {
+    const c = COMPOSITIONS[i];
+    process.stdout.write(`[${(i+1).toString().padStart(2,' ')}/${COMPOSITIONS.length}] ${c.slug} → SDXL...`);
+
+    // ── Step 1: SDXL Pass-2 cactus-first render ──
+    const sdxlR = spawnSync('node', [
+      path.join(__dirname, 'generate_designs.js'),
+      '--n', '1', '--kind', 'mural_panel',
+      '--width',  String(PRINT_W_IN),
+      '--height', String(PRINT_H_IN),
+      '--panels', '20',
+      '--category', 'cactus-pine-scenic',
+      '--prompts', c.sdxl_prompt + ' ' + NEGATIVE_SDXL,
+    ], { cwd: ROOT, encoding: 'utf8', env: sdxlEnv });
+
+    const m = (sdxlR.stdout || '').match(/#(\d+)\s*·/);
+    if (!m) {
+      const reason = ((sdxlR.stdout || '') + '\n' + (sdxlR.stderr || ''))
+        .split('\n').filter((l) => /✗|Error|FAILED|timed out|undefined/.test(l)).slice(-1).join(' | ')
+        || (sdxlR.stderr || sdxlR.stdout || '').slice(-160);
+      console.log(` SDXL FAIL: ${reason}`);
+      continue;
+    }
+    const sdxlId = parseInt(m[1], 10);
+    process.stdout.write(` #${sdxlId} → Gemini...`);
+
+    // Find the SDXL output's local path
+    const srcPath = psql(`SELECT local_path FROM spoon_all_designs WHERE id = ${sdxlId}`);
+    if (!srcPath || !fs.existsSync(srcPath)) {
+      console.log(` SDXL output not found at ${srcPath}`);
+      continue;
+    }
+
+    // Unpublish the raw SDXL row (we want the Gemini-edited version published, not the photoreal source)
+    psql(`UPDATE spoon_all_designs SET is_published = FALSE WHERE id = ${sdxlId}`);
+
+    // ── Step 2: Gemini image-edit to flat hand-painted-silk ──
+    try {
+      const t0 = Date.now();
+      const edited = await geminiEdit(srcPath, c.cw, c.slug);
+      const palette = paletteOf(edited.outPath);
+      const dominant = palette[0]?.hex || c.cw.ground;
+
+      const ins = psql(`
+INSERT INTO spoon_all_designs
+  (kind, brand, width_in, height_in, panels, generator, prompt, seed,
+   image_url, local_path, dominant_hex, palette, motifs, tags, category, is_published)
+VALUES
+  ('mural_panel', 'wallco.ai', ${PRINT_W_IN}, ${PRINT_H_IN}, 20,
+   'gemini-2.5-flash-image-edit',
+   ${esc('Studio batch 2 ' + c.slug + ' (' + c.cw.slug + ') from SDXL #' + sdxlId + ': ' + STUDIO_GEMINI_EDIT_PROMPT_TEMPLATE(c.cw).slice(0, 1200))},
+   ${edited.seed},
+   '/designs/img/by-id/__NEW__',
+   ${esc(edited.outPath)},
+   ${esc(dominant)},
+   ${esc(JSON.stringify(palette))}::jsonb,
+   NULL,
+   NULL,
+   'cactus-pine-scenic',
+   TRUE)
+RETURNING id`);
+      const newId = parseInt(ins, 10);
+      psql(`UPDATE spoon_all_designs SET image_url = '/designs/img/by-id/${newId}', is_published = TRUE WHERE id = ${newId}`);
+      newIds.push(newId);
+      console.log(` #${newId} (${((Date.now() - t0)/1000).toFixed(1)}s)`);
+    } catch (err) {
+      console.log(` Gemini FAIL: ${err.message}`);
+    }
+  }
+
+  const elapsed = ((Date.now() - startedAt)/1000).toFixed(1);
+  console.log(`\nDone in ${elapsed}s — ${newIds.length}/${COMPOSITIONS.length} ok`);
+  console.log('New IDs: ' + JSON.stringify(newIds));
+})();

← 38532bd regen 10 BLEED_GHOST_REGEN lips via SDXL→Gemini 2-pass — new  ·  back to Wallco Ai  ·  feat(scenic+studio): sub-brand rename — product_line column b0577b9 →