← back to Consulting Designerwallcoverings Com
flagship 14-section DW analysis app + 6 luxury-leader concepts, snapshot-bound
153dc6e2f193b3039cf69ea552a9a4b3f4515ad0 · 2026-07-26 08:03:18 -0700 · Steve Abrams
Files touched
M build.mjsM data/dw-analysis.jsonM public/portal.htmlA public/versions/atelier.htmlD public/versions/bold.htmlD public/versions/classic.htmlD public/versions/editorial.htmlA public/versions/gallery.htmlA public/versions/heritage.htmlA public/versions/maison.htmlD public/versions/modern.htmlA public/versions/studio.htmlA public/versions/texture.htmlD public/versions/warm.html
Diff
commit 153dc6e2f193b3039cf69ea552a9a4b3f4515ad0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 26 08:03:18 2026 -0700
flagship 14-section DW analysis app + 6 luxury-leader concepts, snapshot-bound
---
build.mjs | 643 ++++++++++++++++++++++++++++++++++++++---
data/dw-analysis.json | 44 ++-
public/portal.html | 402 +++++++++++++++++++++-----
public/versions/atelier.html | 119 ++++++++
public/versions/bold.html | 27 --
public/versions/classic.html | 27 --
public/versions/editorial.html | 27 --
public/versions/gallery.html | 119 ++++++++
public/versions/heritage.html | 119 ++++++++
public/versions/maison.html | 119 ++++++++
public/versions/modern.html | 27 --
public/versions/studio.html | 119 ++++++++
public/versions/texture.html | 119 ++++++++
public/versions/warm.html | 27 --
14 files changed, 1685 insertions(+), 253 deletions(-)
diff --git a/build.mjs b/build.mjs
index a765d7c..76d6d16 100644
--- a/build.mjs
+++ b/build.mjs
@@ -1,57 +1,612 @@
#!/usr/bin/env node
-// Designer Wallcoverings — deliverable generator (fantasea-consulting pattern).
-// Emits public/versions/<aesthetic>.html: ONE editorial template skinned by a
-// palette/type/copy object per aesthetic direction, so the client picks a look.
-import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
+// Designer Wallcoverings — consulting deliverable generator (RENTV-flagship
+// pattern, DW-data-bound). Emits public/portal.html (the 14-section analysis
+// app behind the gate) + public/versions/*.html (6 luxury-leader storefront
+// concepts, each with the mandatory sort + density controls).
+// Render source = data/dw-analysis.json (DTD verdict C, 5/5, 2026-07-26):
+// snapshot JSON + visible collected_at stamp + /api/refresh re-collector.
+import { writeFileSync, mkdirSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const HERE = dirname(fileURLToPath(import.meta.url));
-const OUT = join(HERE, 'public', 'versions');
-mkdirSync(OUT, { recursive: true });
-
-const client = JSON.parse(readFileSync(join(HERE, 'data', 'client.json'), 'utf8'));
-
-// Each aesthetic = a skin. Add/edit freely; the client chooses from these.
-const SKINS = {
- editorial: { bg:'#f6f2ec', ink:'#14110e', accent:'#a9884f', font:"Georgia,serif", vibe:'Luxury / editorial' },
- modern: { bg:'#ffffff', ink:'#0b0b0d', accent:'#2b6cff', font:"'Helvetica Neue',system-ui,sans-serif", vibe:'Modern / minimal' },
- bold: { bg:'#0d0d12', ink:'#f5f5f7', accent:'#ff4d6d', font:"'Arial Black',system-ui,sans-serif", vibe:'Bold / energetic' },
- warm: { bg:'#fbf3e9', ink:'#3a2a1c', accent:'#d98a3d', font:"'Georgia',serif", vibe:'Warm / approachable' },
- classic: { bg:'#f4f4f0', ink:'#1c2530', accent:'#7a5b34', font:"'Times New Roman',serif", vibe:'Classic / trustworthy' },
+const OUT = join(HERE, 'public');
+mkdirSync(`${OUT}/versions`, { recursive: true });
+const readJ = (p, d) => { try { return JSON.parse(readFileSync(join(HERE, p), 'utf8')); } catch { return d; } };
+const client = readJ('data/client.json', {});
+const SNAP = readJ('data/dw-analysis.json', { catalog: {}, channels: [], fleet: { count: 0, sites: [] }, competitors: [] });
+const C = SNAP.catalog || {};
+const FF = C.five_field || {};
+const SO = C.sample_only || { total: 0, quote_only_by_design: 0, backlog: 0 };
+const fmt = n => (n == null ? '—' : Number(n).toLocaleString());
+const collected = SNAP.collected_at ? new Date(SNAP.collected_at) : null;
+const collectedLabel = collected ? collected.toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: '2-digit' }) : 'not yet collected';
+
+/* ------------------------------------------------------------------ data --- */
+const BIZ = {
+ name: 'Designer Wallcoverings', since: '30+ years', area: 'Los Angeles · nationwide e-commerce + trade',
+ email: client?.contact?.email || 'steve@designerwallcoverings.com',
+ phone: client?.contact?.phone || '',
+ site: 'designerwallcoverings.com',
+ focus: 'Luxury wallcoverings & designer fabrics — retail + to-the-trade',
+};
+
+// Luxe-only hero imagery (standing rule): statement materials — murals, textiles,
+// metallic leaf, velvet. Editorial desaturation for calm.
+const HERO_IMGS = [
+ 'https://images.unsplash.com/photo-1615873968403-89e068629265?auto=format&fit=crop&w=1920&q=68&sat=-25',
+ 'https://images.unsplash.com/photo-1618221195710-dd6b41faaea6?auto=format&fit=crop&w=1920&q=68&sat=-25',
+ 'https://images.unsplash.com/photo-1600210492486-724fe5c67fb0?auto=format&fit=crop&w=1920&q=68&sat=-25',
+ 'https://images.unsplash.com/photo-1600585154340-be6161a56a0c?auto=format&fit=crop&w=1920&q=68&sat=-25',
+ 'https://images.unsplash.com/photo-1600607687939-ce8a6c25118c?auto=format&fit=crop&w=1920&q=68&sat=-25',
+];
+
+/* ---- Luxury-leader concept directions (the "suggested new flagship") --------
+ * Six industry-LEADER directions, not palette swaps. Models are category
+ * leaders in luxury wallcoverings / design commerce. All imagery = gradient
+ * placeholders (leak-scanner-clean: no vendor assets, no upstream names). */
+const HOUSES = [
+ { key:'atelier', label:'Atelier', model:'de Gournay', bg:'#f4f0e6', panel:'#e9e2d0', ink:'#26221a', gold:'#8a7340', line:'rgba(38,34,26,.16)', disp:"'Cormorant Garamond',Georgia,serif", sans:"'Jost',system-ui,sans-serif", dark:false, tag:'Hand-painted calm. The scenic house.', mood:'Scenic-house minimalism — ivory ground, celadon accents, art-object product pages.' },
+ { key:'maison', label:'Maison', model:'Pierre Frey', bg:'#1c2331', panel:'#26304a', ink:'#f2efe6', gold:'#d9b877', line:'rgba(217,184,119,.28)', disp:"'Playfair Display',Georgia,serif", sans:"'Inter',system-ui,sans-serif", dark:true, tag:'The Parisian maison, digitized.', mood:'French maison energy — indigo + ochre, pattern-forward editorial storytelling.' },
+ { key:'studio', label:'Studio', model:'Backdrop (DTC)', bg:'#faf7f2', panel:'#f0e9dd', ink:'#1d1b17', gold:'#d96a3b', line:'rgba(29,27,23,.14)', disp:"'Inter',system-ui,sans-serif", sans:"'Inter',system-ui,sans-serif", dark:false, tag:'Wallpaper, without the intimidation.', mood:'DTC-playful — bold color blocks, plain language, sample-first funnel.' },
+ { key:'heritage', label:'Heritage', model:'Farrow & Ball', bg:'#232820', panel:'#2e352a', ink:'#efeee6', gold:'#b7a878', line:'rgba(183,168,120,.26)', disp:"'Cormorant Garamond',Georgia,serif", sans:"'Jost',system-ui,sans-serif", dark:true, tag:'Colour, considered for a century.', mood:'Estate heritage — muted greens, archival typography, room-story merchandising.' },
+ { key:'texture', label:'Texture', model:'Arte International',bg:'#0f0d0b', panel:'#191510', ink:'#f1ece3', gold:'#c9a24b', line:'rgba(201,162,75,.28)', disp:"'Cormorant Garamond',Georgia,serif", sans:"'Jost',system-ui,sans-serif", dark:true, tag:'Material is the message.', mood:'Immersive texture — full-bleed material macros, dark gallery chrome, slow motion.' },
+ { key:'gallery', label:'Gallery', model:'1stDibs', bg:'#101012', panel:'#1a1a1e', ink:'#f4f2ee', gold:'#caa96a', line:'rgba(202,169,106,.26)', disp:"'Playfair Display',Georgia,serif", sans:"'Inter',system-ui,sans-serif", dark:true, tag:'The marketplace of extraordinary walls.', mood:'Marketplace-luxe — curated collections, provenance chips, designer-first navigation.' },
+];
+
+/* ---- chart data straight from the snapshot ---------------------------------- */
+const CHART = {
+ cadence: { labels: (C.activation_cadence || []).map(w => w.week), added: (C.activation_cadence || []).map(w => w.added) },
+ vendors: { labels: (C.top_vendors || []).slice(0, 10).map(v => v.vendor), counts: (C.top_vendors || []).slice(0, 10).map(v => v.active) },
+ types: { labels: (C.types || []).slice(0, 6).map(t => t.type), counts: (C.types || []).slice(0, 6).map(t => t.active) },
+ integrity: {
+ labels: ['Missing sellable variant', 'Missing sample variant', 'Zero / null price', 'Missing image', 'Missing description'],
+ counts: [FF.missing_sellable || 0, FF.missing_sample || 0, FF.zero_price || 0, FF.missing_image || 0, FF.missing_description || 0],
+ },
+ bands: { labels: (C.price_bands || []).map(b => b.band), counts: (C.price_bands || []).map(b => b.count) },
+ channels: { labels: (SNAP.channels || []).map(c => c.label || c.key), accounts: (SNAP.channels || []).map(c => c.accounts || 0) },
+ sampleOnlyVendors: { labels: (C.sample_only_vendors || []).map(v => v.vendor), counts: (C.sample_only_vendors || []).map(v => v.count) },
+ // Analyst-scored competitive read (authority vs digital polish, 0-100) — analyst tier
+ comp: { labels: ['Designer Wallcoverings', 'DecoratorsBest', 'Burke Decor', 'Mahones', 'Finest Wallpaper', "Steve's B&W"],
+ catalog: [96, 62, 48, 55, 40, 45], digital: [58, 82, 78, 60, 42, 55] },
+};
+
+/* ---- map: DW + tracked competitor HQs (analyst-compiled geo) ---------------- */
+const MAP_POINTS = [
+ { name: 'Designer Wallcoverings — Los Angeles', lat: 34.076, lng: -118.377, you: true, note: 'HQ · showroom · ' + fmt(FF.active_total) + ' live SKUs' },
+ { name: 'DecoratorsBest', lat: 40.752, lng: -73.993, note: 'New York, NY — designer-brand e-commerce' },
+ { name: 'Burke Decor', lat: 41.099, lng: -80.649, note: 'Youngstown, OH — home decor + wallpaper' },
+ { name: "Mahone's Wallpaper Shop", lat: 37.089, lng: -76.473, note: 'Newport News, VA — wallpaper specialist' },
+ { name: 'Finest Wallpaper', lat: 43.09, lng: -79.08, note: 'Ontario, Canada — designer lines, US/CA pricing' },
+ { name: "Steve's Blinds & Wallpaper", lat: 42.58, lng: -83.03, note: 'Sterling Heights, MI — discount volume' },
+];
+
+/* -------------------------------------------------------------- SWOT agent --- */
+const SWOT_INPUT = {
+ strengths: [
+ `${fmt(FF.active_total)} live SKUs across ${fmt(C.vendors_active)} vendor lines — one of the deepest designer-wallcovering catalogs online`,
+ `A ${fmt(SNAP.fleet?.count)}-site microsite fleet feeding discovery back to the flagship`,
+ `${(SNAP.channels || []).filter(c => c.connected).length}/7 social channels connected through one marketing command center`,
+ 'Private-label lines with owned margin (Phillipe Romano, Hollywood Wallcoverings, Malibu Wallpaper)',
+ '30+ years of trade relationships; memo-sample program ($4.25) as a proven funnel entry',
+ 'Automated activation drip already shipping ~500 products/day, textures-first',
+ ],
+ weaknesses: [
+ `${fmt(SO.backlog)} active products are sample-only WITHOUT a quote-only designation — browseable but not buyable`,
+ `${fmt(FF.zero_price)} actives carry zero/null pricing; ${fmt(FF.missing_image)} lack a featured image`,
+ 'Social reach is broad (80 FB pages, 34 IG accounts) but thin — distribution without engagement depth',
+ 'No social→revenue attribution discipline (UTM/coupon per channel) yet',
+ 'Flagship UX carries catalog weight — 80k SKUs need stronger guided curation for retail buyers',
+ ],
+ opportunities: [
+ `Convert the ${fmt(SO.backlog)} sample-only backlog into sellable variants — the single largest dormant-revenue pool in the business`,
+ `${fmt(C.drafts_total)} staged drafts (${fmt(C.drafts_stageable)} fully stageable today) = months of "New Arrivals" marketing fuel`,
+ 'AEO/AI-answer citations for wallcovering queries — the flagship already ships an AEO block; extend it fleet-wide',
+ 'Sample-order → full-roll conversion funnel instrumentation (order sync to the back office already exists)',
+ 'Licensing original design IP (settlement-gated) into marketplaces as a zero-inventory revenue line',
+ ],
+ threats: [
+ 'DTC-native entrants own the "approachable wallpaper" narrative with modern brand voices',
+ 'Marketplace aggregators (Amazon, Wayfair, Etsy) commoditize mid-tier patterns',
+ 'AI answer engines could disintermediate catalog-depth advantages if citations go to competitors',
+ 'Vendor MAP / brand-control tightening limits pricing latitude on marquee lines',
+ ],
+};
+function swotAgent(input) {
+ const quad = (key, title, cls) => `<div class="swotq ${cls}"><h3>${title}</h3><ul>${(input[key] || []).map(x => `<li>${x}</li>`).join('')}</ul></div>`;
+ return `<div class="swotgrid">${quad('strengths', 'Strengths', 'pos')}${quad('weaknesses', 'Weaknesses', 'neg')}${quad('opportunities', 'Opportunities', 'pos')}${quad('threats', 'Threats', 'neg')}</div>`;
+}
+const swotGrid = swotAgent(SWOT_INPUT);
+
+/* ----------------------------------------------------------- tables & rows --- */
+const compRows = (SNAP.competitors || []).map(c =>
+ `<tr><td><b>${c.name}</b></td><td>${c.domain}</td><td>${c.enabled ? 'Active watch' : 'Paused'}</td><td>${fmt(c.products_found)}</td><td>${c.notes || ''}</td></tr>`).join('');
+
+const channelRows = (SNAP.channels || []).map(c =>
+ `<tr><td><b>${c.label || c.key}</b></td><td>${c.connected ? '<span class="good">Connected</span>' : '<span class="flag">Not connected</span>'}</td><td>${fmt(c.accounts)}</td><td>${c.note || (c.connected ? 'Live in the marketing command center' : '')}</td></tr>`).join('');
+
+const vendorRows = (C.top_vendors || []).map((v, i) =>
+ `<tr><td class="mo">${String(i + 1).padStart(2, '0')}</td><td><b>${v.vendor}</b></td><td>${fmt(v.active)}</td></tr>`).join('');
+
+const soVendorRows = (C.sample_only_vendors || []).map(v =>
+ `<tr><td><b>${v.vendor}</b></td><td>${fmt(v.count)}</td></tr>`).join('');
+
+const fleetChips = (SNAP.fleet?.sites || []).slice(0, 48).map(s =>
+ `<span class="fchip">${String(s.host).replace('.designerwallcoverings.com', '')}</span>`).join('');
+
+const partners = [
+ ['Interior-design trade programs (ASID, IIDA chapters)', 'The trade IS the buyer. Chapter sponsorships + a designer-net portal turn 30 years of relationships into a structured acquisition channel.'],
+ ['Professional installers / paper-hangers network', 'An installer directory referral loop: DW sends install-ready clients, installers send spec-stage clients. Both sides win on every roll.'],
+ ['Boutique hotels & hospitality designers', 'Contract lines (Type II) already in catalog — a hospitality lookbook + spec-sheet service opens recurring project-scale orders.'],
+ ['Real-estate stagers & luxury listing agents', 'Statement walls sell listings. A stager program (rapid samples + the peel-and-stick line) creates repeat commercial buyers.'],
+ ['Art-print & framing houses', 'The art-print line proves the adjacency: walls + art as one "finished room" offer, cross-sold at zero acquisition cost.'],
+ ['Paint brands & color consultants', 'Color-matched pairings ("this paper + these three paints") — co-marketing that borrows the paint brand\'s search volume.'],
+ ['Design schools (LA trade programs)', 'Student memo access + a young-designer program seeds the next decade of trade accounts for the cost of samples.'],
+ ['Film / TV set decorators', 'LA-native advantage: a set-decorator fast lane (rush memos, buyout-friendly licensing) monetizes proximity to the studios.'],
+];
+const partnerRows = partners.map((p, i) => `<div class="pcard rv"><div class="pnum">${String(i + 1).padStart(2, '0')}</div><div><h4>${p[0]}</h4><p>${p[1]}</p></div></div>`).join('');
+
+const calendar = [
+ ['Jan', 'New-year refresh intent peaks', 'Push "one statement wall" entry offers; retarget Q4 samplers'],
+ ['Feb', 'Design-award season', 'Editorial: trend reports off the catalog\'s own tag data'],
+ ['Mar', 'Spring project starts', 'Trade outreach wave; hospitality spec season begins'],
+ ['Apr', 'High-intent renovation search', 'Paid search on pattern + brand terms; AEO content sprint'],
+ ['May', 'Peak sample-ordering', 'Sample-bundle promos; instrument sample→roll conversion'],
+ ['Jun', 'Mid-year new-arrivals surge', 'The activation drip = daily "new" stories across channels'],
+ ['Jul', 'Summer install season', 'Installer-partner co-marketing; project galleries'],
+ ['Aug', 'Pre-fall trade buying', 'Designer-net program push; hospitality lookbook release'],
+ ['Sep', 'Fall flagship season', 'Concept-direction launch (the new front page ships here)'],
+ ['Oct', 'Q4 project commits', 'Retarget spring samplers; gift-adjacent art-line cross-sell'],
+ ['Nov', 'Holiday statement walls', 'Peel-and-stick line forward; fast-ship messaging'],
+ ['Dec', 'Planning season', 'Year-in-review design content; January intent capture'],
+];
+const calRows = calendar.map(c => `<tr><td class="mo">${c[0]}</td><td>${c[1]}</td><td class="act">${c[2]}</td></tr>`).join('');
+
+const CATS = [
+ ['summary', 'Executive Summary'], ['swot', 'SWOT Analysis'], ['empire', 'The Catalog Empire'],
+ ['integrity', 'Catalog Integrity — the 5-Field Read'], ['competitors', 'Competitive Landscape'],
+ ['advertising', 'Channels & Distribution'], ['timing', 'Timing & Cadence'],
+ ['audit', 'Website Audit'], ['social', 'Social Audit'], ['suggested', 'Suggested New Flagships'],
+ ['partners', 'Unlikely Partners'], ['revenue', 'Unlikely Revenue'],
+ ['desk', 'Live Commerce Desk'], ['roadmap', '90-Day Roadmap'], ['sources', 'Sources & Methodology'],
+];
+
+/* ---- sources & provenance ---------------------------------------------------- */
+const SRC_TIER = {
+ live: ['Live snapshot', 'r'], observed: ['Observed live', 'o'], derived: ['Computed', 'd'],
+ analyst: ['Analyst view', 'a'], estimate: ['Illustrative', 'e'],
};
+const SOURCES = [
+ ['Catalog KPIs — statuses, vendors, types, integrity, cadence', 'The dw_unified local mirror (READ-ONLY psql over the /tmp socket)', `Collected by <code>scripts/collect-dw.mjs</code> at <b>${collectedLabel}</b>; every number on this page renders from that snapshot`, 'live'],
+ ['5-field / sample-only split', 'Mirror rollup columns (has_sample_variant, has_product_variant, has_description, image_url) + the quotes tag', 'Direct SQL counts; quote-only lines (by-design sample-only) separated from true backlog', 'live'],
+ ['Social channel status', 'The DW marketing command center API (marketing.designerwallcoverings.com)', 'Authenticated status read at collection time — connected flags + account counts per platform', 'live'],
+ ['Microsite fleet', 'The fleet aggregator directory API (all.designerwallcoverings.com)', `${fmt(SNAP.fleet?.count)} sites enumerated at collection time`, 'live'],
+ ['Competitor watch-list', 'The connie_competitors table (the DW competitor-scan registry)', 'Rendered verbatim: domain, watch status, products found by prior scans', 'live'],
+ ['Competitor scoring chart + map pins', 'Analyst assessment over public sites; HQ geo compiled from public records', 'Authored consulting view — NOT scraped metrics; the map is oriented, not surveyed', 'analyst'],
+ ['Price-band chart', C.price_bands_basis || 'Priced subset of the mirror', 'Partial-basis chart, labeled as such — full variant pricing lives Shopify-side', 'derived'],
+ ['Website & social audits, partners, revenue plays, roadmap', 'Analyst strategy grounded in the operating knowledge of the DW stack', 'Consulting recommendations — models and plays, not measurements', 'analyst'],
+ ['Hero & section imagery', 'Unsplash editorial stock (luxury materials, per the luxe-only imagery rule)', 'Hotlinked, decorative only — carries no data meaning', 'estimate'],
+];
+const srcRows = SOURCES.map(s => { const t = SRC_TIER[s[3]] || ['—', 'a']; return `<tr><td><b>${s[0]}</b></td><td>${s[1]}</td><td>${s[2]}</td><td class="srccell"><span class="srcb ${t[1]}">${t[0]}</span></td></tr>`; }).join('');
+const srcLegend = [...new Set(SOURCES.map(s => s[3]))].map(k => { const t = SRC_TIER[k]; return `<span class="srcb ${t[1]}">${t[0]}</span>`; }).join('');
+
+const houseTiles = HOUSES.map(h => `
+ <a class="vtile rv" href="/versions/${h.key}.html" target="_blank" style="--vb:${h.bg};--vi:${h.ink};--vg:${h.gold}">
+ <div class="vswatch"><span style="background:${h.bg}"></span><span style="background:${h.panel}"></span><span style="background:${h.gold}"></span><span style="background:${h.ink}"></span></div>
+ <div class="vname">${h.label}</div><div class="vmodel">after ${h.model}</div>
+ <div class="vmood">${h.mood}</div><div class="vopen">Open live concept →</div>
+ </a>`).join('');
-const esc = (s) => String(s || '').replace(/[&<>]/g, c => ({ '&':'&','<':'<','>':'>' }[c]));
-const goals = (client.goals || []).slice(0, 4);
+const navLinks = CATS.map(c => `<a href="#${c[0]}">${c[1].replace(/&/g, '&')}</a>`).join('');
+const heroSlides = HERO_IMGS.map((u, i) => `<div class="slide${i === 0 ? ' on' : ''}" style="background-image:url('${u}')"></div>`).join('');
+const connectedCount = (SNAP.channels || []).filter(c => c.connected).length;
-for (const [name, s] of Object.entries(SKINS)) {
- const html = `<!doctype html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>${esc(client.business_name)} — ${s.vibe}</title>
+/* =========================================================== the portal app === */
+const app = `<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Growth Strategy</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
+<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
+<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<style>
-:root{--bg:${s.bg};--ink:${s.ink};--accent:${s.accent}}
-*{box-sizing:border-box}body{margin:0;font-family:${s.font};background:var(--bg);color:var(--ink)}
-.bar{padding:14px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--accent)}
-.bar b{letter-spacing:.06em}.bar span{color:var(--accent);font-size:12px;text-transform:uppercase;letter-spacing:.2em}
-.hero{padding:90px 30px;text-align:center}
-.hero .k{color:var(--accent);letter-spacing:.3em;text-transform:uppercase;font-size:12px}
-.hero h1{font-size:56px;margin:.2em 0;font-weight:700}
-.hero p{font-size:20px;max-width:620px;margin:0 auto;opacity:.8}
-.cta{display:inline-block;margin-top:26px;background:var(--accent);color:var(--bg);padding:14px 32px;text-decoration:none;text-transform:uppercase;letter-spacing:.16em;font-size:13px}
-.goals{max-width:900px;margin:40px auto;padding:0 30px;display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:18px}
-.goals div{border:1px solid var(--accent);padding:22px;font-size:17px}
-.foot{padding:40px 30px;text-align:center;opacity:.6;font-size:13px}
+:root{--bg:#0e0c09;--panel:#171310;--ink:#f1ece3;--gold:#c9a24b;--line:rgba(201,162,75,.22);--dim:rgba(241,236,227,.66)}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Jost',system-ui,sans-serif;font-size:19px;line-height:1.75;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Cormorant Garamond',Georgia,serif}a{color:inherit;text-decoration:none}
+.bar{position:fixed;top:0;left:0;right:0;z-index:40;display:flex;align-items:center;justify-content:space-between;padding:18px 34px;background:linear-gradient(180deg,rgba(14,12,9,.94),rgba(14,12,9,0))}
+.burger{width:30px;height:20px;position:relative;cursor:pointer;background:none;border:0}.burger span{position:absolute;left:0;right:0;height:1.6px;background:var(--ink);transition:.35s}
+.burger span:nth-child(1){top:1px}.burger span:nth-child(2){top:9px}.burger span:nth-child(3){top:17px}
+body.nav .burger span:nth-child(1){transform:translateY(8px) rotate(45deg)}body.nav .burger span:nth-child(2){opacity:0}body.nav .burger span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
+.stamp{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);display:flex;gap:10px;align-items:center}
+.stamp button{background:none;border:1px solid var(--line);color:var(--gold);font-family:'Jost';font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:6px 12px;cursor:pointer}
+.stamp button:hover{background:var(--gold);color:var(--bg)}
+.menu{position:fixed;top:0;left:0;bottom:0;width:min(420px,86vw);z-index:39;background:var(--panel);border-right:1px solid var(--line);transform:translateX(-100%);transition:.42s cubic-bezier(.6,0,.2,1);padding:92px 40px;overflow:auto}
+.mbrand{display:block;font-family:'Cormorant Garamond',serif;font-size:24px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink);margin-bottom:28px}
+.mbrand span{color:var(--gold)}
+.mbrand small{display:block;font-family:'Jost',system-ui,sans-serif;font-size:9px;letter-spacing:.32em;color:var(--gold);margin-top:4px}
+body.nav .menu{transform:none}body.nav .scrim{opacity:1;pointer-events:auto}
+.scrim{position:fixed;inset:0;z-index:38;background:rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:.42s}
+.menu .mh{font-family:'Cormorant Garamond',serif;font-size:13px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold);margin-bottom:18px}
+.menu a{display:block;font-family:'Cormorant Garamond',serif;font-size:23px;padding:9px 0;border-bottom:1px solid var(--line);opacity:.85;transition:.25s}
+.menu a:hover{opacity:1;color:var(--gold);padding-left:8px}
+.menu .minfo{margin-top:28px;border-top:1px solid var(--line);padding-top:20px}.menu .minfo p{font-size:13px;line-height:1.7;color:var(--dim);border:0;padding:2px 0}
+.hero{min-height:96vh;position:relative;display:flex;flex-direction:column;justify-content:center;padding:0 clamp(24px,7vw,120px);overflow:hidden}
+.slides{position:absolute;inset:0;z-index:0}
+.slide{position:absolute;inset:0;background-size:cover;background-position:center;opacity:0;transform:scale(1.04);transition:opacity 1.4s ease;will-change:transform,opacity}
+.slide.on{opacity:1;animation:kenburns 13s ease-out forwards}
+@keyframes kenburns{from{transform:scale(1.04) translate3d(0,0,0)}to{transform:scale(1.13) translate3d(-1.4%,-1.2%,0)}}
+.hero:after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,rgba(14,12,9,.94),rgba(14,12,9,.62) 55%,rgba(14,12,9,.35));z-index:1}
+.hero .in{position:relative;z-index:2;max-width:960px}
+.kick{font-size:12px;letter-spacing:.4em;text-transform:uppercase;color:var(--gold);margin-bottom:22px}
+.hero h1{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(40px,6.6vw,92px);line-height:1.02}.hero h1 span{color:var(--gold)}
+.hero p{max-width:64ch;margin-top:24px;font-size:18px;color:var(--dim)}
+.metrics{display:flex;flex-wrap:wrap;gap:46px;margin-top:46px}
+.metrics .v{font-family:'Cormorant Garamond',serif;font-size:40px;color:var(--gold);line-height:1}
+.metrics .l{font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);margin-top:6px}
+section{padding:0 clamp(24px,7vw,120px);border-top:1px solid var(--line);scroll-margin-top:60px}
+.accbar{display:flex;gap:12px;justify-content:flex-end;padding:14px clamp(24px,7vw,120px);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
+.accbar button{background:none;border:1px solid var(--line);color:var(--gold);font-family:'Jost';font-size:11px;letter-spacing:.18em;text-transform:uppercase;padding:9px 18px;cursor:pointer}.accbar button:hover{background:var(--gold);color:var(--bg)}
+.acchead{width:100%;text-align:left;background:none;border:0;cursor:pointer;display:flex;gap:22px;padding:36px 0;color:var(--ink)}
+.acchead .htext{flex:1}.eyebrow{font-size:12.5px;letter-spacing:.36em;text-transform:uppercase;color:var(--gold);margin-bottom:12px}
+h2{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(30px,4.4vw,54px);line-height:1.05;max-width:22ch}
+.acchead .chev{font-family:'Cormorant Garamond',serif;font-size:36px;color:var(--gold);transition:.3s;line-height:.7}
+section.open .chev{transform:rotate(45deg)}.acchead:hover h2{color:var(--gold);transition:.25s}
+.accbody{display:none;padding-bottom:60px}section.open .accbody{display:block;animation:af .45s ease}
+@keyframes af{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
+.lead2{max-width:72ch;color:var(--dim);margin-top:6px;font-size:20px}
+table{width:100%;border-collapse:collapse;margin-top:34px;font-size:16px}th,td{text-align:left;padding:15px 14px;border-bottom:1px solid var(--line);vertical-align:top;font-size:15.5px}
+th{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);font-weight:400}
+tr.you{background:rgba(201,162,75,.09)}tr.you td:first-child{color:var(--gold)}
+td.mo{font-family:'Cormorant Garamond',serif;color:var(--gold);font-size:18px;width:60px}
+.chartwrap{margin-top:34px;background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:22px 20px 14px;position:relative;height:340px}
+.chartwrap.tall{height:410px}.chartwrap .ct{font-family:'Cormorant Garamond',serif;font-size:15px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);margin-bottom:10px}
+.cards2{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1px;background:var(--line);margin-top:34px}
+.cards2 .c{background:var(--bg);padding:32px 28px}.cards2 .c h3{font-family:'Cormorant Garamond',serif;font-size:22px;color:var(--gold);margin-bottom:10px}.cards2 .c p{color:var(--dim);font-size:16px;line-height:1.6}
+.flag{color:#e8a0a0}.good{color:#9fd6b0}
+.swotgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1px;background:var(--line);margin-top:34px}
+.swotq{background:var(--bg);padding:28px 26px}.swotq h3{font-family:'Cormorant Garamond',serif;font-size:22px;margin-bottom:12px}
+.swotq.pos{border-top:2px solid #9fd6b0}.swotq.neg{border-top:2px solid #e8a0a0}
+.swotq.pos h3{color:#9fd6b0}.swotq.neg h3{color:#e8a0a0}
+.swotq ul{margin:0;padding-left:18px}.swotq li{color:var(--dim);font-size:15px;line-height:1.55;margin:6px 0}
+.srclegend{display:flex;flex-wrap:wrap;gap:10px;margin:26px 0 4px}
+.srcb{display:inline-block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:5px 11px;border-radius:3px;border:1px solid var(--line);white-space:nowrap}
+.srcb.r{color:var(--gold)}.srcb.o{color:#78aaff;border-color:rgba(120,170,255,.4)}.srcb.d{color:#b78d3f}.srcb.a{color:var(--dim)}.srcb.e{color:#e8a0a0;border-color:rgba(232,160,160,.4)}
+td.srccell{white-space:nowrap;vertical-align:middle}
+.accbody td code{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;color:var(--ink);background:rgba(201,162,75,.12);padding:1px 6px;border-radius:3px}
+.srcnote{margin-top:34px;display:flex;gap:22px;padding:28px 30px;border:1px solid var(--line);background:var(--panel)}
+.srcnote .i{font-size:26px;color:var(--gold);line-height:1}
+.srcnote h4{font-family:'Cormorant Garamond',serif;font-size:21px;color:var(--gold);margin-bottom:8px}
+.srcnote p{color:var(--dim);font-size:15px;line-height:1.6}
+.srcnote code{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;color:var(--ink);background:rgba(201,162,75,.12);padding:1px 6px;border-radius:3px}
+.flagbox{display:flex;gap:22px;margin-top:34px;padding:30px 32px;border:1px solid var(--gold);background:rgba(201,162,75,.07)}
+.flagbox .i{font-size:30px;color:var(--gold)}.flagbox h3{font-family:'Cormorant Garamond',serif;font-size:24px;color:var(--gold);margin-bottom:10px}.flagbox p{color:var(--ink);opacity:.92;font-size:16px;line-height:1.6}
+.vgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px;margin-top:20px}
+.vtile{background:var(--vb);border:1px solid var(--line);padding:28px 26px;transition:.3s;position:relative}.vtile:hover{transform:translateY(-5px);box-shadow:0 22px 60px rgba(0,0,0,.55)}
+.vswatch{display:flex;height:36px;border-radius:3px;overflow:hidden;margin-bottom:20px}.vswatch span{flex:1}
+.vname{font-family:'Cormorant Garamond',serif;font-size:26px;color:var(--vi)}.vmodel{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--vg);margin-top:2px}
+.vmood{color:var(--vi);opacity:.72;font-size:13px;margin-top:10px;min-height:38px}.vopen{margin-top:16px;font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--vg)}
+.pcard{display:flex;gap:22px;padding:24px 0;border-bottom:1px solid var(--line)}.pnum{font-family:'Cormorant Garamond',serif;font-size:30px;color:var(--gold);min-width:44px}.pcard h4{font-family:'Cormorant Garamond',serif;font-size:21px;margin-bottom:6px}.pcard p{color:var(--dim);font-size:16px;line-height:1.6}
+.sugg{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1px;background:var(--line);margin-top:20px}.sugg .s{background:var(--bg);padding:26px 24px}.sugg .s .p{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold)}.sugg .s h4{font-family:'Cormorant Garamond',serif;font-size:20px;margin:8px 0}.sugg .s p{font-size:15px;color:var(--dim);line-height:1.55}
+.road{list-style:none;margin-top:20px;position:relative;padding-left:36px}
+.road:before{content:'';position:absolute;left:9px;top:10px;bottom:10px;width:2px;background:linear-gradient(180deg,var(--gold),rgba(201,162,75,.14));transform:scaleY(0);transform-origin:top;transition:transform 1.5s cubic-bezier(.5,0,.2,1)}
+.road.drawn:before{transform:scaleY(1)}
+.road li{padding:22px 0;border-bottom:1px solid var(--line);display:flex;gap:26px;position:relative}
+.road li:before{content:'';position:absolute;left:-32px;top:30px;width:12px;height:12px;border-radius:50%;background:var(--bg);border:2px solid var(--gold);box-shadow:0 0 0 4px var(--bg);transform:scale(0);transition:transform .5s cubic-bezier(.2,1.5,.4,1)}
+.road.drawn li:before{transform:scale(1)}
+.road.drawn li:nth-child(1):before{transition-delay:.30s}.road.drawn li:nth-child(2):before{transition-delay:.62s}.road.drawn li:nth-child(3):before{transition-delay:.94s}.road.drawn li:nth-child(4):before{transition-delay:1.26s}
+.road .w{font-family:'Cormorant Garamond',serif;color:var(--gold);font-size:15px;letter-spacing:.2em;text-transform:uppercase;min-width:130px}.road .d{color:var(--dim)}
+@media(prefers-reduced-motion:reduce){.slide.on{animation:none;transform:scale(1)}.road:before{transition:none;transform:scaleY(1)}.road li:before{transition:none;transform:scale(1)}.accbody{animation:none!important}}
+.rv{opacity:0;transform:translateY(22px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+#compmap{height:420px;border:1px solid var(--line);border-radius:8px;margin-top:34px;background:#0a0908}
+.leaflet-container{background:#0a0908;font-family:'Jost',sans-serif}
+.leaflet-popup-content-wrapper{background:var(--panel);color:var(--ink);border:1px solid var(--line)}
+.leaflet-popup-tip{background:var(--panel)}
+.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin-top:34px}
+.kpi{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:22px 20px}
+.kpi .kv{font-family:'Cormorant Garamond',serif;font-size:34px;color:var(--gold);line-height:1}
+.kpi .kl{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);margin-top:8px}
+.fchips{display:flex;flex-wrap:wrap;gap:8px;margin-top:24px}
+.fchip{font-size:11px;letter-spacing:.06em;border:1px solid var(--line);color:var(--dim);padding:5px 11px;border-radius:3px}
+footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color:var(--dim);font-size:12px;letter-spacing:.14em;text-transform:uppercase;display:flex;justify-content:space-between;flex-wrap:wrap;gap:20px}
+@media(max-width:640px){.metrics{gap:26px}}
</style></head><body>
-<div class="bar"><b>${esc(client.business_name)}</b><span>${s.vibe} concept</span></div>
-<div class="hero">
- <div class="k">${esc(client.industry || '')} ${client.location ? '· ' + esc(client.location) : ''}</div>
- <h1>${esc(client.business_name)}</h1>
- <p>${esc(client.tagline || 'A new website concept, ready to make your first impression unforgettable.')}</p>
- <a class="cta" href="#">Get in touch</a>
+<header class="bar">
+ <button class="burger" onclick="document.body.classList.toggle('nav')" aria-label="Menu" aria-expanded="false" aria-controls="portalmenu"><span></span><span></span><span></span></button>
+ <div class="stamp"><span>Data collected ${collectedLabel}</span><button id="refbtn" title="Re-run the read-only collector">↻ Refresh data</button></div>
+</header>
+<div class="scrim" onclick="document.body.classList.remove('nav')"></div>
+<nav class="menu" id="portalmenu" onclick="if(event.target.closest('a'))document.body.classList.remove('nav')">
+ <a class="mbrand" href="#summary">Designer <span>Wallcoverings</span><small>Growth Strategy · 2026</small></a>
+ <div class="mh">Contents</div>${navLinks}
+ <div class="minfo"><div class="mh">${BIZ.name}</div><p>${BIZ.area}</p><p>${BIZ.email}</p><p>${BIZ.site}</p></div>
+</nav>
+
+<div class="hero" id="summary">
+ <div class="slides">${heroSlides}</div>
+ <div class="in">
+ <div class="kick">${BIZ.area} · Confidential strategy brief · prepared for Steve Abrams</div>
+ <h1 class="disp">Designer <span>Wallcoverings</span></h1>
+ <p>Thirty years of trade authority, <b>${fmt(FF.active_total)} live SKUs</b> across <b>${fmt(C.vendors_active)} vendor lines</b>, a <b>${fmt(SNAP.fleet?.count)}-site</b> discovery fleet, and <b>${connectedCount} connected social channels</b> — the deepest designer-wallcovering operation online. The opportunity isn't building an audience; it's converting the catalog's dormant depth (a ${fmt(SO.backlog)}-product sellable-variant backlog, ${fmt(C.drafts_total)} staged drafts) into measured revenue. This brief maps exactly that, from the live data.</p>
+ <div class="metrics">
+ <div class="m"><div class="v" data-c="${FF.active_total || 0}">0</div><div class="l">Live SKUs (active)</div></div>
+ <div class="m"><div class="v" data-c="${C.vendors_active || 0}">0</div><div class="l">Vendor lines</div></div>
+ <div class="m"><div class="v" data-c="${SNAP.fleet?.count || 0}">0</div><div class="l">Microsite fleet</div></div>
+ <div class="m"><div class="v" data-c="${C.drafts_total || 0}">0</div><div class="l">Staged drafts (fuel)</div></div>
+ </div>
+ </div>
</div>
-${goals.length ? '<div class="goals">' + goals.map(g => '<div>' + esc(g) + '</div>').join('') + '</div>' : ''}
-<div class="foot">Concept "${name}" · generated ${client.generated_at || ''} · one of several directions to choose from.</div>
+
+<div class="accbar"><button id="xall">Expand all</button><button id="call">Collapse all</button></div>
+
+<section id="swot"><div class="eyebrow">Strategic Snapshot · SWOT</div><h2 class="disp">The whole board on one screen.</h2><div class="accbody">
+ <p class="lead2">Four lenses over the live snapshot — internal <b>Strengths</b> and <b>Weaknesses</b>, external <b>Opportunities</b> and <b>Threats</b> — so the strategy that follows starts from one honest picture. Every number here is from the ${collectedLabel} collection.</p>
+ ${swotGrid}
+ <div class="flagbox" style="margin-top:34px"><div class="i">⚡</div><div><h3 class="disp">The one-sentence thesis</h3><p>DW's moat is <b>catalog depth + trade authority</b>; its constraint is <b>conversion infrastructure</b>. The fastest wins activate what already exists — the sample-only backlog, the staged-draft drip, the connected-but-quiet channels — before building anything new.</p></div></div>
+</div></section>
+
+<section id="empire"><div class="eyebrow">01 · The Catalog Empire</div><h2 class="disp">Not a store. A catalog empire.</h2><div class="accbody">
+ <p class="lead2">The live mirror shows <b>${fmt(FF.active_total)}</b> active products, <b>${fmt(C.drafts_total)}</b> staged drafts, and <b>${fmt((C.statuses || {}).ARCHIVED)}</b> archived — a merchandising engine with more inventory in reserve than most competitors have in total. Distribution runs through the flagship plus a <b>${fmt(SNAP.fleet?.count)}-site</b> microsite fleet.</p>
+ <div class="chartwrap tall"><div class="ct">Top vendor lines by live products</div><canvas id="vendorChart"></canvas></div>
+ <div class="chartwrap"><div class="ct">Live catalog by product type</div><canvas id="typeChart"></canvas></div>
+ <table><thead><tr><th>#</th><th>Vendor line</th><th>Active products</th></tr></thead><tbody>${vendorRows}</tbody></table>
+ <div class="eyebrow" style="margin-top:52px">The discovery fleet</div>
+ <p class="lead2">${fmt(SNAP.fleet?.count)} microsites — material-, era-, and city-specific storefront satellites that catch long-tail search and funnel to the flagship. A sample:</p>
+ <div class="fchips">${fleetChips}</div>
+</div></section>
+
+<section id="integrity"><div class="eyebrow">02 · Catalog Integrity — the 5-Field Read</div><h2 class="disp">Where the catalog leaks revenue.</h2><div class="accbody">
+ <p class="lead2">The house rule: every active product needs a sample variant, a sellable variant, complete pricing, a description, and tags — plus a featured image. Against ${fmt(FF.active_total)} actives, the live counts:</p>
+ <div class="chartwrap"><div class="ct">Actives failing each field (live mirror counts)</div><canvas id="ffChart"></canvas></div>
+ <div class="flagbox"><div class="i">◆</div><div><h3 class="disp">The ${fmt(SO.backlog)}-product finding</h3><p><b>${fmt(SO.total)}</b> actives are sample-only. <b>${fmt(SO.quote_only_by_design)}</b> of those are quote-only lines by design. The remaining <b>${fmt(SO.backlog)}</b> — a third of the live catalog — can be browsed and sampled but not bought. Every one is paid-for merchandising with the register removed. This is the single largest dormant-revenue pool in the business.</p></div></div>
+ <div class="chartwrap"><div class="ct">Sample-only actives — where they sit (top lines)</div><canvas id="soChart"></canvas></div>
+ <table><thead><tr><th>Vendor line</th><th>Sample-only actives</th></tr></thead><tbody>${soVendorRows}</tbody></table>
+</div></section>
+
+<section id="competitors"><div class="eyebrow">03 · Competitive Landscape</div><h2 class="disp">Depth vs. polish: the field.</h2><div class="accbody">
+ <p class="lead2">DW's tracked competitor registry, rendered verbatim, plus an analyst read: DW wins on catalog depth and trade authority; the DTC natives win on front-end polish and brand voice. The play is closing the polish gap without surrendering the depth moat.</p>
+ <div class="chartwrap"><div class="ct">Catalog depth vs. digital polish — analyst-scored, 0–100</div><canvas id="compChart"></canvas></div>
+ <table><thead><tr><th>Competitor</th><th>Domain</th><th>Watch status</th><th>Products found</th><th>Notes</th></tr></thead><tbody>${compRows}</tbody></table>
+ <div id="compmap"></div>
+ <p class="lead2" style="font-size:15px;margin-top:14px;opacity:.7">The field, mapped: DW in Los Angeles vs. tracked competitor HQs (analyst-compiled geo). LA proximity to the design trade + studios is a structural advantage none of them share.</p>
+</div></section>
+
+<section id="advertising"><div class="eyebrow">04 · Channels & Distribution</div><h2 class="disp">Seven channels, one command center.</h2><div class="accbody">
+ <p class="lead2">Live from the marketing command center at collection time: <b>${connectedCount} of ${(SNAP.channels || []).length}</b> platforms connected. The Facebook page network alone spans <b>${fmt((SNAP.channels || []).find(c => c.key === 'facebook')?.accounts)}</b> pages; Instagram <b>${fmt((SNAP.channels || []).find(c => c.key === 'instagram')?.accounts)}</b> accounts. The infrastructure exists — the discipline to convert reach into attributed revenue is the build.</p>
+ <div class="chartwrap"><div class="ct">Connected accounts per platform (live)</div><canvas id="chanChart"></canvas></div>
+ <table><thead><tr><th>Platform</th><th>Status</th><th>Accounts</th><th>Note</th></tr></thead><tbody>${channelRows}</tbody></table>
+ <div class="cards2">
+ <div class="c"><h3>Attribution first</h3><p>Per-channel UTM + coupon discipline before spend scales. Today reach is broad but revenue attribution is dark — no channel can prove its keep.</p></div>
+ <div class="c"><h3>New-arrivals engine</h3><p>The activation drip ships ~500 products/day. Each batch is a native "new" story for every channel — content fuel most brands would pay to manufacture.</p></div>
+ <div class="c"><h3>AEO / AI answers</h3><p>The flagship already ships AI-answer-optimized collection copy. Extending AEO fleet-wide targets the search channel that's growing while classic SERP flattens.</p></div>
+ </div>
+</div></section>
+
+<section id="timing"><div class="eyebrow">05 · Timing & Cadence</div><h2 class="disp">The drip is live. Point it at revenue.</h2><div class="accbody">
+ <p class="lead2">New actives per week from the live mirror — the activation engine at work. The merchandising calendar below aligns campaigns to the natural intent cycle of the category.</p>
+ <div class="chartwrap"><div class="ct">New active products per week — last 12 weeks (live)</div><canvas id="cadenceChart"></canvas></div>
+ <table><thead><tr><th>Month</th><th>What the market is doing</th><th>The DW play</th></tr></thead><tbody>${calRows}</tbody></table>
+</div></section>
+
+<section id="audit"><div class="eyebrow">06 · Website Audit</div><h2 class="disp">A strong engine that hides its best features.</h2><div class="accbody">
+ <p class="lead2">Analyst audit of the live flagship (Shopify + Boost search): the merchandising infrastructure is genuinely advanced — the gap is guided discovery for the retail buyer facing ${fmt(FF.active_total)} choices.</p>
+ <div class="cards2">
+ <div class="c"><h3>Working well</h3><p class="good">Left-rail collection navigation · shop-by-color wheel with type pills · AEO content blocks on collections · sort + density controls on grids · New Arrivals / Trending smart collections refreshed by daily tag-sync · $4.25 memo-sample funnel on every product.</p></div>
+ <div class="c"><h3>Gaps</h3><p class="flag">Sample-only products present a dead-end buy box (${fmt(SO.backlog)} products) · zero-price actives surface in feeds (${fmt(FF.zero_price)}) · ${fmt(FF.missing_image)} actives lack a featured image · curation layers (rooms, moods, designer picks) are thin relative to catalog depth.</p></div>
+ <div class="c"><h3>Action</h3><p>Fix the integrity backlog (Section 02), then ship a guided-discovery layer: room/mood entry points, "pairs well with" on every PDP, and a designer-picks editorial tier — the concept directions in Section 08 show the face of it.</p></div>
+ </div>
+</div></section>
+
+<section id="social"><div class="eyebrow">07 · Social Audit</div><h2 class="disp">Broad reach, quiet voice.</h2><div class="accbody">
+ <p class="lead2">All major platforms are connected through one command center — a real infrastructure asset. The audit finding is consistent across platforms: <b>distribution exists, engagement discipline doesn't yet</b>. The page network posts; it doesn't yet converse, attribute, or convert.</p>
+ <div class="cards2">
+ <div class="c"><h3>Connected & ready</h3><p class="good">${(SNAP.channels || []).filter(c => c.connected).map(c => c.label || c.key).join(' · ')}</p></div>
+ <div class="c"><h3>The gap</h3><p class="flag">No per-channel revenue attribution · posting cadence not synced to the activation drip · reels/video formats underused relative to the category (interiors is a visual-first vertical).</p></div>
+ <div class="c"><h3>The play</h3><p>One flagship voice + the page network as amplifiers. Daily new-arrival stories (auto-fed by the drip), weekly designer-pick reels, per-channel UTM coupons — measured, not sprayed.</p></div>
+ </div>
+</div></section>
+
+<section id="suggested"><div class="eyebrow">08 · Suggested New Flagships</div><h2 class="disp">Six directions worthy of the catalog.</h2><div class="accbody">
+ <p class="lead2">Six full front-page concepts — each after a house that owns its lane, each a working page with the mandatory sort + density controls on its grid. Not palette swaps: different merchandising philosophies. Open each live and pick the direction.</p>
+ <div class="vgrid">${houseTiles}</div>
+</div></section>
+
+<section id="partners"><div class="eyebrow">09 · Unlikely Partners</div><h2 class="disp">Channels that don't look like channels.</h2><div class="accbody">
+ <p class="lead2">Eight partnership lanes where DW's LA position and trade heritage do the acquisition work.</p>
+ ${partnerRows}
+</div></section>
+
+<section id="revenue"><div class="eyebrow">10 · Unlikely Revenue</div><h2 class="disp">The money already in the building.</h2><div class="accbody">
+ <p class="lead2">Before any new audience is bought, six revenue pools sit inside the existing operation:</p>
+ <div class="sugg">
+ <div class="s"><div class="p">Pool 1 · largest</div><h4>The sellable-variant backlog</h4><p>${fmt(SO.backlog)} active products browseable but not buyable. Even a 1% conversion at category AOV is a six-figure annual pool. Remediation is data work, not marketing spend.</p></div>
+ <div class="s"><div class="p">Pool 2 · compounding</div><h4>Sample → roll funnel</h4><p>The $4.25 memo program generates purchase-intent signals daily. Instrumented follow-up (sampled-but-didn't-buy sequences) converts existing intent at near-zero cost.</p></div>
+ <div class="s"><div class="p">Pool 3 · scheduled</div><h4>The staged-draft drip</h4><p>${fmt(C.drafts_total)} drafts activating ~500/day = a permanent "new arrivals" marketing engine. Sync email + social to the drip and every day ships its own campaign.</p></div>
+ <div class="s"><div class="p">Pool 4 · zero-inventory</div><h4>Original design licensing</h4><p>Settlement-gated original pattern IP licensed to print-on-demand marketplaces — revenue without inventory, already piloted in the wider operation.</p></div>
+ <div class="s"><div class="p">Pool 5 · trade</div><h4>Designer-net portal</h4><p>Formalize trade pricing behind a designer login. Trade buyers are the highest-LTV segment and currently buy through the retail flow.</p></div>
+ <div class="s"><div class="p">Pool 6 · projects</div><h4>Hospitality / contract desk</h4><p>Type II contract lines already in catalog. A spec-sheet + quote desk turns one hotel corridor into 400 rolls.</p></div>
+ </div>
+ <div class="chartwrap"><div class="ct">Priced-subset architecture (basis: min variant > $4.25 memo — partial, labeled)</div><canvas id="bandChart"></canvas></div>
+</div></section>
+
+<section id="desk"><div class="eyebrow">11 · Live Commerce Desk</div><h2 class="disp">The operation, on one screen.</h2><div class="accbody">
+ <p class="lead2">Live KPIs from the ${collectedLabel} snapshot — the numbers a weekly growth review should open with. Hit ↻ Refresh (top right) to re-collect on demand.</p>
+ <div class="kpis">
+ <div class="kpi"><div class="kv">${fmt(FF.active_total)}</div><div class="kl">Active products</div></div>
+ <div class="kpi"><div class="kv">${fmt(C.drafts_total)}</div><div class="kl">Staged drafts</div></div>
+ <div class="kpi"><div class="kv">${fmt(C.drafts_stageable)}</div><div class="kl">Stageable today (variant + image)</div></div>
+ <div class="kpi"><div class="kv">${fmt(SO.backlog)}</div><div class="kl">Sample-only backlog (non-quote)</div></div>
+ <div class="kpi"><div class="kv">${fmt(FF.zero_price)}</div><div class="kl">Zero-price actives</div></div>
+ <div class="kpi"><div class="kv">${fmt(FF.missing_image)}</div><div class="kl">Image-less actives</div></div>
+ <div class="kpi"><div class="kv">${fmt(C.vendors_active)}</div><div class="kl">Vendor lines live</div></div>
+ <div class="kpi"><div class="kv">${fmt(SNAP.fleet?.count)}</div><div class="kl">Fleet microsites</div></div>
+ </div>
+ <div class="chartwrap"><div class="ct">Weekly activation cadence (same data as Section 05 — the desk's pulse line)</div><canvas id="deskChart"></canvas></div>
+</div></section>
+
+<section id="roadmap"><div class="eyebrow">12 · 90-Day Roadmap</div><h2 class="disp">What to do, in order.</h2><div class="accbody">
+ <ul class="road">
+ <li><div class="w">Weeks 1–2</div><div class="d"><b>Integrity sprint:</b> triage the ${fmt(SO.backlog)} sample-only backlog by vendor (top 8 lines = ${fmt((C.sample_only_vendors || []).reduce((a, v) => a + v.count, 0))} products); fix zero-price and image-less actives. Wire per-channel UTM + coupon attribution. Pick a concept direction from Section 08.</div></li>
+ <li><div class="w">Weeks 3–6</div><div class="d"><b>Convert intent:</b> ship the sampled-but-didn't-buy email sequence off the memo funnel. Sync daily social posting to the activation drip. Start the designer-net trade portal build.</div></li>
+ <li><div class="w">Weeks 6–10</div><div class="d"><b>Ship the face:</b> launch the chosen flagship direction (guided discovery: rooms, moods, designer picks). Extend AEO blocks fleet-wide. Sign 3 unlikely-partner deals (one installer network, one stager program, one hospitality designer).</div></li>
+ <li><div class="w">Weeks 10–13</div><div class="d"><b>Measure & double down:</b> channel-level revenue review off the new attribution; scale the winner. Open the contract/hospitality quote desk. Publish the first licensing-line results.</div></li>
+ </ul>
+</div></section>
+
+<section id="sources"><div class="eyebrow">13 · Sources & Methodology</div><h2 class="disp">Where every number comes from.</h2><div class="accbody">
+ <p class="lead2">Snapshot collected <b>${collectedLabel}</b> by a read-only collector. Live rows are measured; analyst rows are authored judgment; anything illustrative says so.</p>
+ <div class="srclegend">${srcLegend}</div>
+ <table><thead><tr><th>Section</th><th>Where it comes from</th><th>How it's produced</th><th>Provenance</th></tr></thead><tbody>${srcRows}</tbody></table>
+ <div class="srcnote"><div class="i">⚙</div><div><h4>How this document is built</h4><p>Generated, not hand-typed. A read-only collector (<code>scripts/collect-dw.mjs</code>) snapshots the DW systems into <code>data/dw-analysis.json</code>; the build (<code>build.mjs</code>) renders that snapshot into this page. The ↻ Refresh button re-runs collector + build on demand. Nothing writes to any DW production system.</p></div></div>
+</div></section>
+
+<footer><span>Designer Wallcoverings · Growth Strategy Brief</span><span>Data as of ${collectedLabel}</span><span>Confidential — for discussion</span></footer>
+
+<script>
+(function(){var s=document.querySelectorAll('.hero .slide'),i=0;if(s.length<2)return;setInterval(function(){s[i].classList.remove('on');i=(i+1)%s.length;s[i].classList.add('on');},5200);})();
+var REDUCE=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
+function countUp(el){var t=+el.dataset.c;if(!t)return;if(REDUCE){el.textContent=t.toLocaleString();return;}var d=1300,st=null;function step(ts){st=st||ts;var p=Math.min((ts-st)/d,1),e=1-Math.pow(1-p,3);el.textContent=Math.round(t*e).toLocaleString();if(p<1)requestAnimationFrame(step);}requestAnimationFrame(step);}
+var secs=[].slice.call(document.querySelectorAll('section[id]'));var accs=[];
+secs.forEach(function(sec){var eb=sec.querySelector(':scope>.eyebrow'),h2=sec.querySelector(':scope>h2');if(!eb&&!h2)return;accs.push(sec);
+ var head=document.createElement('button');head.type='button';head.className='acchead';var txt=document.createElement('div');txt.className='htext';if(eb)txt.appendChild(eb);if(h2)txt.appendChild(h2);
+ var chev=document.createElement('span');chev.className='chev';chev.textContent='+';head.appendChild(txt);head.appendChild(chev);sec.insertBefore(head,sec.querySelector('.accbody'));
+ head.addEventListener('click',function(){var open=sec.classList.toggle('open');chev.textContent=open?'\\u2013':'+';if(open){initCharts();initMap();drawRoad(sec);}});});
+function drawRoad(sec){var rd=sec.querySelector('.road');if(rd)setTimeout(function(){rd.classList.add('drawn');},140);}
+function setAll(o){accs.forEach(function(s){s.classList.toggle('open',o);var c=s.querySelector('.chev');if(c)c.textContent=o?'\\u2013':'+';if(o)drawRoad(s);});if(o){initCharts();initMap();}}
+document.getElementById('xall').onclick=function(){setAll(true);};document.getElementById('call').onclick=function(){setAll(false);};
+document.querySelectorAll('.menu a[href^="#"]').forEach(function(a){a.addEventListener('click',function(){var id=a.getAttribute('href').slice(1),s=document.getElementById(id);if(s&&!s.classList.contains('open')&&s.querySelector('.acchead')){s.querySelector('.acchead').click();}if(s)setTimeout(function(){s.scrollIntoView({behavior:'smooth'});},80);});});
+(function(){var burger=document.querySelector('.burger');if(!burger)return;function sync(){burger.setAttribute('aria-expanded',document.body.classList.contains('nav'));}new MutationObserver(sync).observe(document.body,{attributes:true,attributeFilter:['class']});sync();})();
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+document.querySelectorAll('.metrics .v[data-c]').forEach(function(el){var mo=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){countUp(el);mo.unobserve(el);}});});mo.observe(el);});
+document.getElementById('refbtn').addEventListener('click',function(){var b=this;b.disabled=true;b.textContent='↻ Refreshing…';fetch('/api/refresh',{method:'POST'}).then(function(r){return r.json();}).then(function(d){if(d.ok){b.textContent='↻ Rebuilt — reloading';setTimeout(function(){location.reload();},600);}else{b.textContent='↻ '+(d.error||'unavailable here');b.disabled=false;}}).catch(function(){b.textContent='↻ Refresh unavailable';b.disabled=false;});});
+var charted=false;
+function initCharts(){if(charted||!window.Chart)return;charted=true;
+ var gold='#c9a24b',dim='rgba(241,236,227,.6)',line='rgba(201,162,75,.18)';Chart.defaults.color=dim;Chart.defaults.font.family='Jost,system-ui,sans-serif';
+ var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
+ Chart.defaults.animation=RM?false:{duration:1150,easing:'easeInOutQuart'};
+ if(!RM){Chart.defaults.animations={y:{from:function(c){return c.chart.scales.y?c.chart.scales.y.getPixelForValue(0):0;}}};}
+ var D=${JSON.stringify(CHART)};
+ function mk(id,cfg){var el=document.getElementById(id);if(el)new Chart(el,cfg);}
+ mk('vendorChart',{type:'bar',data:{labels:D.vendors.labels,datasets:[{label:'Active products',data:D.vendors.counts,backgroundColor:'rgba(201,162,75,.75)'}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('typeChart',{type:'doughnut',data:{labels:D.types.labels,datasets:[{data:D.types.counts,backgroundColor:['#c9a24b','#b78d3f','#a67c32','#d9b877','#8f6d2c','#e3c98d'],borderColor:'#0e0c09',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'right',labels:{color:dim,boxWidth:12}}},cutout:'58%'}});
+ mk('ffChart',{type:'bar',data:{labels:D.integrity.labels,datasets:[{label:'Actives failing',data:D.integrity.counts,backgroundColor:D.integrity.counts.map(function(v){return v>10000?'rgba(232,160,160,.8)':'rgba(201,162,75,.6)';})}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('soChart',{type:'bar',data:{labels:D.sampleOnlyVendors.labels,datasets:[{label:'Sample-only actives',data:D.sampleOnlyVendors.counts,backgroundColor:'rgba(232,160,160,.7)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('compChart',{type:'bar',data:{labels:D.comp.labels,datasets:[{label:'Catalog depth',data:D.comp.catalog,backgroundColor:'rgba(201,162,75,.75)'},{label:'Digital polish',data:D.comp.digital,backgroundColor:'rgba(120,170,255,.6)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line},max:100},x:{grid:{display:false}}},plugins:{legend:{labels:{color:dim}}}}});
+ mk('chanChart',{type:'bar',data:{labels:D.channels.labels,datasets:[{label:'Connected accounts',data:D.channels.accounts,backgroundColor:'rgba(201,162,75,.75)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('cadenceChart',{type:'line',data:{labels:D.cadence.labels,datasets:[{label:'New actives / week',data:D.cadence.added,borderColor:gold,backgroundColor:'rgba(201,162,75,.12)',fill:true,tension:.4,pointRadius:4}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('deskChart',{type:'line',data:{labels:D.cadence.labels,datasets:[{label:'New actives / week',data:D.cadence.added,borderColor:gold,backgroundColor:'rgba(201,162,75,.12)',fill:true,tension:.4,pointRadius:4}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('bandChart',{type:'bar',data:{labels:D.bands.labels,datasets:[{label:'Products (priced subset)',data:D.bands.counts,backgroundColor:'rgba(201,162,75,.6)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+}
+var mapped=false;
+function initMap(){if(mapped||!window.L||!document.getElementById('compmap'))return;mapped=true;
+ var pts=${JSON.stringify(MAP_POINTS)};
+ var m=L.map('compmap',{scrollWheelZoom:false}).setView([38.5,-96],4);
+ L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',{attribution:'© OpenStreetMap © CARTO',maxZoom:18}).addTo(m);
+ pts.forEach(function(p){var mk=L.circleMarker([p.lat,p.lng],{radius:p.you?10:7,color:p.you?'#c9a24b':'#78aaff',fillColor:p.you?'#c9a24b':'#78aaff',fillOpacity:.85,weight:1});
+ mk.bindPopup('<b>'+p.name+'</b><br>'+(p.note||''));mk.addTo(m);});
+ setTimeout(function(){m.invalidateSize();},300);
+}
+</script>
+</body></html>`;
+
+/* ================================================== concept version pages === */
+function versionPage(h) {
+ const gridCards = Array.from({ length: 12 }, (_, i) => {
+ const hue = [28, 152, 208, 12, 262, 88, 340, 190, 46, 300, 130, 20][i];
+ const names = ['Chinois Garden', 'Venetian Plaster', 'Grasscloth No. 9', 'Deco Fan', 'Midnight Damask', 'Coastal Weave', 'Rosewood Toile', 'Celadon Silk', 'Gilt Trellis', 'Amethyst Moire', 'Sage Stripe', 'Terra Fresco'][i];
+ const tierName = ['casual', 'signature', 'reserve'][i % 3];
+ return `<article class="gcard" data-title="${names}" data-hue="${hue}" data-tier="${i % 3}">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(${hue},22%,${h.dark ? 24 : 78}%),hsl(${(hue + 40) % 360},30%,${h.dark ? 14 : 64}%))"></div>
+ <h4>${names}</h4><div class="gmeta"><span>${['Wallcovering', 'Fabric', 'Mural'][i % 3]}</span><span class="tier">${tierName}</span></div>
+ </article>`;
+ }).join('');
+ return `<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — ${h.label} concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:${h.bg};--panel:${h.panel};--ink:${h.ink};--gold:${h.gold};--line:${h.line};--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:${h.sans};font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:${h.disp}}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:${h.dark ? '#0b0b0c' : '#fff'};font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:${h.disp};font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:${h.sans};font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:${h.disp};font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:${h.dark ? '#0b0b0c' : '#fff'}}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:${h.sans};font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:${h.disp};font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:${h.disp};font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:${h.dark ? '#0b0b0c' : '#fff'};border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · ${h.model} direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>${h.label} · ${h.tag}</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">${h.tag}</h1><p>${h.mood} A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid">${gridCards}</div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "${h.label}" (${h.model} direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-${h.key}-sort',KD='dwconcept-${h.key}-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
</body></html>`;
- writeFileSync(join(OUT, `${name}.html`), html);
}
-console.log('Generated ' + Object.keys(SKINS).length + ' concept versions into public/versions/');
+
+writeFileSync(`${OUT}/portal.html`, app);
+for (const h of HOUSES) writeFileSync(`${OUT}/versions/${h.key}.html`, versionPage(h));
+console.log(`Wrote portal.html (14-section DW analysis app, data of ${collectedLabel}) + ${HOUSES.length} concepts: ${HOUSES.map(h => h.key).join(', ')}`);
diff --git a/data/dw-analysis.json b/data/dw-analysis.json
index f9f2f10..f93e306 100644
--- a/data/dw-analysis.json
+++ b/data/dw-analysis.json
@@ -1,5 +1,5 @@
{
- "collected_at": "2026-07-26T14:41:40.707Z",
+ "collected_at": "2026-07-26T15:02:30.181Z",
"sources": {
"mirror": "dw_unified local mirror (host=/tmp) — READ ONLY",
"mcc": "marketing.designerwallcoverings.com/api/channels/status",
@@ -187,8 +187,48 @@
"count": 129
}
],
+ "price_bands_basis": "products whose minimum variant exceeds the $4.25 memo sample — the priced subset of the mirror (~3.8k); most actives resolve min-variant to the sample, and full variant-level pricing lives Shopify-side",
"drafts_total": 16055,
- "drafts_stageable": 2793
+ "drafts_stageable": 2793,
+ "sample_only": {
+ "quote_only_by_design": 3785,
+ "total": 26737,
+ "backlog": 22952
+ },
+ "sample_only_vendors": [
+ {
+ "vendor": "Phillipe Romano",
+ "count": 5924
+ },
+ {
+ "vendor": "Phillip Jeffries",
+ "count": 2461
+ },
+ {
+ "vendor": "Koroseal",
+ "count": 2454
+ },
+ {
+ "vendor": "China Seas",
+ "count": 1776
+ },
+ {
+ "vendor": "Coordonné",
+ "count": 1300
+ },
+ {
+ "vendor": "Hollywood Wallcoverings",
+ "count": 1089
+ },
+ {
+ "vendor": "Designers Guild",
+ "count": 840
+ },
+ {
+ "vendor": "Osborne & Little",
+ "count": 820
+ }
+ ]
},
"channels": [
{
diff --git a/public/portal.html b/public/portal.html
index 9c92d19..637fe63 100644
--- a/public/portal.html
+++ b/public/portal.html
@@ -1,80 +1,338 @@
-<!doctype html>
-<html lang="en">
-<head>
-<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Designer Wallcoverings · Deliverable</title>
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Growth Strategy</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
+<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
+<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<style>
- :root{--ink:#14110e;--paper:#f6f2ec;--gold:#a9884f;--line:#dcd3c5}
- *{box-sizing:border-box}
- body{margin:0;font-family:Georgia,serif;background:var(--paper);color:var(--ink)}
- nav{display:flex;justify-content:space-between;align-items:center;padding:16px 28px;background:#fff;border-bottom:1px solid var(--line);font-family:system-ui,sans-serif}
- nav .brand{letter-spacing:.06em}
- nav a{color:var(--gold);text-decoration:none;font-size:13px;letter-spacing:.1em;text-transform:uppercase;margin-left:18px}
- .hero{padding:56px 28px 34px;text-align:center}
- .hero .eyebrow{letter-spacing:.32em;text-transform:uppercase;font-size:11px;color:var(--gold);font-family:system-ui,sans-serif}
- .hero h1{font-weight:400;font-size:44px;margin:.2em 0}
- .hero p{font-style:italic;color:#6b6357;max-width:640px;margin:0 auto}
- section{max-width:1080px;margin:0 auto;padding:28px}
- h2{font-weight:400;font-size:26px;border-bottom:1px solid var(--line);padding-bottom:8px}
- .cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:18px;margin-top:18px}
- .vcard{background:#fff;border:1px solid var(--line);text-decoration:none;color:inherit;transition:.2s}
- .vcard:hover{box-shadow:0 16px 40px rgba(20,17,14,.1);transform:translateY(-2px)}
- .vcard .swatch{height:120px;background:var(--gold)}
- .vcard .body{padding:14px 16px}
- .vcard b{font-family:system-ui,sans-serif;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:#9a9082}
- .list{font-family:system-ui,sans-serif;font-size:15px}
- .list li{margin:8px 0}
- .badge{display:inline-block;font-family:system-ui,sans-serif;font-size:11px;background:#faf7f1;border:1px solid var(--gold);color:var(--gold);padding:2px 9px;border-radius:20px;margin-left:8px}
-</style>
-</head>
-<body>
- <nav>
- <div class="brand" id="brand">Designer Wallcoverings</div>
- <div><a href="/portal">Deliverable</a><a href="/admin">Growth & Social</a><a href="/">Sign-in</a></div>
- </nav>
-
- <div class="hero">
- <div class="eyebrow">Consulting Deliverable</div>
- <h1 id="name">Designer Wallcoverings</h1>
- <p id="tag"></p>
+:root{--bg:#0e0c09;--panel:#171310;--ink:#f1ece3;--gold:#c9a24b;--line:rgba(201,162,75,.22);--dim:rgba(241,236,227,.66)}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Jost',system-ui,sans-serif;font-size:19px;line-height:1.75;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Cormorant Garamond',Georgia,serif}a{color:inherit;text-decoration:none}
+.bar{position:fixed;top:0;left:0;right:0;z-index:40;display:flex;align-items:center;justify-content:space-between;padding:18px 34px;background:linear-gradient(180deg,rgba(14,12,9,.94),rgba(14,12,9,0))}
+.burger{width:30px;height:20px;position:relative;cursor:pointer;background:none;border:0}.burger span{position:absolute;left:0;right:0;height:1.6px;background:var(--ink);transition:.35s}
+.burger span:nth-child(1){top:1px}.burger span:nth-child(2){top:9px}.burger span:nth-child(3){top:17px}
+body.nav .burger span:nth-child(1){transform:translateY(8px) rotate(45deg)}body.nav .burger span:nth-child(2){opacity:0}body.nav .burger span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
+.stamp{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);display:flex;gap:10px;align-items:center}
+.stamp button{background:none;border:1px solid var(--line);color:var(--gold);font-family:'Jost';font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:6px 12px;cursor:pointer}
+.stamp button:hover{background:var(--gold);color:var(--bg)}
+.menu{position:fixed;top:0;left:0;bottom:0;width:min(420px,86vw);z-index:39;background:var(--panel);border-right:1px solid var(--line);transform:translateX(-100%);transition:.42s cubic-bezier(.6,0,.2,1);padding:92px 40px;overflow:auto}
+.mbrand{display:block;font-family:'Cormorant Garamond',serif;font-size:24px;letter-spacing:.2em;text-transform:uppercase;color:var(--ink);margin-bottom:28px}
+.mbrand span{color:var(--gold)}
+.mbrand small{display:block;font-family:'Jost',system-ui,sans-serif;font-size:9px;letter-spacing:.32em;color:var(--gold);margin-top:4px}
+body.nav .menu{transform:none}body.nav .scrim{opacity:1;pointer-events:auto}
+.scrim{position:fixed;inset:0;z-index:38;background:rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:.42s}
+.menu .mh{font-family:'Cormorant Garamond',serif;font-size:13px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold);margin-bottom:18px}
+.menu a{display:block;font-family:'Cormorant Garamond',serif;font-size:23px;padding:9px 0;border-bottom:1px solid var(--line);opacity:.85;transition:.25s}
+.menu a:hover{opacity:1;color:var(--gold);padding-left:8px}
+.menu .minfo{margin-top:28px;border-top:1px solid var(--line);padding-top:20px}.menu .minfo p{font-size:13px;line-height:1.7;color:var(--dim);border:0;padding:2px 0}
+.hero{min-height:96vh;position:relative;display:flex;flex-direction:column;justify-content:center;padding:0 clamp(24px,7vw,120px);overflow:hidden}
+.slides{position:absolute;inset:0;z-index:0}
+.slide{position:absolute;inset:0;background-size:cover;background-position:center;opacity:0;transform:scale(1.04);transition:opacity 1.4s ease;will-change:transform,opacity}
+.slide.on{opacity:1;animation:kenburns 13s ease-out forwards}
+@keyframes kenburns{from{transform:scale(1.04) translate3d(0,0,0)}to{transform:scale(1.13) translate3d(-1.4%,-1.2%,0)}}
+.hero:after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,rgba(14,12,9,.94),rgba(14,12,9,.62) 55%,rgba(14,12,9,.35));z-index:1}
+.hero .in{position:relative;z-index:2;max-width:960px}
+.kick{font-size:12px;letter-spacing:.4em;text-transform:uppercase;color:var(--gold);margin-bottom:22px}
+.hero h1{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(40px,6.6vw,92px);line-height:1.02}.hero h1 span{color:var(--gold)}
+.hero p{max-width:64ch;margin-top:24px;font-size:18px;color:var(--dim)}
+.metrics{display:flex;flex-wrap:wrap;gap:46px;margin-top:46px}
+.metrics .v{font-family:'Cormorant Garamond',serif;font-size:40px;color:var(--gold);line-height:1}
+.metrics .l{font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);margin-top:6px}
+section{padding:0 clamp(24px,7vw,120px);border-top:1px solid var(--line);scroll-margin-top:60px}
+.accbar{display:flex;gap:12px;justify-content:flex-end;padding:14px clamp(24px,7vw,120px);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
+.accbar button{background:none;border:1px solid var(--line);color:var(--gold);font-family:'Jost';font-size:11px;letter-spacing:.18em;text-transform:uppercase;padding:9px 18px;cursor:pointer}.accbar button:hover{background:var(--gold);color:var(--bg)}
+.acchead{width:100%;text-align:left;background:none;border:0;cursor:pointer;display:flex;gap:22px;padding:36px 0;color:var(--ink)}
+.acchead .htext{flex:1}.eyebrow{font-size:12.5px;letter-spacing:.36em;text-transform:uppercase;color:var(--gold);margin-bottom:12px}
+h2{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(30px,4.4vw,54px);line-height:1.05;max-width:22ch}
+.acchead .chev{font-family:'Cormorant Garamond',serif;font-size:36px;color:var(--gold);transition:.3s;line-height:.7}
+section.open .chev{transform:rotate(45deg)}.acchead:hover h2{color:var(--gold);transition:.25s}
+.accbody{display:none;padding-bottom:60px}section.open .accbody{display:block;animation:af .45s ease}
+@keyframes af{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
+.lead2{max-width:72ch;color:var(--dim);margin-top:6px;font-size:20px}
+table{width:100%;border-collapse:collapse;margin-top:34px;font-size:16px}th,td{text-align:left;padding:15px 14px;border-bottom:1px solid var(--line);vertical-align:top;font-size:15.5px}
+th{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);font-weight:400}
+tr.you{background:rgba(201,162,75,.09)}tr.you td:first-child{color:var(--gold)}
+td.mo{font-family:'Cormorant Garamond',serif;color:var(--gold);font-size:18px;width:60px}
+.chartwrap{margin-top:34px;background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:22px 20px 14px;position:relative;height:340px}
+.chartwrap.tall{height:410px}.chartwrap .ct{font-family:'Cormorant Garamond',serif;font-size:15px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);margin-bottom:10px}
+.cards2{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1px;background:var(--line);margin-top:34px}
+.cards2 .c{background:var(--bg);padding:32px 28px}.cards2 .c h3{font-family:'Cormorant Garamond',serif;font-size:22px;color:var(--gold);margin-bottom:10px}.cards2 .c p{color:var(--dim);font-size:16px;line-height:1.6}
+.flag{color:#e8a0a0}.good{color:#9fd6b0}
+.swotgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1px;background:var(--line);margin-top:34px}
+.swotq{background:var(--bg);padding:28px 26px}.swotq h3{font-family:'Cormorant Garamond',serif;font-size:22px;margin-bottom:12px}
+.swotq.pos{border-top:2px solid #9fd6b0}.swotq.neg{border-top:2px solid #e8a0a0}
+.swotq.pos h3{color:#9fd6b0}.swotq.neg h3{color:#e8a0a0}
+.swotq ul{margin:0;padding-left:18px}.swotq li{color:var(--dim);font-size:15px;line-height:1.55;margin:6px 0}
+.srclegend{display:flex;flex-wrap:wrap;gap:10px;margin:26px 0 4px}
+.srcb{display:inline-block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:5px 11px;border-radius:3px;border:1px solid var(--line);white-space:nowrap}
+.srcb.r{color:var(--gold)}.srcb.o{color:#78aaff;border-color:rgba(120,170,255,.4)}.srcb.d{color:#b78d3f}.srcb.a{color:var(--dim)}.srcb.e{color:#e8a0a0;border-color:rgba(232,160,160,.4)}
+td.srccell{white-space:nowrap;vertical-align:middle}
+.accbody td code{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;color:var(--ink);background:rgba(201,162,75,.12);padding:1px 6px;border-radius:3px}
+.srcnote{margin-top:34px;display:flex;gap:22px;padding:28px 30px;border:1px solid var(--line);background:var(--panel)}
+.srcnote .i{font-size:26px;color:var(--gold);line-height:1}
+.srcnote h4{font-family:'Cormorant Garamond',serif;font-size:21px;color:var(--gold);margin-bottom:8px}
+.srcnote p{color:var(--dim);font-size:15px;line-height:1.6}
+.srcnote code{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;color:var(--ink);background:rgba(201,162,75,.12);padding:1px 6px;border-radius:3px}
+.flagbox{display:flex;gap:22px;margin-top:34px;padding:30px 32px;border:1px solid var(--gold);background:rgba(201,162,75,.07)}
+.flagbox .i{font-size:30px;color:var(--gold)}.flagbox h3{font-family:'Cormorant Garamond',serif;font-size:24px;color:var(--gold);margin-bottom:10px}.flagbox p{color:var(--ink);opacity:.92;font-size:16px;line-height:1.6}
+.vgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px;margin-top:20px}
+.vtile{background:var(--vb);border:1px solid var(--line);padding:28px 26px;transition:.3s;position:relative}.vtile:hover{transform:translateY(-5px);box-shadow:0 22px 60px rgba(0,0,0,.55)}
+.vswatch{display:flex;height:36px;border-radius:3px;overflow:hidden;margin-bottom:20px}.vswatch span{flex:1}
+.vname{font-family:'Cormorant Garamond',serif;font-size:26px;color:var(--vi)}.vmodel{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--vg);margin-top:2px}
+.vmood{color:var(--vi);opacity:.72;font-size:13px;margin-top:10px;min-height:38px}.vopen{margin-top:16px;font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--vg)}
+.pcard{display:flex;gap:22px;padding:24px 0;border-bottom:1px solid var(--line)}.pnum{font-family:'Cormorant Garamond',serif;font-size:30px;color:var(--gold);min-width:44px}.pcard h4{font-family:'Cormorant Garamond',serif;font-size:21px;margin-bottom:6px}.pcard p{color:var(--dim);font-size:16px;line-height:1.6}
+.sugg{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1px;background:var(--line);margin-top:20px}.sugg .s{background:var(--bg);padding:26px 24px}.sugg .s .p{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold)}.sugg .s h4{font-family:'Cormorant Garamond',serif;font-size:20px;margin:8px 0}.sugg .s p{font-size:15px;color:var(--dim);line-height:1.55}
+.road{list-style:none;margin-top:20px;position:relative;padding-left:36px}
+.road:before{content:'';position:absolute;left:9px;top:10px;bottom:10px;width:2px;background:linear-gradient(180deg,var(--gold),rgba(201,162,75,.14));transform:scaleY(0);transform-origin:top;transition:transform 1.5s cubic-bezier(.5,0,.2,1)}
+.road.drawn:before{transform:scaleY(1)}
+.road li{padding:22px 0;border-bottom:1px solid var(--line);display:flex;gap:26px;position:relative}
+.road li:before{content:'';position:absolute;left:-32px;top:30px;width:12px;height:12px;border-radius:50%;background:var(--bg);border:2px solid var(--gold);box-shadow:0 0 0 4px var(--bg);transform:scale(0);transition:transform .5s cubic-bezier(.2,1.5,.4,1)}
+.road.drawn li:before{transform:scale(1)}
+.road.drawn li:nth-child(1):before{transition-delay:.30s}.road.drawn li:nth-child(2):before{transition-delay:.62s}.road.drawn li:nth-child(3):before{transition-delay:.94s}.road.drawn li:nth-child(4):before{transition-delay:1.26s}
+.road .w{font-family:'Cormorant Garamond',serif;color:var(--gold);font-size:15px;letter-spacing:.2em;text-transform:uppercase;min-width:130px}.road .d{color:var(--dim)}
+@media(prefers-reduced-motion:reduce){.slide.on{animation:none;transform:scale(1)}.road:before{transition:none;transform:scaleY(1)}.road li:before{transition:none;transform:scale(1)}.accbody{animation:none!important}}
+.rv{opacity:0;transform:translateY(22px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+#compmap{height:420px;border:1px solid var(--line);border-radius:8px;margin-top:34px;background:#0a0908}
+.leaflet-container{background:#0a0908;font-family:'Jost',sans-serif}
+.leaflet-popup-content-wrapper{background:var(--panel);color:var(--ink);border:1px solid var(--line)}
+.leaflet-popup-tip{background:var(--panel)}
+.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:14px;margin-top:34px}
+.kpi{background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:22px 20px}
+.kpi .kv{font-family:'Cormorant Garamond',serif;font-size:34px;color:var(--gold);line-height:1}
+.kpi .kl{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);margin-top:8px}
+.fchips{display:flex;flex-wrap:wrap;gap:8px;margin-top:24px}
+.fchip{font-size:11px;letter-spacing:.06em;border:1px solid var(--line);color:var(--dim);padding:5px 11px;border-radius:3px}
+footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color:var(--dim);font-size:12px;letter-spacing:.14em;text-transform:uppercase;display:flex;justify-content:space-between;flex-wrap:wrap;gap:20px}
+@media(max-width:640px){.metrics{gap:26px}}
+</style></head><body>
+<header class="bar">
+ <button class="burger" onclick="document.body.classList.toggle('nav')" aria-label="Menu" aria-expanded="false" aria-controls="portalmenu"><span></span><span></span><span></span></button>
+ <div class="stamp"><span>Data collected Jul 26, 2026, 8:02 AM</span><button id="refbtn" title="Re-run the read-only collector">↻ Refresh data</button></div>
+</header>
+<div class="scrim" onclick="document.body.classList.remove('nav')"></div>
+<nav class="menu" id="portalmenu" onclick="if(event.target.closest('a'))document.body.classList.remove('nav')">
+ <a class="mbrand" href="#summary">Designer <span>Wallcoverings</span><small>Growth Strategy · 2026</small></a>
+ <div class="mh">Contents</div><a href="#summary">Executive Summary</a><a href="#swot">SWOT Analysis</a><a href="#empire">The Catalog Empire</a><a href="#integrity">Catalog Integrity — the 5-Field Read</a><a href="#competitors">Competitive Landscape</a><a href="#advertising">Channels & Distribution</a><a href="#timing">Timing & Cadence</a><a href="#audit">Website Audit</a><a href="#social">Social Audit</a><a href="#suggested">Suggested New Flagships</a><a href="#partners">Unlikely Partners</a><a href="#revenue">Unlikely Revenue</a><a href="#desk">Live Commerce Desk</a><a href="#roadmap">90-Day Roadmap</a><a href="#sources">Sources & Methodology</a>
+ <div class="minfo"><div class="mh">Designer Wallcoverings</div><p>Los Angeles · nationwide e-commerce + trade</p><p>steve@designerwallcoverings.com</p><p>designerwallcoverings.com</p></div>
+</nav>
+
+<div class="hero" id="summary">
+ <div class="slides"><div class="slide on" style="background-image:url('https://images.unsplash.com/photo-1615873968403-89e068629265?auto=format&fit=crop&w=1920&q=68&sat=-25')"></div><div class="slide" style="background-image:url('https://images.unsplash.com/photo-1618221195710-dd6b41faaea6?auto=format&fit=crop&w=1920&q=68&sat=-25')"></div><div class="slide" style="background-image:url('https://images.unsplash.com/photo-1600210492486-724fe5c67fb0?auto=format&fit=crop&w=1920&q=68&sat=-25')"></div><div class="slide" style="background-image:url('https://images.unsplash.com/photo-1600585154340-be6161a56a0c?auto=format&fit=crop&w=1920&q=68&sat=-25')"></div><div class="slide" style="background-image:url('https://images.unsplash.com/photo-1600607687939-ce8a6c25118c?auto=format&fit=crop&w=1920&q=68&sat=-25')"></div></div>
+ <div class="in">
+ <div class="kick">Los Angeles · nationwide e-commerce + trade · Confidential strategy brief · prepared for Steve Abrams</div>
+ <h1 class="disp">Designer <span>Wallcoverings</span></h1>
+ <p>Thirty years of trade authority, <b>80,522 live SKUs</b> across <b>174 vendor lines</b>, a <b>287-site</b> discovery fleet, and <b>7 connected social channels</b> — the deepest designer-wallcovering operation online. The opportunity isn't building an audience; it's converting the catalog's dormant depth (a 22,952-product sellable-variant backlog, 16,055 staged drafts) into measured revenue. This brief maps exactly that, from the live data.</p>
+ <div class="metrics">
+ <div class="m"><div class="v" data-c="80522">0</div><div class="l">Live SKUs (active)</div></div>
+ <div class="m"><div class="v" data-c="174">0</div><div class="l">Vendor lines</div></div>
+ <div class="m"><div class="v" data-c="287">0</div><div class="l">Microsite fleet</div></div>
+ <div class="m"><div class="v" data-c="16055">0</div><div class="l">Staged drafts (fuel)</div></div>
+ </div>
+ </div>
+</div>
+
+<div class="accbar"><button id="xall">Expand all</button><button id="call">Collapse all</button></div>
+
+<section id="swot"><div class="eyebrow">Strategic Snapshot · SWOT</div><h2 class="disp">The whole board on one screen.</h2><div class="accbody">
+ <p class="lead2">Four lenses over the live snapshot — internal <b>Strengths</b> and <b>Weaknesses</b>, external <b>Opportunities</b> and <b>Threats</b> — so the strategy that follows starts from one honest picture. Every number here is from the Jul 26, 2026, 8:02 AM collection.</p>
+ <div class="swotgrid"><div class="swotq pos"><h3>Strengths</h3><ul><li>80,522 live SKUs across 174 vendor lines — one of the deepest designer-wallcovering catalogs online</li><li>A 287-site microsite fleet feeding discovery back to the flagship</li><li>7/7 social channels connected through one marketing command center</li><li>Private-label lines with owned margin (Phillipe Romano, Hollywood Wallcoverings, Malibu Wallpaper)</li><li>30+ years of trade relationships; memo-sample program ($4.25) as a proven funnel entry</li><li>Automated activation drip already shipping ~500 products/day, textures-first</li></ul></div><div class="swotq neg"><h3>Weaknesses</h3><ul><li>22,952 active products are sample-only WITHOUT a quote-only designation — browseable but not buyable</li><li>1,444 actives carry zero/null pricing; 333 lack a featured image</li><li>Social reach is broad (80 FB pages, 34 IG accounts) but thin — distribution without engagement depth</li><li>No social→revenue attribution discipline (UTM/coupon per channel) yet</li><li>Flagship UX carries catalog weight — 80k SKUs need stronger guided curation for retail buyers</li></ul></div><div class="swotq pos"><h3>Opportunities</h3><ul><li>Convert the 22,952 sample-only backlog into sellable variants — the single largest dormant-revenue pool in the business</li><li>16,055 staged drafts (2,793 fully stageable today) = months of "New Arrivals" marketing fuel</li><li>AEO/AI-answer citations for wallcovering queries — the flagship already ships an AEO block; extend it fleet-wide</li><li>Sample-order → full-roll conversion funnel instrumentation (order sync to the back office already exists)</li><li>Licensing original design IP (settlement-gated) into marketplaces as a zero-inventory revenue line</li></ul></div><div class="swotq neg"><h3>Threats</h3><ul><li>DTC-native entrants own the "approachable wallpaper" narrative with modern brand voices</li><li>Marketplace aggregators (Amazon, Wayfair, Etsy) commoditize mid-tier patterns</li><li>AI answer engines could disintermediate catalog-depth advantages if citations go to competitors</li><li>Vendor MAP / brand-control tightening limits pricing latitude on marquee lines</li></ul></div></div>
+ <div class="flagbox" style="margin-top:34px"><div class="i">⚡</div><div><h3 class="disp">The one-sentence thesis</h3><p>DW's moat is <b>catalog depth + trade authority</b>; its constraint is <b>conversion infrastructure</b>. The fastest wins activate what already exists — the sample-only backlog, the staged-draft drip, the connected-but-quiet channels — before building anything new.</p></div></div>
+</div></section>
+
+<section id="empire"><div class="eyebrow">01 · The Catalog Empire</div><h2 class="disp">Not a store. A catalog empire.</h2><div class="accbody">
+ <p class="lead2">The live mirror shows <b>80,522</b> active products, <b>16,055</b> staged drafts, and <b>80,473</b> archived — a merchandising engine with more inventory in reserve than most competitors have in total. Distribution runs through the flagship plus a <b>287-site</b> microsite fleet.</p>
+ <div class="chartwrap tall"><div class="ct">Top vendor lines by live products</div><canvas id="vendorChart"></canvas></div>
+ <div class="chartwrap"><div class="ct">Live catalog by product type</div><canvas id="typeChart"></canvas></div>
+ <table><thead><tr><th>#</th><th>Vendor line</th><th>Active products</th></tr></thead><tbody><tr><td class="mo">01</td><td><b>Phillipe Romano</b></td><td>11,270</td></tr><tr><td class="mo">02</td><td><b>Rebel Walls</b></td><td>3,770</td></tr><tr><td class="mo">03</td><td><b>Clarke And Clarke</b></td><td>3,570</td></tr><tr><td class="mo">04</td><td><b>Hollywood Wallcoverings</b></td><td>3,515</td></tr><tr><td class="mo">05</td><td><b>Malibu Wallpaper</b></td><td>3,232</td></tr><tr><td class="mo">06</td><td><b>Thibaut</b></td><td>2,987</td></tr><tr><td class="mo">07</td><td><b>Jeffrey Stevens</b></td><td>2,884</td></tr><tr><td class="mo">08</td><td><b>Brunschwig & Fils</b></td><td>2,761</td></tr><tr><td class="mo">09</td><td><b>Kravet</b></td><td>2,616</td></tr><tr><td class="mo">10</td><td><b>Phillip Jeffries</b></td><td>2,469</td></tr><tr><td class="mo">11</td><td><b>Koroseal</b></td><td>2,455</td></tr><tr><td class="mo">12</td><td><b>Gaston Y Daniela</b></td><td>2,148</td></tr><tr><td class="mo">13</td><td><b>Lee Jofa</b></td><td>2,040</td></tr><tr><td class="mo">14</td><td><b>Los Angeles Fabrics</b></td><td>1,833</td></tr></tbody></table>
+ <div class="eyebrow" style="margin-top:52px">The discovery fleet</div>
+ <p class="lead2">287 microsites — material-, era-, and city-specific storefront satellites that catch long-tail search and funnel to the flagship. A sample:</p>
+ <div class="fchips"><span class="fchip">all</span><span class="fchip">japan</span><span class="fchip">kravet</span><span class="fchip">momentum</span><span class="fchip">cowtan</span><span class="fchip">coastline-reserve</span><span class="fchip">cowtan-tout</span><span class="fchip">phillipe-romano-textiles</span><span class="fchip">astek</span><span class="fchip">ascreation</span><span class="fchip">wolfgordon</span><span class="fchip">pf-fabric-10110</span><span class="fchip">pierrefreyfabrics</span><span class="fchip">scalamandre</span><span class="fchip">sangetsu</span><span class="fchip">milton-king</span><span class="fchip">phillipjeffries</span><span class="fchip">rebelwalls</span><span class="fchip">jeffreystevens</span><span class="fchip">internal.schumacher</span><span class="fchip">china</span><span class="fchip">quadrille</span><span class="fchip">malibu</span><span class="fchip">marburg</span><span class="fchip">hollywood</span><span class="fchip">sancar</span><span class="fchip">philliperomano</span><span class="fchip">graham-brown</span><span class="fchip">coordonn</span><span class="fchip">coordonne</span><span class="fchip">designtex</span><span class="fchip">chinaseas</span><span class="fchip">romo</span><span class="fchip">jf-fabrics</span><span class="fchip">goodrich</span><span class="fchip">eijffinger</span><span class="fchip">koroseal</span><span class="fchip">murals</span><span class="fchip">philipjeffries</span><span class="fchip">schumacher</span><span class="fchip">phillipe-romano-vinyls</span><span class="fchip">holly-hunt</span><span class="fchip">arte</span><span class="fchip">thibaut</span><span class="fchip">j-josephson</span><span class="fchip">omexco</span><span class="fchip">koroseal-sg</span><span class="fchip">maharam</span></div>
+</div></section>
+
+<section id="integrity"><div class="eyebrow">02 · Catalog Integrity — the 5-Field Read</div><h2 class="disp">Where the catalog leaks revenue.</h2><div class="accbody">
+ <p class="lead2">The house rule: every active product needs a sample variant, a sellable variant, complete pricing, a description, and tags — plus a featured image. Against 80,522 actives, the live counts:</p>
+ <div class="chartwrap"><div class="ct">Actives failing each field (live mirror counts)</div><canvas id="ffChart"></canvas></div>
+ <div class="flagbox"><div class="i">◆</div><div><h3 class="disp">The 22,952-product finding</h3><p><b>26,737</b> actives are sample-only. <b>3,785</b> of those are quote-only lines by design. The remaining <b>22,952</b> — a third of the live catalog — can be browsed and sampled but not bought. Every one is paid-for merchandising with the register removed. This is the single largest dormant-revenue pool in the business.</p></div></div>
+ <div class="chartwrap"><div class="ct">Sample-only actives — where they sit (top lines)</div><canvas id="soChart"></canvas></div>
+ <table><thead><tr><th>Vendor line</th><th>Sample-only actives</th></tr></thead><tbody><tr><td><b>Phillipe Romano</b></td><td>5,924</td></tr><tr><td><b>Phillip Jeffries</b></td><td>2,461</td></tr><tr><td><b>Koroseal</b></td><td>2,454</td></tr><tr><td><b>China Seas</b></td><td>1,776</td></tr><tr><td><b>Coordonné</b></td><td>1,300</td></tr><tr><td><b>Hollywood Wallcoverings</b></td><td>1,089</td></tr><tr><td><b>Designers Guild</b></td><td>840</td></tr><tr><td><b>Osborne & Little</b></td><td>820</td></tr></tbody></table>
+</div></section>
+
+<section id="competitors"><div class="eyebrow">03 · Competitive Landscape</div><h2 class="disp">Depth vs. polish: the field.</h2><div class="accbody">
+ <p class="lead2">DW's tracked competitor registry, rendered verbatim, plus an analyst read: DW wins on catalog depth and trade authority; the DTC natives win on front-end polish and brand voice. The play is closing the polish gap without surrendering the depth moat.</p>
+ <div class="chartwrap"><div class="ct">Catalog depth vs. digital polish — analyst-scored, 0–100</div><canvas id="compChart"></canvas></div>
+ <table><thead><tr><th>Competitor</th><th>Domain</th><th>Watch status</th><th>Products found</th><th>Notes</th></tr></thead><tbody><tr><td><b>Decorators Best</b></td><td>decoratorsbest.com</td><td>Active watch</td><td>26,607</td><td>Large catalog, public pricing. Carries Thibaut, Schumacher, Cole & Son, Kravet</td></tr><tr><td><b>Wallpapers To Go</b></td><td>wallpaperstogo.com</td><td>Active watch</td><td>25,001</td><td>Major retailer. York, Thibaut, Brewster, Norwall</td></tr><tr><td><b>Mahones Wallpaper</b></td><td>mahoneswallpapershop.com</td><td>Active watch</td><td>24,990</td><td>Traditional dealer. Most major brands.</td></tr><tr><td><b>L.A. Design Concepts</b></td><td>ladesignconcepts.com</td><td>Active watch</td><td>13,826</td><td>Discount dealer (40% off). Thibaut, Schumacher, Anna French</td></tr><tr><td><b>Finest Wallpaper</b></td><td>finestwallpaper.com</td><td>Active watch</td><td>1,046</td><td>Ralph Lauren, Thibaut. US/Canada pricing.</td></tr><tr><td><b>Burke Decor</b></td><td>burkedecor.com</td><td>Active watch</td><td>0</td><td>Home decor + wallpaper. Cole & Son, Brewster, York</td></tr><tr><td><b>Wallpaper Wholesaler</b></td><td>wallpaperwholesaler.com</td><td>Active watch</td><td>0</td><td>Custom site (not Shopify). 32K+ products. JSON-LD structured data. Sitemap: /sitemaps/sitemap-products-{1,2}.xml. Brands: Brewster, MDC, Mind the Gap, Sancar, Eykon, National Wallcovering, Norwall. Quote-only: Astek, Fabricut, Innovations, PJ, S.Harris, Stroheim, Trend, Vervain.</td></tr><tr><td><b>Peelstick</b></td><td>peelstick.com</td><td>Paused</td><td>0</td><td>Peel & stick only — different category</td></tr></tbody></table>
+ <div id="compmap"></div>
+ <p class="lead2" style="font-size:15px;margin-top:14px;opacity:.7">The field, mapped: DW in Los Angeles vs. tracked competitor HQs (analyst-compiled geo). LA proximity to the design trade + studios is a structural advantage none of them share.</p>
+</div></section>
+
+<section id="advertising"><div class="eyebrow">04 · Channels & Distribution</div><h2 class="disp">Seven channels, one command center.</h2><div class="accbody">
+ <p class="lead2">Live from the marketing command center at collection time: <b>7 of 7</b> platforms connected. The Facebook page network alone spans <b>80</b> pages; Instagram <b>34</b> accounts. The infrastructure exists — the discipline to convert reach into attributed revenue is the build.</p>
+ <div class="chartwrap"><div class="ct">Connected accounts per platform (live)</div><canvas id="chanChart"></canvas></div>
+ <table><thead><tr><th>Platform</th><th>Status</th><th>Accounts</th><th>Note</th></tr></thead><tbody><tr><td><b>Facebook Pages</b></td><td><span class="good">Connected</span></td><td>80</td><td>Live in the marketing command center</td></tr><tr><td><b>Instagram</b></td><td><span class="good">Connected</span></td><td>34</td><td>Live in the marketing command center</td></tr><tr><td><b>TikTok</b></td><td><span class="good">Connected</span></td><td>1</td><td>Live in the marketing command center</td></tr><tr><td><b>YouTube</b></td><td><span class="good">Connected</span></td><td>1</td><td>Live in the marketing command center</td></tr><tr><td><b>Bluesky</b></td><td><span class="good">Connected</span></td><td>1</td><td>Live in the marketing command center</td></tr><tr><td><b>Threads</b></td><td><span class="good">Connected</span></td><td>1</td><td>Live in the marketing command center</td></tr><tr><td><b>LinkedIn</b></td><td><span class="good">Connected</span></td><td>1</td><td>Live in the marketing command center</td></tr></tbody></table>
+ <div class="cards2">
+ <div class="c"><h3>Attribution first</h3><p>Per-channel UTM + coupon discipline before spend scales. Today reach is broad but revenue attribution is dark — no channel can prove its keep.</p></div>
+ <div class="c"><h3>New-arrivals engine</h3><p>The activation drip ships ~500 products/day. Each batch is a native "new" story for every channel — content fuel most brands would pay to manufacture.</p></div>
+ <div class="c"><h3>AEO / AI answers</h3><p>The flagship already ships AI-answer-optimized collection copy. Extending AEO fleet-wide targets the search channel that's growing while classic SERP flattens.</p></div>
+ </div>
+</div></section>
+
+<section id="timing"><div class="eyebrow">05 · Timing & Cadence</div><h2 class="disp">The drip is live. Point it at revenue.</h2><div class="accbody">
+ <p class="lead2">New actives per week from the live mirror — the activation engine at work. The merchandising calendar below aligns campaigns to the natural intent cycle of the category.</p>
+ <div class="chartwrap"><div class="ct">New active products per week — last 12 weeks (live)</div><canvas id="cadenceChart"></canvas></div>
+ <table><thead><tr><th>Month</th><th>What the market is doing</th><th>The DW play</th></tr></thead><tbody><tr><td class="mo">Jan</td><td>New-year refresh intent peaks</td><td class="act">Push "one statement wall" entry offers; retarget Q4 samplers</td></tr><tr><td class="mo">Feb</td><td>Design-award season</td><td class="act">Editorial: trend reports off the catalog's own tag data</td></tr><tr><td class="mo">Mar</td><td>Spring project starts</td><td class="act">Trade outreach wave; hospitality spec season begins</td></tr><tr><td class="mo">Apr</td><td>High-intent renovation search</td><td class="act">Paid search on pattern + brand terms; AEO content sprint</td></tr><tr><td class="mo">May</td><td>Peak sample-ordering</td><td class="act">Sample-bundle promos; instrument sample→roll conversion</td></tr><tr><td class="mo">Jun</td><td>Mid-year new-arrivals surge</td><td class="act">The activation drip = daily "new" stories across channels</td></tr><tr><td class="mo">Jul</td><td>Summer install season</td><td class="act">Installer-partner co-marketing; project galleries</td></tr><tr><td class="mo">Aug</td><td>Pre-fall trade buying</td><td class="act">Designer-net program push; hospitality lookbook release</td></tr><tr><td class="mo">Sep</td><td>Fall flagship season</td><td class="act">Concept-direction launch (the new front page ships here)</td></tr><tr><td class="mo">Oct</td><td>Q4 project commits</td><td class="act">Retarget spring samplers; gift-adjacent art-line cross-sell</td></tr><tr><td class="mo">Nov</td><td>Holiday statement walls</td><td class="act">Peel-and-stick line forward; fast-ship messaging</td></tr><tr><td class="mo">Dec</td><td>Planning season</td><td class="act">Year-in-review design content; January intent capture</td></tr></tbody></table>
+</div></section>
+
+<section id="audit"><div class="eyebrow">06 · Website Audit</div><h2 class="disp">A strong engine that hides its best features.</h2><div class="accbody">
+ <p class="lead2">Analyst audit of the live flagship (Shopify + Boost search): the merchandising infrastructure is genuinely advanced — the gap is guided discovery for the retail buyer facing 80,522 choices.</p>
+ <div class="cards2">
+ <div class="c"><h3>Working well</h3><p class="good">Left-rail collection navigation · shop-by-color wheel with type pills · AEO content blocks on collections · sort + density controls on grids · New Arrivals / Trending smart collections refreshed by daily tag-sync · $4.25 memo-sample funnel on every product.</p></div>
+ <div class="c"><h3>Gaps</h3><p class="flag">Sample-only products present a dead-end buy box (22,952 products) · zero-price actives surface in feeds (1,444) · 333 actives lack a featured image · curation layers (rooms, moods, designer picks) are thin relative to catalog depth.</p></div>
+ <div class="c"><h3>Action</h3><p>Fix the integrity backlog (Section 02), then ship a guided-discovery layer: room/mood entry points, "pairs well with" on every PDP, and a designer-picks editorial tier — the concept directions in Section 08 show the face of it.</p></div>
+ </div>
+</div></section>
+
+<section id="social"><div class="eyebrow">07 · Social Audit</div><h2 class="disp">Broad reach, quiet voice.</h2><div class="accbody">
+ <p class="lead2">All major platforms are connected through one command center — a real infrastructure asset. The audit finding is consistent across platforms: <b>distribution exists, engagement discipline doesn't yet</b>. The page network posts; it doesn't yet converse, attribute, or convert.</p>
+ <div class="cards2">
+ <div class="c"><h3>Connected & ready</h3><p class="good">Facebook Pages · Instagram · TikTok · YouTube · Bluesky · Threads · LinkedIn</p></div>
+ <div class="c"><h3>The gap</h3><p class="flag">No per-channel revenue attribution · posting cadence not synced to the activation drip · reels/video formats underused relative to the category (interiors is a visual-first vertical).</p></div>
+ <div class="c"><h3>The play</h3><p>One flagship voice + the page network as amplifiers. Daily new-arrival stories (auto-fed by the drip), weekly designer-pick reels, per-channel UTM coupons — measured, not sprayed.</p></div>
+ </div>
+</div></section>
+
+<section id="suggested"><div class="eyebrow">08 · Suggested New Flagships</div><h2 class="disp">Six directions worthy of the catalog.</h2><div class="accbody">
+ <p class="lead2">Six full front-page concepts — each after a house that owns its lane, each a working page with the mandatory sort + density controls on its grid. Not palette swaps: different merchandising philosophies. Open each live and pick the direction.</p>
+ <div class="vgrid">
+ <a class="vtile rv" href="/versions/atelier.html" target="_blank" style="--vb:#f4f0e6;--vi:#26221a;--vg:#8a7340">
+ <div class="vswatch"><span style="background:#f4f0e6"></span><span style="background:#e9e2d0"></span><span style="background:#8a7340"></span><span style="background:#26221a"></span></div>
+ <div class="vname">Atelier</div><div class="vmodel">after de Gournay</div>
+ <div class="vmood">Scenic-house minimalism — ivory ground, celadon accents, art-object product pages.</div><div class="vopen">Open live concept →</div>
+ </a>
+ <a class="vtile rv" href="/versions/maison.html" target="_blank" style="--vb:#1c2331;--vi:#f2efe6;--vg:#d9b877">
+ <div class="vswatch"><span style="background:#1c2331"></span><span style="background:#26304a"></span><span style="background:#d9b877"></span><span style="background:#f2efe6"></span></div>
+ <div class="vname">Maison</div><div class="vmodel">after Pierre Frey</div>
+ <div class="vmood">French maison energy — indigo + ochre, pattern-forward editorial storytelling.</div><div class="vopen">Open live concept →</div>
+ </a>
+ <a class="vtile rv" href="/versions/studio.html" target="_blank" style="--vb:#faf7f2;--vi:#1d1b17;--vg:#d96a3b">
+ <div class="vswatch"><span style="background:#faf7f2"></span><span style="background:#f0e9dd"></span><span style="background:#d96a3b"></span><span style="background:#1d1b17"></span></div>
+ <div class="vname">Studio</div><div class="vmodel">after Backdrop (DTC)</div>
+ <div class="vmood">DTC-playful — bold color blocks, plain language, sample-first funnel.</div><div class="vopen">Open live concept →</div>
+ </a>
+ <a class="vtile rv" href="/versions/heritage.html" target="_blank" style="--vb:#232820;--vi:#efeee6;--vg:#b7a878">
+ <div class="vswatch"><span style="background:#232820"></span><span style="background:#2e352a"></span><span style="background:#b7a878"></span><span style="background:#efeee6"></span></div>
+ <div class="vname">Heritage</div><div class="vmodel">after Farrow & Ball</div>
+ <div class="vmood">Estate heritage — muted greens, archival typography, room-story merchandising.</div><div class="vopen">Open live concept →</div>
+ </a>
+ <a class="vtile rv" href="/versions/texture.html" target="_blank" style="--vb:#0f0d0b;--vi:#f1ece3;--vg:#c9a24b">
+ <div class="vswatch"><span style="background:#0f0d0b"></span><span style="background:#191510"></span><span style="background:#c9a24b"></span><span style="background:#f1ece3"></span></div>
+ <div class="vname">Texture</div><div class="vmodel">after Arte International</div>
+ <div class="vmood">Immersive texture — full-bleed material macros, dark gallery chrome, slow motion.</div><div class="vopen">Open live concept →</div>
+ </a>
+ <a class="vtile rv" href="/versions/gallery.html" target="_blank" style="--vb:#101012;--vi:#f4f2ee;--vg:#caa96a">
+ <div class="vswatch"><span style="background:#101012"></span><span style="background:#1a1a1e"></span><span style="background:#caa96a"></span><span style="background:#f4f2ee"></span></div>
+ <div class="vname">Gallery</div><div class="vmodel">after 1stDibs</div>
+ <div class="vmood">Marketplace-luxe — curated collections, provenance chips, designer-first navigation.</div><div class="vopen">Open live concept →</div>
+ </a></div>
+</div></section>
+
+<section id="partners"><div class="eyebrow">09 · Unlikely Partners</div><h2 class="disp">Channels that don't look like channels.</h2><div class="accbody">
+ <p class="lead2">Eight partnership lanes where DW's LA position and trade heritage do the acquisition work.</p>
+ <div class="pcard rv"><div class="pnum">01</div><div><h4>Interior-design trade programs (ASID, IIDA chapters)</h4><p>The trade IS the buyer. Chapter sponsorships + a designer-net portal turn 30 years of relationships into a structured acquisition channel.</p></div></div><div class="pcard rv"><div class="pnum">02</div><div><h4>Professional installers / paper-hangers network</h4><p>An installer directory referral loop: DW sends install-ready clients, installers send spec-stage clients. Both sides win on every roll.</p></div></div><div class="pcard rv"><div class="pnum">03</div><div><h4>Boutique hotels & hospitality designers</h4><p>Contract lines (Type II) already in catalog — a hospitality lookbook + spec-sheet service opens recurring project-scale orders.</p></div></div><div class="pcard rv"><div class="pnum">04</div><div><h4>Real-estate stagers & luxury listing agents</h4><p>Statement walls sell listings. A stager program (rapid samples + the peel-and-stick line) creates repeat commercial buyers.</p></div></div><div class="pcard rv"><div class="pnum">05</div><div><h4>Art-print & framing houses</h4><p>The art-print line proves the adjacency: walls + art as one "finished room" offer, cross-sold at zero acquisition cost.</p></div></div><div class="pcard rv"><div class="pnum">06</div><div><h4>Paint brands & color consultants</h4><p>Color-matched pairings ("this paper + these three paints") — co-marketing that borrows the paint brand's search volume.</p></div></div><div class="pcard rv"><div class="pnum">07</div><div><h4>Design schools (LA trade programs)</h4><p>Student memo access + a young-designer program seeds the next decade of trade accounts for the cost of samples.</p></div></div><div class="pcard rv"><div class="pnum">08</div><div><h4>Film / TV set decorators</h4><p>LA-native advantage: a set-decorator fast lane (rush memos, buyout-friendly licensing) monetizes proximity to the studios.</p></div></div>
+</div></section>
+
+<section id="revenue"><div class="eyebrow">10 · Unlikely Revenue</div><h2 class="disp">The money already in the building.</h2><div class="accbody">
+ <p class="lead2">Before any new audience is bought, six revenue pools sit inside the existing operation:</p>
+ <div class="sugg">
+ <div class="s"><div class="p">Pool 1 · largest</div><h4>The sellable-variant backlog</h4><p>22,952 active products browseable but not buyable. Even a 1% conversion at category AOV is a six-figure annual pool. Remediation is data work, not marketing spend.</p></div>
+ <div class="s"><div class="p">Pool 2 · compounding</div><h4>Sample → roll funnel</h4><p>The $4.25 memo program generates purchase-intent signals daily. Instrumented follow-up (sampled-but-didn't-buy sequences) converts existing intent at near-zero cost.</p></div>
+ <div class="s"><div class="p">Pool 3 · scheduled</div><h4>The staged-draft drip</h4><p>16,055 drafts activating ~500/day = a permanent "new arrivals" marketing engine. Sync email + social to the drip and every day ships its own campaign.</p></div>
+ <div class="s"><div class="p">Pool 4 · zero-inventory</div><h4>Original design licensing</h4><p>Settlement-gated original pattern IP licensed to print-on-demand marketplaces — revenue without inventory, already piloted in the wider operation.</p></div>
+ <div class="s"><div class="p">Pool 5 · trade</div><h4>Designer-net portal</h4><p>Formalize trade pricing behind a designer login. Trade buyers are the highest-LTV segment and currently buy through the retail flow.</p></div>
+ <div class="s"><div class="p">Pool 6 · projects</div><h4>Hospitality / contract desk</h4><p>Type II contract lines already in catalog. A spec-sheet + quote desk turns one hotel corridor into 400 rolls.</p></div>
+ </div>
+ <div class="chartwrap"><div class="ct">Priced-subset architecture (basis: min variant > $4.25 memo — partial, labeled)</div><canvas id="bandChart"></canvas></div>
+</div></section>
+
+<section id="desk"><div class="eyebrow">11 · Live Commerce Desk</div><h2 class="disp">The operation, on one screen.</h2><div class="accbody">
+ <p class="lead2">Live KPIs from the Jul 26, 2026, 8:02 AM snapshot — the numbers a weekly growth review should open with. Hit ↻ Refresh (top right) to re-collect on demand.</p>
+ <div class="kpis">
+ <div class="kpi"><div class="kv">80,522</div><div class="kl">Active products</div></div>
+ <div class="kpi"><div class="kv">16,055</div><div class="kl">Staged drafts</div></div>
+ <div class="kpi"><div class="kv">2,793</div><div class="kl">Stageable today (variant + image)</div></div>
+ <div class="kpi"><div class="kv">22,952</div><div class="kl">Sample-only backlog (non-quote)</div></div>
+ <div class="kpi"><div class="kv">1,444</div><div class="kl">Zero-price actives</div></div>
+ <div class="kpi"><div class="kv">333</div><div class="kl">Image-less actives</div></div>
+ <div class="kpi"><div class="kv">174</div><div class="kl">Vendor lines live</div></div>
+ <div class="kpi"><div class="kv">287</div><div class="kl">Fleet microsites</div></div>
</div>
+ <div class="chartwrap"><div class="ct">Weekly activation cadence (same data as Section 05 — the desk's pulse line)</div><canvas id="deskChart"></canvas></div>
+</div></section>
- <section>
- <h2>Website concept directions <span class="badge" id="vcount">—</span></h2>
- <p class="list" style="color:#6b6357">Several high-end redesign concepts of your new site — pick the direction that feels right. (Generate/refresh with <code>node build.mjs</code>.)</p>
- <div class="cards" id="versions"></div>
- </section>
+<section id="roadmap"><div class="eyebrow">12 · 90-Day Roadmap</div><h2 class="disp">What to do, in order.</h2><div class="accbody">
+ <ul class="road">
+ <li><div class="w">Weeks 1–2</div><div class="d"><b>Integrity sprint:</b> triage the 22,952 sample-only backlog by vendor (top 8 lines = 16,664 products); fix zero-price and image-less actives. Wire per-channel UTM + coupon attribution. Pick a concept direction from Section 08.</div></li>
+ <li><div class="w">Weeks 3–6</div><div class="d"><b>Convert intent:</b> ship the sampled-but-didn't-buy email sequence off the memo funnel. Sync daily social posting to the activation drip. Start the designer-net trade portal build.</div></li>
+ <li><div class="w">Weeks 6–10</div><div class="d"><b>Ship the face:</b> launch the chosen flagship direction (guided discovery: rooms, moods, designer picks). Extend AEO blocks fleet-wide. Sign 3 unlikely-partner deals (one installer network, one stager program, one hospitality designer).</div></li>
+ <li><div class="w">Weeks 10–13</div><div class="d"><b>Measure & double down:</b> channel-level revenue review off the new attribution; scale the winner. Open the contract/hospitality quote desk. Publish the first licensing-line results.</div></li>
+ </ul>
+</div></section>
- <section>
- <h2>Priority growth moves</h2>
- <ul class="list" id="sugs"></ul>
- </section>
+<section id="sources"><div class="eyebrow">13 · Sources & Methodology</div><h2 class="disp">Where every number comes from.</h2><div class="accbody">
+ <p class="lead2">Snapshot collected <b>Jul 26, 2026, 8:02 AM</b> by a read-only collector. Live rows are measured; analyst rows are authored judgment; anything illustrative says so.</p>
+ <div class="srclegend"><span class="srcb r">Live snapshot</span><span class="srcb a">Analyst view</span><span class="srcb d">Computed</span><span class="srcb e">Illustrative</span></div>
+ <table><thead><tr><th>Section</th><th>Where it comes from</th><th>How it's produced</th><th>Provenance</th></tr></thead><tbody><tr><td><b>Catalog KPIs — statuses, vendors, types, integrity, cadence</b></td><td>The dw_unified local mirror (READ-ONLY psql over the /tmp socket)</td><td>Collected by <code>scripts/collect-dw.mjs</code> at <b>Jul 26, 2026, 8:02 AM</b>; every number on this page renders from that snapshot</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>5-field / sample-only split</b></td><td>Mirror rollup columns (has_sample_variant, has_product_variant, has_description, image_url) + the quotes tag</td><td>Direct SQL counts; quote-only lines (by-design sample-only) separated from true backlog</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Social channel status</b></td><td>The DW marketing command center API (marketing.designerwallcoverings.com)</td><td>Authenticated status read at collection time — connected flags + account counts per platform</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Microsite fleet</b></td><td>The fleet aggregator directory API (all.designerwallcoverings.com)</td><td>287 sites enumerated at collection time</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Competitor watch-list</b></td><td>The connie_competitors table (the DW competitor-scan registry)</td><td>Rendered verbatim: domain, watch status, products found by prior scans</td><td class="srccell"><span class="srcb r">Live snapshot</span></td></tr><tr><td><b>Competitor scoring chart + map pins</b></td><td>Analyst assessment over public sites; HQ geo compiled from public records</td><td>Authored consulting view — NOT scraped metrics; the map is oriented, not surveyed</td><td class="srccell"><span class="srcb a">Analyst view</span></td></tr><tr><td><b>Price-band chart</b></td><td>products whose minimum variant exceeds the $4.25 memo sample — the priced subset of the mirror (~3.8k); most actives resolve min-variant to the sample, and full variant-level pricing lives Shopify-side</td><td>Partial-basis chart, labeled as such — full variant pricing lives Shopify-side</td><td class="srccell"><span class="srcb d">Computed</span></td></tr><tr><td><b>Website & social audits, partners, revenue plays, roadmap</b></td><td>Analyst strategy grounded in the operating knowledge of the DW stack</td><td>Consulting recommendations — models and plays, not measurements</td><td class="srccell"><span class="srcb a">Analyst view</span></td></tr><tr><td><b>Hero & section imagery</b></td><td>Unsplash editorial stock (luxury materials, per the luxe-only imagery rule)</td><td>Hotlinked, decorative only — carries no data meaning</td><td class="srccell"><span class="srcb e">Illustrative</span></td></tr></tbody></table>
+ <div class="srcnote"><div class="i">⚙</div><div><h4>How this document is built</h4><p>Generated, not hand-typed. A read-only collector (<code>scripts/collect-dw.mjs</code>) snapshots the DW systems into <code>data/dw-analysis.json</code>; the build (<code>build.mjs</code>) renders that snapshot into this page. The ↻ Refresh button re-runs collector + build on demand. Nothing writes to any DW production system.</p></div></div>
+</div></section>
- <section>
- <h2>Integrated social snapshot</h2>
- <ul class="list" id="social"></ul>
- </section>
+<footer><span>Designer Wallcoverings · Growth Strategy Brief</span><span>Data as of Jul 26, 2026, 8:02 AM</span><span>Confidential — for discussion</span></footer>
<script>
-async function j(u){ const r = await fetch(u); return r.ok ? r.json() : null; }
-(async () => {
- const c = await j('/api/client'); if (c && c.business_name){ document.getElementById('name').textContent = c.business_name; document.getElementById('brand').textContent = c.business_name; if(c.tagline) document.getElementById('tag').textContent = c.tagline; }
- // version concepts (generated into /versions by build.mjs)
- const known = ['flagship','editorial','modern','bold','warm','classic'];
- const vc = document.getElementById('versions'); let found = 0;
- for (const v of known){ const ok = await fetch('/versions/'+v+'.html',{method:'HEAD'}).then(r=>r.ok).catch(()=>false);
- if(ok){ found++; const a=document.createElement('a'); a.className='vcard'; a.href='/versions/'+v+'.html';
- a.innerHTML='<div class="swatch"></div><div class="body"><b>'+v+'</b></div>'; vc.appendChild(a); } }
- document.getElementById('vcount').textContent = found + ' concepts';
- if(!found) vc.innerHTML = '<p style="font-family:system-ui;color:#9a9082">No concepts generated yet — run <code>node build.mjs</code>.</p>';
- // suggestions
- const s = await j('/api/admin/suggestions')||[]; const su=document.getElementById('sugs');
- su.innerHTML = s.length ? s.map(x=>'<li><b>'+(x.title||'')+'</b> <span class="badge">impact '+(x.impact||'?')+' / effort '+(x.effort||'?')+'</span><br><span style="color:#6b6357">'+(x.rationale||'')+'</span></li>').join('') : '<li style="color:#9a9082">No growth moves seeded yet.</li>';
- // socials
- const so = await j('/api/admin/socials')||{}; const el=document.getElementById('social');
- const rows = Object.entries(so).filter(([k])=>!['connected','notes'].includes(k)).map(([k,v])=>'<li><b>'+k+'</b> — '+(v?('<a href="'+(String(v).startsWith('http')?v:'#')+'">'+v+'</a>'):'<span style="color:#c66">not set up yet</span>')+'</li>');
- el.innerHTML = rows.join('') + (so.notes?'<li style="color:#9a9082;font-size:13px">'+so.notes+'</li>':'');
-})();
+(function(){var s=document.querySelectorAll('.hero .slide'),i=0;if(s.length<2)return;setInterval(function(){s[i].classList.remove('on');i=(i+1)%s.length;s[i].classList.add('on');},5200);})();
+var REDUCE=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
+function countUp(el){var t=+el.dataset.c;if(!t)return;if(REDUCE){el.textContent=t.toLocaleString();return;}var d=1300,st=null;function step(ts){st=st||ts;var p=Math.min((ts-st)/d,1),e=1-Math.pow(1-p,3);el.textContent=Math.round(t*e).toLocaleString();if(p<1)requestAnimationFrame(step);}requestAnimationFrame(step);}
+var secs=[].slice.call(document.querySelectorAll('section[id]'));var accs=[];
+secs.forEach(function(sec){var eb=sec.querySelector(':scope>.eyebrow'),h2=sec.querySelector(':scope>h2');if(!eb&&!h2)return;accs.push(sec);
+ var head=document.createElement('button');head.type='button';head.className='acchead';var txt=document.createElement('div');txt.className='htext';if(eb)txt.appendChild(eb);if(h2)txt.appendChild(h2);
+ var chev=document.createElement('span');chev.className='chev';chev.textContent='+';head.appendChild(txt);head.appendChild(chev);sec.insertBefore(head,sec.querySelector('.accbody'));
+ head.addEventListener('click',function(){var open=sec.classList.toggle('open');chev.textContent=open?'\u2013':'+';if(open){initCharts();initMap();drawRoad(sec);}});});
+function drawRoad(sec){var rd=sec.querySelector('.road');if(rd)setTimeout(function(){rd.classList.add('drawn');},140);}
+function setAll(o){accs.forEach(function(s){s.classList.toggle('open',o);var c=s.querySelector('.chev');if(c)c.textContent=o?'\u2013':'+';if(o)drawRoad(s);});if(o){initCharts();initMap();}}
+document.getElementById('xall').onclick=function(){setAll(true);};document.getElementById('call').onclick=function(){setAll(false);};
+document.querySelectorAll('.menu a[href^="#"]').forEach(function(a){a.addEventListener('click',function(){var id=a.getAttribute('href').slice(1),s=document.getElementById(id);if(s&&!s.classList.contains('open')&&s.querySelector('.acchead')){s.querySelector('.acchead').click();}if(s)setTimeout(function(){s.scrollIntoView({behavior:'smooth'});},80);});});
+(function(){var burger=document.querySelector('.burger');if(!burger)return;function sync(){burger.setAttribute('aria-expanded',document.body.classList.contains('nav'));}new MutationObserver(sync).observe(document.body,{attributes:true,attributeFilter:['class']});sync();})();
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+document.querySelectorAll('.metrics .v[data-c]').forEach(function(el){var mo=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){countUp(el);mo.unobserve(el);}});});mo.observe(el);});
+document.getElementById('refbtn').addEventListener('click',function(){var b=this;b.disabled=true;b.textContent='↻ Refreshing…';fetch('/api/refresh',{method:'POST'}).then(function(r){return r.json();}).then(function(d){if(d.ok){b.textContent='↻ Rebuilt — reloading';setTimeout(function(){location.reload();},600);}else{b.textContent='↻ '+(d.error||'unavailable here');b.disabled=false;}}).catch(function(){b.textContent='↻ Refresh unavailable';b.disabled=false;});});
+var charted=false;
+function initCharts(){if(charted||!window.Chart)return;charted=true;
+ var gold='#c9a24b',dim='rgba(241,236,227,.6)',line='rgba(201,162,75,.18)';Chart.defaults.color=dim;Chart.defaults.font.family='Jost,system-ui,sans-serif';
+ var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
+ Chart.defaults.animation=RM?false:{duration:1150,easing:'easeInOutQuart'};
+ if(!RM){Chart.defaults.animations={y:{from:function(c){return c.chart.scales.y?c.chart.scales.y.getPixelForValue(0):0;}}};}
+ var D={"cadence":{"labels":["05-11","05-25","06-01","06-08","06-15","06-22","06-29","07-06","07-13","07-20"],"added":[490,3,492,924,1993,1510,1854,4255,1471,3377]},"vendors":{"labels":["Phillipe Romano","Rebel Walls","Clarke And Clarke","Hollywood Wallcoverings","Malibu Wallpaper","Thibaut","Jeffrey Stevens","Brunschwig & Fils","Kravet","Phillip Jeffries"],"counts":[11270,3770,3570,3515,3232,2987,2884,2761,2616,2469]},"types":{"labels":["Wallcovering","Fabric","Commercial Fabric","Mural","Wallcoverings","Memo Sample"],"counts":[58283,16195,1797,1305,453,451]},"integrity":{"labels":["Missing sellable variant","Missing sample variant","Zero / null price","Missing image","Missing description"],"counts":[26737,2298,1444,333,172]},"bands":{"labels":["Under $50","$50–150","$150–300","$300–600","$600+"],"counts":[2118,699,435,443,129]},"channels":{"labels":["Facebook Pages","Instagram","TikTok","YouTube","Bluesky","Threads","LinkedIn"],"accounts":[80,34,1,1,1,1,1]},"sampleOnlyVendors":{"labels":["Phillipe Romano","Phillip Jeffries","Koroseal","China Seas","Coordonné","Hollywood Wallcoverings","Designers Guild","Osborne & Little"],"counts":[5924,2461,2454,1776,1300,1089,840,820]},"comp":{"labels":["Designer Wallcoverings","DecoratorsBest","Burke Decor","Mahones","Finest Wallpaper","Steve's B&W"],"catalog":[96,62,48,55,40,45],"digital":[58,82,78,60,42,55]}};
+ function mk(id,cfg){var el=document.getElementById(id);if(el)new Chart(el,cfg);}
+ mk('vendorChart',{type:'bar',data:{labels:D.vendors.labels,datasets:[{label:'Active products',data:D.vendors.counts,backgroundColor:'rgba(201,162,75,.75)'}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('typeChart',{type:'doughnut',data:{labels:D.types.labels,datasets:[{data:D.types.counts,backgroundColor:['#c9a24b','#b78d3f','#a67c32','#d9b877','#8f6d2c','#e3c98d'],borderColor:'#0e0c09',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'right',labels:{color:dim,boxWidth:12}}},cutout:'58%'}});
+ mk('ffChart',{type:'bar',data:{labels:D.integrity.labels,datasets:[{label:'Actives failing',data:D.integrity.counts,backgroundColor:D.integrity.counts.map(function(v){return v>10000?'rgba(232,160,160,.8)':'rgba(201,162,75,.6)';})}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('soChart',{type:'bar',data:{labels:D.sampleOnlyVendors.labels,datasets:[{label:'Sample-only actives',data:D.sampleOnlyVendors.counts,backgroundColor:'rgba(232,160,160,.7)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('compChart',{type:'bar',data:{labels:D.comp.labels,datasets:[{label:'Catalog depth',data:D.comp.catalog,backgroundColor:'rgba(201,162,75,.75)'},{label:'Digital polish',data:D.comp.digital,backgroundColor:'rgba(120,170,255,.6)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line},max:100},x:{grid:{display:false}}},plugins:{legend:{labels:{color:dim}}}}});
+ mk('chanChart',{type:'bar',data:{labels:D.channels.labels,datasets:[{label:'Connected accounts',data:D.channels.accounts,backgroundColor:'rgba(201,162,75,.75)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('cadenceChart',{type:'line',data:{labels:D.cadence.labels,datasets:[{label:'New actives / week',data:D.cadence.added,borderColor:gold,backgroundColor:'rgba(201,162,75,.12)',fill:true,tension:.4,pointRadius:4}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('deskChart',{type:'line',data:{labels:D.cadence.labels,datasets:[{label:'New actives / week',data:D.cadence.added,borderColor:gold,backgroundColor:'rgba(201,162,75,.12)',fill:true,tension:.4,pointRadius:4}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+ mk('bandChart',{type:'bar',data:{labels:D.bands.labels,datasets:[{label:'Products (priced subset)',data:D.bands.counts,backgroundColor:'rgba(201,162,75,.6)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
+}
+var mapped=false;
+function initMap(){if(mapped||!window.L||!document.getElementById('compmap'))return;mapped=true;
+ var pts=[{"name":"Designer Wallcoverings — Los Angeles","lat":34.076,"lng":-118.377,"you":true,"note":"HQ · showroom · 80,522 live SKUs"},{"name":"DecoratorsBest","lat":40.752,"lng":-73.993,"note":"New York, NY — designer-brand e-commerce"},{"name":"Burke Decor","lat":41.099,"lng":-80.649,"note":"Youngstown, OH — home decor + wallpaper"},{"name":"Mahone's Wallpaper Shop","lat":37.089,"lng":-76.473,"note":"Newport News, VA — wallpaper specialist"},{"name":"Finest Wallpaper","lat":43.09,"lng":-79.08,"note":"Ontario, Canada — designer lines, US/CA pricing"},{"name":"Steve's Blinds & Wallpaper","lat":42.58,"lng":-83.03,"note":"Sterling Heights, MI — discount volume"}];
+ var m=L.map('compmap',{scrollWheelZoom:false}).setView([38.5,-96],4);
+ L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',{attribution:'© OpenStreetMap © CARTO',maxZoom:18}).addTo(m);
+ pts.forEach(function(p){var mk=L.circleMarker([p.lat,p.lng],{radius:p.you?10:7,color:p.you?'#c9a24b':'#78aaff',fillColor:p.you?'#c9a24b':'#78aaff',fillOpacity:.85,weight:1});
+ mk.bindPopup('<b>'+p.name+'</b><br>'+(p.note||''));mk.addTo(m);});
+ setTimeout(function(){m.invalidateSize();},300);
+}
</script>
-</body>
-</html>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/atelier.html b/public/versions/atelier.html
new file mode 100644
index 0000000..b8eaeec
--- /dev/null
+++ b/public/versions/atelier.html
@@ -0,0 +1,119 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Atelier concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:#f4f0e6;--panel:#e9e2d0;--ink:#26221a;--gold:#8a7340;--line:rgba(38,34,26,.16);--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Jost',system-ui,sans-serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Cormorant Garamond',Georgia,serif}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:#fff;font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:'Cormorant Garamond',Georgia,serif;font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:'Jost',system-ui,sans-serif;font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:'Cormorant Garamond',Georgia,serif;font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:#fff}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:'Jost',system-ui,sans-serif;font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:'Cormorant Garamond',Georgia,serif;font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:'Cormorant Garamond',Georgia,serif;font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:#fff;border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · de Gournay direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>Atelier · Hand-painted calm. The scenic house.</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">Hand-painted calm. The scenic house.</h1><p>Scenic-house minimalism — ivory ground, celadon accents, art-object product pages. A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid"><article class="gcard" data-title="Chinois Garden" data-hue="28" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(28,22%,78%),hsl(68,30%,64%))"></div>
+ <h4>Chinois Garden</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Venetian Plaster" data-hue="152" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(152,22%,78%),hsl(192,30%,64%))"></div>
+ <h4>Venetian Plaster</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Grasscloth No. 9" data-hue="208" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(208,22%,78%),hsl(248,30%,64%))"></div>
+ <h4>Grasscloth No. 9</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Deco Fan" data-hue="12" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(12,22%,78%),hsl(52,30%,64%))"></div>
+ <h4>Deco Fan</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Midnight Damask" data-hue="262" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(262,22%,78%),hsl(302,30%,64%))"></div>
+ <h4>Midnight Damask</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Coastal Weave" data-hue="88" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(88,22%,78%),hsl(128,30%,64%))"></div>
+ <h4>Coastal Weave</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Rosewood Toile" data-hue="340" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(340,22%,78%),hsl(20,30%,64%))"></div>
+ <h4>Rosewood Toile</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Celadon Silk" data-hue="190" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(190,22%,78%),hsl(230,30%,64%))"></div>
+ <h4>Celadon Silk</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Gilt Trellis" data-hue="46" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(46,22%,78%),hsl(86,30%,64%))"></div>
+ <h4>Gilt Trellis</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Amethyst Moire" data-hue="300" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(300,22%,78%),hsl(340,30%,64%))"></div>
+ <h4>Amethyst Moire</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Sage Stripe" data-hue="130" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(130,22%,78%),hsl(170,30%,64%))"></div>
+ <h4>Sage Stripe</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Terra Fresco" data-hue="20" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(20,22%,78%),hsl(60,30%,64%))"></div>
+ <h4>Terra Fresco</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article></div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "Atelier" (de Gournay direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-atelier-sort',KD='dwconcept-atelier-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/bold.html b/public/versions/bold.html
deleted file mode 100644
index 41f231b..0000000
--- a/public/versions/bold.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Designer Wallcoverings — Bold / energetic</title>
-<style>
-:root{--bg:#0d0d12;--ink:#f5f5f7;--accent:#ff4d6d}
-*{box-sizing:border-box}body{margin:0;font-family:'Arial Black',system-ui,sans-serif;background:var(--bg);color:var(--ink)}
-.bar{padding:14px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--accent)}
-.bar b{letter-spacing:.06em}.bar span{color:var(--accent);font-size:12px;text-transform:uppercase;letter-spacing:.2em}
-.hero{padding:90px 30px;text-align:center}
-.hero .k{color:var(--accent);letter-spacing:.3em;text-transform:uppercase;font-size:12px}
-.hero h1{font-size:56px;margin:.2em 0;font-weight:700}
-.hero p{font-size:20px;max-width:620px;margin:0 auto;opacity:.8}
-.cta{display:inline-block;margin-top:26px;background:var(--accent);color:var(--bg);padding:14px 32px;text-decoration:none;text-transform:uppercase;letter-spacing:.16em;font-size:13px}
-.goals{max-width:900px;margin:40px auto;padding:0 30px;display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:18px}
-.goals div{border:1px solid var(--accent);padding:22px;font-size:17px}
-.foot{padding:40px 30px;text-align:center;opacity:.6;font-size:13px}
-</style></head><body>
-<div class="bar"><b>Designer Wallcoverings</b><span>Bold / energetic concept</span></div>
-<div class="hero">
- <div class="k">Luxury wallcoverings & designer fabrics — e-commerce + to-the-trade · Los Angeles, CA</div>
- <h1>Designer Wallcoverings</h1>
- <p>A new website concept, ready to make your first impression unforgettable.</p>
- <a class="cta" href="#">Get in touch</a>
-</div>
-<div class="goals"><div>Grow retail conversion on the flagship Shopify store</div><div>Win AI-answer citations (AEO) for wallcovering queries</div><div>Turn the 15.8k staged-draft activation drip into measurable revenue</div><div>Social-to-revenue attribution across the 6 connected channels</div></div>
-<div class="foot">Concept "bold" · generated 2026-07-26 · one of several directions to choose from.</div>
-</body></html>
\ No newline at end of file
diff --git a/public/versions/classic.html b/public/versions/classic.html
deleted file mode 100644
index bb7db0e..0000000
--- a/public/versions/classic.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Designer Wallcoverings — Classic / trustworthy</title>
-<style>
-:root{--bg:#f4f4f0;--ink:#1c2530;--accent:#7a5b34}
-*{box-sizing:border-box}body{margin:0;font-family:'Times New Roman',serif;background:var(--bg);color:var(--ink)}
-.bar{padding:14px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--accent)}
-.bar b{letter-spacing:.06em}.bar span{color:var(--accent);font-size:12px;text-transform:uppercase;letter-spacing:.2em}
-.hero{padding:90px 30px;text-align:center}
-.hero .k{color:var(--accent);letter-spacing:.3em;text-transform:uppercase;font-size:12px}
-.hero h1{font-size:56px;margin:.2em 0;font-weight:700}
-.hero p{font-size:20px;max-width:620px;margin:0 auto;opacity:.8}
-.cta{display:inline-block;margin-top:26px;background:var(--accent);color:var(--bg);padding:14px 32px;text-decoration:none;text-transform:uppercase;letter-spacing:.16em;font-size:13px}
-.goals{max-width:900px;margin:40px auto;padding:0 30px;display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:18px}
-.goals div{border:1px solid var(--accent);padding:22px;font-size:17px}
-.foot{padding:40px 30px;text-align:center;opacity:.6;font-size:13px}
-</style></head><body>
-<div class="bar"><b>Designer Wallcoverings</b><span>Classic / trustworthy concept</span></div>
-<div class="hero">
- <div class="k">Luxury wallcoverings & designer fabrics — e-commerce + to-the-trade · Los Angeles, CA</div>
- <h1>Designer Wallcoverings</h1>
- <p>A new website concept, ready to make your first impression unforgettable.</p>
- <a class="cta" href="#">Get in touch</a>
-</div>
-<div class="goals"><div>Grow retail conversion on the flagship Shopify store</div><div>Win AI-answer citations (AEO) for wallcovering queries</div><div>Turn the 15.8k staged-draft activation drip into measurable revenue</div><div>Social-to-revenue attribution across the 6 connected channels</div></div>
-<div class="foot">Concept "classic" · generated 2026-07-26 · one of several directions to choose from.</div>
-</body></html>
\ No newline at end of file
diff --git a/public/versions/editorial.html b/public/versions/editorial.html
deleted file mode 100644
index db25fe0..0000000
--- a/public/versions/editorial.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Designer Wallcoverings — Luxury / editorial</title>
-<style>
-:root{--bg:#f6f2ec;--ink:#14110e;--accent:#a9884f}
-*{box-sizing:border-box}body{margin:0;font-family:Georgia,serif;background:var(--bg);color:var(--ink)}
-.bar{padding:14px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--accent)}
-.bar b{letter-spacing:.06em}.bar span{color:var(--accent);font-size:12px;text-transform:uppercase;letter-spacing:.2em}
-.hero{padding:90px 30px;text-align:center}
-.hero .k{color:var(--accent);letter-spacing:.3em;text-transform:uppercase;font-size:12px}
-.hero h1{font-size:56px;margin:.2em 0;font-weight:700}
-.hero p{font-size:20px;max-width:620px;margin:0 auto;opacity:.8}
-.cta{display:inline-block;margin-top:26px;background:var(--accent);color:var(--bg);padding:14px 32px;text-decoration:none;text-transform:uppercase;letter-spacing:.16em;font-size:13px}
-.goals{max-width:900px;margin:40px auto;padding:0 30px;display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:18px}
-.goals div{border:1px solid var(--accent);padding:22px;font-size:17px}
-.foot{padding:40px 30px;text-align:center;opacity:.6;font-size:13px}
-</style></head><body>
-<div class="bar"><b>Designer Wallcoverings</b><span>Luxury / editorial concept</span></div>
-<div class="hero">
- <div class="k">Luxury wallcoverings & designer fabrics — e-commerce + to-the-trade · Los Angeles, CA</div>
- <h1>Designer Wallcoverings</h1>
- <p>A new website concept, ready to make your first impression unforgettable.</p>
- <a class="cta" href="#">Get in touch</a>
-</div>
-<div class="goals"><div>Grow retail conversion on the flagship Shopify store</div><div>Win AI-answer citations (AEO) for wallcovering queries</div><div>Turn the 15.8k staged-draft activation drip into measurable revenue</div><div>Social-to-revenue attribution across the 6 connected channels</div></div>
-<div class="foot">Concept "editorial" · generated 2026-07-26 · one of several directions to choose from.</div>
-</body></html>
\ No newline at end of file
diff --git a/public/versions/gallery.html b/public/versions/gallery.html
new file mode 100644
index 0000000..6560937
--- /dev/null
+++ b/public/versions/gallery.html
@@ -0,0 +1,119 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Gallery concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:#101012;--panel:#1a1a1e;--ink:#f4f2ee;--gold:#caa96a;--line:rgba(202,169,106,.26);--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Inter',system-ui,sans-serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Playfair Display',Georgia,serif}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:#0b0b0c;font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:'Playfair Display',Georgia,serif;font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:'Inter',system-ui,sans-serif;font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:'Playfair Display',Georgia,serif;font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:#0b0b0c}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:'Inter',system-ui,sans-serif;font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:'Playfair Display',Georgia,serif;font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:'Playfair Display',Georgia,serif;font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:#0b0b0c;border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · 1stDibs direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>Gallery · The marketplace of extraordinary walls.</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">The marketplace of extraordinary walls.</h1><p>Marketplace-luxe — curated collections, provenance chips, designer-first navigation. A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid"><article class="gcard" data-title="Chinois Garden" data-hue="28" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(28,22%,24%),hsl(68,30%,14%))"></div>
+ <h4>Chinois Garden</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Venetian Plaster" data-hue="152" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(152,22%,24%),hsl(192,30%,14%))"></div>
+ <h4>Venetian Plaster</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Grasscloth No. 9" data-hue="208" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(208,22%,24%),hsl(248,30%,14%))"></div>
+ <h4>Grasscloth No. 9</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Deco Fan" data-hue="12" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(12,22%,24%),hsl(52,30%,14%))"></div>
+ <h4>Deco Fan</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Midnight Damask" data-hue="262" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(262,22%,24%),hsl(302,30%,14%))"></div>
+ <h4>Midnight Damask</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Coastal Weave" data-hue="88" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(88,22%,24%),hsl(128,30%,14%))"></div>
+ <h4>Coastal Weave</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Rosewood Toile" data-hue="340" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(340,22%,24%),hsl(20,30%,14%))"></div>
+ <h4>Rosewood Toile</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Celadon Silk" data-hue="190" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(190,22%,24%),hsl(230,30%,14%))"></div>
+ <h4>Celadon Silk</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Gilt Trellis" data-hue="46" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(46,22%,24%),hsl(86,30%,14%))"></div>
+ <h4>Gilt Trellis</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Amethyst Moire" data-hue="300" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(300,22%,24%),hsl(340,30%,14%))"></div>
+ <h4>Amethyst Moire</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Sage Stripe" data-hue="130" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(130,22%,24%),hsl(170,30%,14%))"></div>
+ <h4>Sage Stripe</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Terra Fresco" data-hue="20" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(20,22%,24%),hsl(60,30%,14%))"></div>
+ <h4>Terra Fresco</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article></div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "Gallery" (1stDibs direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-gallery-sort',KD='dwconcept-gallery-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/heritage.html b/public/versions/heritage.html
new file mode 100644
index 0000000..ef2c45e
--- /dev/null
+++ b/public/versions/heritage.html
@@ -0,0 +1,119 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Heritage concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:#232820;--panel:#2e352a;--ink:#efeee6;--gold:#b7a878;--line:rgba(183,168,120,.26);--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Jost',system-ui,sans-serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Cormorant Garamond',Georgia,serif}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:#0b0b0c;font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:'Cormorant Garamond',Georgia,serif;font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:'Jost',system-ui,sans-serif;font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:'Cormorant Garamond',Georgia,serif;font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:#0b0b0c}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:'Jost',system-ui,sans-serif;font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:'Cormorant Garamond',Georgia,serif;font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:'Cormorant Garamond',Georgia,serif;font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:#0b0b0c;border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · Farrow & Ball direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>Heritage · Colour, considered for a century.</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">Colour, considered for a century.</h1><p>Estate heritage — muted greens, archival typography, room-story merchandising. A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid"><article class="gcard" data-title="Chinois Garden" data-hue="28" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(28,22%,24%),hsl(68,30%,14%))"></div>
+ <h4>Chinois Garden</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Venetian Plaster" data-hue="152" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(152,22%,24%),hsl(192,30%,14%))"></div>
+ <h4>Venetian Plaster</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Grasscloth No. 9" data-hue="208" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(208,22%,24%),hsl(248,30%,14%))"></div>
+ <h4>Grasscloth No. 9</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Deco Fan" data-hue="12" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(12,22%,24%),hsl(52,30%,14%))"></div>
+ <h4>Deco Fan</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Midnight Damask" data-hue="262" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(262,22%,24%),hsl(302,30%,14%))"></div>
+ <h4>Midnight Damask</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Coastal Weave" data-hue="88" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(88,22%,24%),hsl(128,30%,14%))"></div>
+ <h4>Coastal Weave</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Rosewood Toile" data-hue="340" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(340,22%,24%),hsl(20,30%,14%))"></div>
+ <h4>Rosewood Toile</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Celadon Silk" data-hue="190" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(190,22%,24%),hsl(230,30%,14%))"></div>
+ <h4>Celadon Silk</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Gilt Trellis" data-hue="46" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(46,22%,24%),hsl(86,30%,14%))"></div>
+ <h4>Gilt Trellis</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Amethyst Moire" data-hue="300" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(300,22%,24%),hsl(340,30%,14%))"></div>
+ <h4>Amethyst Moire</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Sage Stripe" data-hue="130" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(130,22%,24%),hsl(170,30%,14%))"></div>
+ <h4>Sage Stripe</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Terra Fresco" data-hue="20" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(20,22%,24%),hsl(60,30%,14%))"></div>
+ <h4>Terra Fresco</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article></div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "Heritage" (Farrow & Ball direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-heritage-sort',KD='dwconcept-heritage-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/maison.html b/public/versions/maison.html
new file mode 100644
index 0000000..c19373c
--- /dev/null
+++ b/public/versions/maison.html
@@ -0,0 +1,119 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Maison concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:#1c2331;--panel:#26304a;--ink:#f2efe6;--gold:#d9b877;--line:rgba(217,184,119,.28);--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Inter',system-ui,sans-serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Playfair Display',Georgia,serif}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:#0b0b0c;font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:'Playfair Display',Georgia,serif;font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:'Inter',system-ui,sans-serif;font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:'Playfair Display',Georgia,serif;font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:#0b0b0c}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:'Inter',system-ui,sans-serif;font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:'Playfair Display',Georgia,serif;font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:'Playfair Display',Georgia,serif;font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:#0b0b0c;border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · Pierre Frey direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>Maison · The Parisian maison, digitized.</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">The Parisian maison, digitized.</h1><p>French maison energy — indigo + ochre, pattern-forward editorial storytelling. A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid"><article class="gcard" data-title="Chinois Garden" data-hue="28" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(28,22%,24%),hsl(68,30%,14%))"></div>
+ <h4>Chinois Garden</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Venetian Plaster" data-hue="152" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(152,22%,24%),hsl(192,30%,14%))"></div>
+ <h4>Venetian Plaster</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Grasscloth No. 9" data-hue="208" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(208,22%,24%),hsl(248,30%,14%))"></div>
+ <h4>Grasscloth No. 9</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Deco Fan" data-hue="12" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(12,22%,24%),hsl(52,30%,14%))"></div>
+ <h4>Deco Fan</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Midnight Damask" data-hue="262" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(262,22%,24%),hsl(302,30%,14%))"></div>
+ <h4>Midnight Damask</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Coastal Weave" data-hue="88" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(88,22%,24%),hsl(128,30%,14%))"></div>
+ <h4>Coastal Weave</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Rosewood Toile" data-hue="340" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(340,22%,24%),hsl(20,30%,14%))"></div>
+ <h4>Rosewood Toile</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Celadon Silk" data-hue="190" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(190,22%,24%),hsl(230,30%,14%))"></div>
+ <h4>Celadon Silk</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Gilt Trellis" data-hue="46" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(46,22%,24%),hsl(86,30%,14%))"></div>
+ <h4>Gilt Trellis</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Amethyst Moire" data-hue="300" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(300,22%,24%),hsl(340,30%,14%))"></div>
+ <h4>Amethyst Moire</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Sage Stripe" data-hue="130" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(130,22%,24%),hsl(170,30%,14%))"></div>
+ <h4>Sage Stripe</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Terra Fresco" data-hue="20" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(20,22%,24%),hsl(60,30%,14%))"></div>
+ <h4>Terra Fresco</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article></div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "Maison" (Pierre Frey direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-maison-sort',KD='dwconcept-maison-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/modern.html b/public/versions/modern.html
deleted file mode 100644
index d52fd08..0000000
--- a/public/versions/modern.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Designer Wallcoverings — Modern / minimal</title>
-<style>
-:root{--bg:#ffffff;--ink:#0b0b0d;--accent:#2b6cff}
-*{box-sizing:border-box}body{margin:0;font-family:'Helvetica Neue',system-ui,sans-serif;background:var(--bg);color:var(--ink)}
-.bar{padding:14px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--accent)}
-.bar b{letter-spacing:.06em}.bar span{color:var(--accent);font-size:12px;text-transform:uppercase;letter-spacing:.2em}
-.hero{padding:90px 30px;text-align:center}
-.hero .k{color:var(--accent);letter-spacing:.3em;text-transform:uppercase;font-size:12px}
-.hero h1{font-size:56px;margin:.2em 0;font-weight:700}
-.hero p{font-size:20px;max-width:620px;margin:0 auto;opacity:.8}
-.cta{display:inline-block;margin-top:26px;background:var(--accent);color:var(--bg);padding:14px 32px;text-decoration:none;text-transform:uppercase;letter-spacing:.16em;font-size:13px}
-.goals{max-width:900px;margin:40px auto;padding:0 30px;display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:18px}
-.goals div{border:1px solid var(--accent);padding:22px;font-size:17px}
-.foot{padding:40px 30px;text-align:center;opacity:.6;font-size:13px}
-</style></head><body>
-<div class="bar"><b>Designer Wallcoverings</b><span>Modern / minimal concept</span></div>
-<div class="hero">
- <div class="k">Luxury wallcoverings & designer fabrics — e-commerce + to-the-trade · Los Angeles, CA</div>
- <h1>Designer Wallcoverings</h1>
- <p>A new website concept, ready to make your first impression unforgettable.</p>
- <a class="cta" href="#">Get in touch</a>
-</div>
-<div class="goals"><div>Grow retail conversion on the flagship Shopify store</div><div>Win AI-answer citations (AEO) for wallcovering queries</div><div>Turn the 15.8k staged-draft activation drip into measurable revenue</div><div>Social-to-revenue attribution across the 6 connected channels</div></div>
-<div class="foot">Concept "modern" · generated 2026-07-26 · one of several directions to choose from.</div>
-</body></html>
\ No newline at end of file
diff --git a/public/versions/studio.html b/public/versions/studio.html
new file mode 100644
index 0000000..0acf4d9
--- /dev/null
+++ b/public/versions/studio.html
@@ -0,0 +1,119 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Studio concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:#faf7f2;--panel:#f0e9dd;--ink:#1d1b17;--gold:#d96a3b;--line:rgba(29,27,23,.14);--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Inter',system-ui,sans-serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Inter',system-ui,sans-serif}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:#fff;font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:'Inter',system-ui,sans-serif;font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:'Inter',system-ui,sans-serif;font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:'Inter',system-ui,sans-serif;font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:#fff}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:'Inter',system-ui,sans-serif;font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:'Inter',system-ui,sans-serif;font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:'Inter',system-ui,sans-serif;font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:#fff;border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · Backdrop (DTC) direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>Studio · Wallpaper, without the intimidation.</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">Wallpaper, without the intimidation.</h1><p>DTC-playful — bold color blocks, plain language, sample-first funnel. A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid"><article class="gcard" data-title="Chinois Garden" data-hue="28" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(28,22%,78%),hsl(68,30%,64%))"></div>
+ <h4>Chinois Garden</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Venetian Plaster" data-hue="152" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(152,22%,78%),hsl(192,30%,64%))"></div>
+ <h4>Venetian Plaster</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Grasscloth No. 9" data-hue="208" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(208,22%,78%),hsl(248,30%,64%))"></div>
+ <h4>Grasscloth No. 9</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Deco Fan" data-hue="12" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(12,22%,78%),hsl(52,30%,64%))"></div>
+ <h4>Deco Fan</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Midnight Damask" data-hue="262" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(262,22%,78%),hsl(302,30%,64%))"></div>
+ <h4>Midnight Damask</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Coastal Weave" data-hue="88" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(88,22%,78%),hsl(128,30%,64%))"></div>
+ <h4>Coastal Weave</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Rosewood Toile" data-hue="340" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(340,22%,78%),hsl(20,30%,64%))"></div>
+ <h4>Rosewood Toile</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Celadon Silk" data-hue="190" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(190,22%,78%),hsl(230,30%,64%))"></div>
+ <h4>Celadon Silk</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Gilt Trellis" data-hue="46" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(46,22%,78%),hsl(86,30%,64%))"></div>
+ <h4>Gilt Trellis</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Amethyst Moire" data-hue="300" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(300,22%,78%),hsl(340,30%,64%))"></div>
+ <h4>Amethyst Moire</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Sage Stripe" data-hue="130" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(130,22%,78%),hsl(170,30%,64%))"></div>
+ <h4>Sage Stripe</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Terra Fresco" data-hue="20" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(20,22%,78%),hsl(60,30%,64%))"></div>
+ <h4>Terra Fresco</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article></div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "Studio" (Backdrop (DTC) direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-studio-sort',KD='dwconcept-studio-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/texture.html b/public/versions/texture.html
new file mode 100644
index 0000000..a75a80f
--- /dev/null
+++ b/public/versions/texture.html
@@ -0,0 +1,119 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>Designer Wallcoverings — Texture concept</title>
+<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
+<style>
+:root{--bg:#0f0d0b;--panel:#191510;--ink:#f1ece3;--gold:#c9a24b;--line:rgba(201,162,75,.28);--cols:4}
+*{margin:0;padding:0;box-sizing:border-box}
+body{background:var(--bg);color:var(--ink);font-family:'Jost',system-ui,sans-serif;font-size:16px;line-height:1.55;-webkit-font-smoothing:antialiased}
+.disp{font-family:'Cormorant Garamond',Georgia,serif}a{color:inherit;text-decoration:none}
+.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:#0b0b0c;font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px}
+.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
+header{max-width:1240px;margin:0 auto;padding:26px 22px;display:flex;justify-content:space-between;align-items:flex-end;border-bottom:2px solid var(--gold)}
+.logo{font-family:'Cormorant Garamond',Georgia,serif;font-size:30px;letter-spacing:-.3px}.logo span{color:var(--gold)}
+.logo small{display:block;font-size:9.5px;letter-spacing:.32em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:'Jost',system-ui,sans-serif;font-weight:400}
+nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
+nav.sec .in{max-width:1240px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
+nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.05em;padding:15px 14px;white-space:nowrap;border-bottom:3px solid transparent}
+nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
+.heroc{max-width:1240px;margin:0 auto;padding:54px 22px;display:grid;grid-template-columns:1.25fr 1fr;gap:44px;align-items:center}
+.heroc h1{font-family:'Cormorant Garamond',Georgia,serif;font-size:clamp(34px,4.6vw,58px);line-height:1.06}
+.heroc p{margin-top:16px;opacity:.75;font-size:17px;max-width:52ch}
+.cta{display:inline-block;margin-top:26px;border:1px solid var(--gold);color:var(--gold);font-size:12px;letter-spacing:.22em;text-transform:uppercase;padding:13px 26px;border-radius:999px;transition:.25s}
+.cta:hover{background:var(--gold);color:#0b0b0c}
+.heroimg{aspect-ratio:4/3;border-radius:6px;background:linear-gradient(135deg,var(--panel),var(--gold))}
+.wrap{max-width:1240px;margin:0 auto;padding:0 22px}
+.sh{display:flex;align-items:center;justify-content:space-between;gap:18px;border-top:3px solid var(--gold);padding-top:12px;margin:34px 0 8px;flex-wrap:wrap}
+.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.08em;font-weight:600}
+.controls{display:flex;gap:14px;align-items:center;font-size:12px}
+.controls label{opacity:.7;letter-spacing:.08em;text-transform:uppercase;font-size:10.5px}
+.controls select{background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 10px;border-radius:4px;font-family:'Jost',system-ui,sans-serif;font-size:12px}
+.controls input[type=range]{accent-color:var(--gold);width:110px}
+.grid{display:grid;grid-template-columns:repeat(var(--cols),1fr);gap:20px;padding:18px 0 40px}
+.gcard .gimg{aspect-ratio:3/4;border-radius:5px;transition:.3s}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
+.gcard h4{font-family:'Cormorant Garamond',Georgia,serif;font-size:16.5px;margin:10px 0 2px}
+.gmeta{display:flex;justify-content:space-between;font-size:11px;opacity:.65;letter-spacing:.06em;text-transform:uppercase}
+.tier{color:var(--gold)}
+.ns{max-width:1240px;margin:10px auto 0;padding:44px 22px;border-top:1px solid var(--line);display:grid;grid-template-columns:1fr 1fr;gap:30px;align-items:center}
+.ns h3{font-family:'Cormorant Garamond',Georgia,serif;font-size:26px}.ns p{opacity:.7;font-size:14px;margin-top:8px}
+.ns form{display:flex;gap:10px}.ns input[type=email]{flex:1;padding:13px;border:1px solid var(--line);background:var(--panel);color:var(--ink);border-radius:4px;font-size:14px}
+.ns button{padding:13px 22px;background:var(--gold);color:#0b0b0c;border:0;border-radius:4px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;font-size:11px;cursor:pointer}
+footer{border-top:1px solid var(--line);margin-top:14px}
+footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify-content:space-between;flex-wrap:wrap;gap:16px;font-size:12px;opacity:.65}
+@media(max-width:960px){.heroc{grid-template-columns:1fr}.ns{grid-template-columns:1fr}}
+@media(max-width:720px){:root{--cols:2!important}}
+</style></head><body>
+<a class="badge" href="/portal#suggested">◀ Concept · Arte International direction</a>
+<header><div class="logo">Designer <span>Wallcoverings</span><small>Texture · Material is the message.</small></div><div style="font-size:12px;opacity:.65;text-align:right">Los Angeles · To the Trade<br>Samples $4.25 · Free shipping</div></header>
+<nav class="sec"><div class="in"><a>Wallcoverings</a><a>Fabrics</a><a>Murals</a><a>By Color</a><a>By Room</a><a>New Arrivals</a><a>Trade Program</a><a>Samples</a></div></nav>
+<div class="heroc">
+ <div class="rv"><h1 class="disp">Material is the message.</h1><p>Immersive texture — full-bleed material macros, dark gallery chrome, slow motion. A curated face for the deepest designer-wallcovering catalog online — every pattern sampled for $4.25, every order backed by thirty years of trade expertise.</p><a class="cta">Explore the collection</a></div>
+ <div class="heroimg rv"></div>
+</div>
+<div class="wrap">
+ <div class="sh"><h2>Curated This Week</h2>
+ <div class="controls">
+ <label for="sortsel">Sort</label>
+ <select id="sortsel"><option value="newest">Newest</option><option value="color">Color</option><option value="title">Title A→Z</option><option value="tier">Collection tier</option></select>
+ <label for="dens">Density</label>
+ <input type="range" id="dens" min="2" max="6" step="1" value="4">
+ </div>
+ </div>
+ <div class="grid" id="grid"><article class="gcard" data-title="Chinois Garden" data-hue="28" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(28,22%,24%),hsl(68,30%,14%))"></div>
+ <h4>Chinois Garden</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Venetian Plaster" data-hue="152" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(152,22%,24%),hsl(192,30%,14%))"></div>
+ <h4>Venetian Plaster</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Grasscloth No. 9" data-hue="208" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(208,22%,24%),hsl(248,30%,14%))"></div>
+ <h4>Grasscloth No. 9</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Deco Fan" data-hue="12" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(12,22%,24%),hsl(52,30%,14%))"></div>
+ <h4>Deco Fan</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Midnight Damask" data-hue="262" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(262,22%,24%),hsl(302,30%,14%))"></div>
+ <h4>Midnight Damask</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Coastal Weave" data-hue="88" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(88,22%,24%),hsl(128,30%,14%))"></div>
+ <h4>Coastal Weave</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Rosewood Toile" data-hue="340" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(340,22%,24%),hsl(20,30%,14%))"></div>
+ <h4>Rosewood Toile</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Celadon Silk" data-hue="190" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(190,22%,24%),hsl(230,30%,14%))"></div>
+ <h4>Celadon Silk</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Gilt Trellis" data-hue="46" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(46,22%,24%),hsl(86,30%,14%))"></div>
+ <h4>Gilt Trellis</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article><article class="gcard" data-title="Amethyst Moire" data-hue="300" data-tier="0">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(300,22%,24%),hsl(340,30%,14%))"></div>
+ <h4>Amethyst Moire</h4><div class="gmeta"><span>Wallcovering</span><span class="tier">casual</span></div>
+ </article><article class="gcard" data-title="Sage Stripe" data-hue="130" data-tier="1">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(130,22%,24%),hsl(170,30%,14%))"></div>
+ <h4>Sage Stripe</h4><div class="gmeta"><span>Fabric</span><span class="tier">signature</span></div>
+ </article><article class="gcard" data-title="Terra Fresco" data-hue="20" data-tier="2">
+ <div class="gimg" style="background:linear-gradient(135deg,hsl(20,22%,24%),hsl(60,30%,14%))"></div>
+ <h4>Terra Fresco</h4><div class="gmeta"><span>Mural</span><span class="tier">reserve</span></div>
+ </article></div>
+</div>
+<div class="ns"><div><h3 class="disp">The Designer's Brief</h3><p>New arrivals, designer picks, and pattern stories — weekly, from Los Angeles.</p></div><form onsubmit="return false"><input type="email" placeholder="you@studio.com"><button>Subscribe</button></form></div>
+<footer><div class="in"><span>Designer Wallcoverings — concept "Texture" (Arte International direction) · placeholder art for layout</span><span>One of six directions · <a href="/portal#suggested" style="color:var(--gold)">back to the brief</a></span></div></footer>
+<script>
+var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
+document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
+// Sort + density — the house rule: functional, persisted.
+var grid=document.getElementById('grid'),sel=document.getElementById('sortsel'),dens=document.getElementById('dens');
+var KS='dwconcept-texture-sort',KD='dwconcept-texture-cols';
+function apply(){var v=sel.value,cards=[].slice.call(grid.children);
+ cards.sort(function(a,b){if(v==='title')return a.dataset.title.localeCompare(b.dataset.title);
+ if(v==='color')return (+a.dataset.hue)-(+b.dataset.hue);
+ if(v==='tier')return (+a.dataset.tier)-(+b.dataset.tier);return 0;});
+ cards.forEach(function(c){grid.appendChild(c);});localStorage.setItem(KS,v);}
+sel.addEventListener('change',apply);
+dens.addEventListener('input',function(){document.documentElement.style.setProperty('--cols',dens.value);localStorage.setItem(KD,dens.value);});
+var sv=localStorage.getItem(KS),dv=localStorage.getItem(KD);
+if(sv){sel.value=sv;apply();}if(dv){dens.value=dv;document.documentElement.style.setProperty('--cols',dv);}
+</script>
+</body></html>
\ No newline at end of file
diff --git a/public/versions/warm.html b/public/versions/warm.html
deleted file mode 100644
index 56f1aee..0000000
--- a/public/versions/warm.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!doctype html><html lang="en"><head><meta charset="utf-8">
-<meta name="viewport" content="width=device-width, initial-scale=1">
-<title>Designer Wallcoverings — Warm / approachable</title>
-<style>
-:root{--bg:#fbf3e9;--ink:#3a2a1c;--accent:#d98a3d}
-*{box-sizing:border-box}body{margin:0;font-family:'Georgia',serif;background:var(--bg);color:var(--ink)}
-.bar{padding:14px 30px;display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--accent)}
-.bar b{letter-spacing:.06em}.bar span{color:var(--accent);font-size:12px;text-transform:uppercase;letter-spacing:.2em}
-.hero{padding:90px 30px;text-align:center}
-.hero .k{color:var(--accent);letter-spacing:.3em;text-transform:uppercase;font-size:12px}
-.hero h1{font-size:56px;margin:.2em 0;font-weight:700}
-.hero p{font-size:20px;max-width:620px;margin:0 auto;opacity:.8}
-.cta{display:inline-block;margin-top:26px;background:var(--accent);color:var(--bg);padding:14px 32px;text-decoration:none;text-transform:uppercase;letter-spacing:.16em;font-size:13px}
-.goals{max-width:900px;margin:40px auto;padding:0 30px;display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:18px}
-.goals div{border:1px solid var(--accent);padding:22px;font-size:17px}
-.foot{padding:40px 30px;text-align:center;opacity:.6;font-size:13px}
-</style></head><body>
-<div class="bar"><b>Designer Wallcoverings</b><span>Warm / approachable concept</span></div>
-<div class="hero">
- <div class="k">Luxury wallcoverings & designer fabrics — e-commerce + to-the-trade · Los Angeles, CA</div>
- <h1>Designer Wallcoverings</h1>
- <p>A new website concept, ready to make your first impression unforgettable.</p>
- <a class="cta" href="#">Get in touch</a>
-</div>
-<div class="goals"><div>Grow retail conversion on the flagship Shopify store</div><div>Win AI-answer citations (AEO) for wallcovering queries</div><div>Turn the 15.8k staged-draft activation drip into measurable revenue</div><div>Social-to-revenue attribution across the 6 connected channels</div></div>
-<div class="foot">Concept "warm" · generated 2026-07-26 · one of several directions to choose from.</div>
-</body></html>
\ No newline at end of file
← 5f513da collector + /api/refresh + deploy conf; live at dw.agentabra
·
back to Consulting Designerwallcoverings Com
·
seed growth buckets with live channel state + $0 competitor f141e57 →