← back to Consulting Designerwallcoverings Com
designer LOW follow-ups: 2x16px line-marker HTML legends on the two doughnuts, styled select+caret chrome on concept sort controls, thin vertical-rule accent on section headers
27e394b6fa3571fcd38f59aef1be06ccf6d8d75e · 2026-07-26 09:16:58 -0700 · Steve Abrams
Files touched
M build.mjsM public/portal.htmlM public/versions/atelier.htmlM public/versions/gallery.htmlM public/versions/heritage.htmlM public/versions/maison.htmlM public/versions/studio.htmlM public/versions/texture.html
Diff
commit 27e394b6fa3571fcd38f59aef1be06ccf6d8d75e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Jul 26 09:16:58 2026 -0700
designer LOW follow-ups: 2x16px line-marker HTML legends on the two doughnuts, styled select+caret chrome on concept sort controls, thin vertical-rule accent on section headers
---
build.mjs | 43 ++++++++++++++++++++++++++++++++++++-------
public/portal.html | 34 +++++++++++++++++++++++++++++-----
public/versions/atelier.html | 9 +++++++--
public/versions/gallery.html | 9 +++++++--
public/versions/heritage.html | 9 +++++++--
public/versions/maison.html | 9 +++++++--
public/versions/studio.html | 9 +++++++--
public/versions/texture.html | 9 +++++++--
8 files changed, 107 insertions(+), 24 deletions(-)
diff --git a/build.mjs b/build.mjs
index 7eea3e0..9399ff4 100644
--- a/build.mjs
+++ b/build.mjs
@@ -271,7 +271,10 @@ section{padding:0 clamp(24px,7vw,120px);border-top:1px solid var(--line);scroll-
.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}
+.acchead .htext{flex:1;position:relative;padding-left:26px}
+.acchead .htext:before{content:'';position:absolute;left:0;top:3px;bottom:3px;width:1px;background:linear-gradient(180deg,var(--gold),rgba(201,162,75,.14));opacity:.5;transition:opacity .28s}
+.acchead:hover .htext:before,section.open .acchead .htext:before{opacity: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}
@@ -284,6 +287,15 @@ 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:'Jost',sans-serif;font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:rgba(241,236,227,.42);margin-bottom:12px}
+.chartwrap.dgt{display:flex;flex-direction:column}
+.chartwrap.dgt .cwrow{flex:1;min-height:0;display:flex;gap:18px;align-items:stretch}
+.chartwrap.dgt .cwcanvas{position:relative;flex:1 1 auto;min-width:0;height:100%}
+.hleg{list-style:none;margin:0;padding:0;flex:0 0 auto;max-width:46%;display:flex;flex-direction:column;justify-content:center;gap:10px;overflow:auto}
+.hleg li{display:flex;align-items:center;cursor:pointer;font-size:11px;font-weight:500;letter-spacing:.02em;color:rgba(241,236,227,.62);transition:color .2s,opacity .2s;line-height:1.1}
+.hleg li:hover{color:var(--ink)}
+.hleg li.off{opacity:.38}
+.hleg .lgmk{flex:0 0 16px;width:16px;height:2px;border-radius:1px;margin-right:10px}
+.hleg .lgtx{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.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}
@@ -378,13 +390,13 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<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>
+ <div class="chartwrap dgt"><div class="ct">Live catalog by product type</div><div class="cwrow"><div class="cwcanvas"><canvas id="typeChart"></canvas></div><ul class="hleg" id="typeChart-legend"></ul></div></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">Catalog DNA — what the shelves actually hold</div>
<p class="lead2">Tag analysis across all ${fmt(FF.active_total)} actives. The palette runs <b>neutrals-first</b> — Beige + White alone account for ~${fmt(((C.color_mix || []).find(c => c.color === 'Beige')?.count || 0) + ((C.color_mix || []).find(c => c.color === 'White')?.count || 0))} products — a texture-led, trade-calibrated assortment. The merchandising read: DW owns the "quiet luxury" wall; bolder saturated stories (the DTC entrants' lane) are the underweighted shelf.</p>
<div class="duo">
<div class="chartwrap"><div class="ct">Style mix — tag-matched across actives</div><canvas id="styleChart"></canvas></div>
- <div class="chartwrap"><div class="ct">Color mix — rendered in the actual hues</div><canvas id="colorChart"></canvas></div>
+ <div class="chartwrap dgt"><div class="ct">Color mix — rendered in the actual hues</div><div class="cwrow"><div class="cwcanvas"><canvas id="colorChart"></canvas></div><ul class="hleg" id="colorChart-legend"></ul></div></div>
</div>
<div class="mosaic">${GALLERY.slice(0, 12).map(g => `<a class="mtile" title="${String(g.title).replace(/"/g, '"')} — ${g.vendor}"><img src="${g.image}&width=360" loading="lazy" alt="${String(g.title).replace(/"/g, '"')}"><span>${g.vendor}</span></a>`).join('')}</div>
<p class="lead2" style="font-size:14px;opacity:.6;margin-top:10px">Live catalog, not stock photography — one current product from each of twelve vendor lines, straight off the store's own CDN.</p>
@@ -546,14 +558,26 @@ function initCharts(){if(charted||!window.Chart)return;charted=true;
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);}
+ // Custom HTML legend for the doughnuts — thin 2x16px line markers instead of box swatches, click-to-toggle
+ var htmlLegend={id:'htmlLegend',afterUpdate:function(chart){
+ var ul=document.getElementById(chart.canvas.id+'-legend');if(!ul)return;ul.innerHTML='';
+ var items=chart.options.plugins.legend.labels.generateLabels(chart);
+ items.forEach(function(item){
+ var li=document.createElement('li');if(item.hidden)li.className='off';
+ li.onclick=function(){chart.toggleDataVisibility(item.index);chart.update();};
+ var mk=document.createElement('span');mk.className='lgmk';mk.style.background=item.fillStyle;
+ var tx=document.createElement('span');tx.className='lgtx';tx.textContent=item.text;
+ li.appendChild(mk);li.appendChild(tx);ul.appendChild(li);
+ });
+ }};
// Vertical gold gradient for area fills — scriptable so it re-derives per chart area
function goldFill(a){return function(c){var ch=c.chart,area=ch.chartArea;if(!area)return 'rgba(201,162,75,.12)';var g=ch.ctx.createLinearGradient(0,area.top,0,area.bottom);g.addColorStop(0,'rgba(201,162,75,'+a+')');g.addColorStop(1,'rgba(201,162,75,0)');return g;};}
mk('rampChart',{type:'bar',data:{labels:D.monthly.labels,datasets:[{label:'New actives / month',data:D.monthly.added,backgroundColor:function(c){var ch=c.chart,area=ch.chartArea;if(!area)return 'rgba(201,162,75,.7)';var g=ch.ctx.createLinearGradient(0,area.bottom,0,area.top);g.addColorStop(0,'rgba(201,162,75,.25)');g.addColorStop(1,'rgba(201,162,75,.9)');return g;},borderRadius:5}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
mk('needsChart',{type:'bar',data:{labels:D.needs.labels,datasets:[{label:'Actives tagged',data:D.needs.counts,backgroundColor:'rgba(212,100,122,.85)',borderRadius:5}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
mk('styleChart',{type:'bar',data:{labels:D.styles.labels,datasets:[{label:'Actives tagged',data:D.styles.counts,backgroundColor:'rgba(201,162,75,.72)',borderRadius:5}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
- mk('colorChart',{type:'doughnut',data:{labels:D.colors.labels,datasets:[{data:D.colors.counts,backgroundColor:D.colors.hex,borderColor:'#0e0c09',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'right',labels:{color:dim,boxWidth:12}}},cutout:'58%'}});
+ mk('colorChart',{type:'doughnut',plugins:[htmlLegend],data:{labels:D.colors.labels,datasets:[{data:D.colors.counts,backgroundColor:D.colors.hex,borderColor:'#0e0c09',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false},htmlLegend:{}},cutout:'58%'}});
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('typeChart',{type:'doughnut',plugins:[htmlLegend],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:{display:false},htmlLegend:{}},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(212,100,122,.9)':'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(212,100,122,.8)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
mk('srChart',{type:'bar',data:{labels:D.sampleRoll.labels,datasets:[{label:'Roll available (sample converts)',data:D.sampleRoll.converted,backgroundColor:'rgba(201,162,75,.8)',borderRadius:3},{label:'Recoverable backlog (memo, no roll)',data:D.sampleRoll.leak,backgroundColor:'rgba(212,100,122,.85)',borderRadius:3}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{stacked:true,grid:{color:line}},y:{stacked:true,grid:{display:false}}},plugins:{legend:{labels:{color:dim}}}}});
@@ -628,7 +652,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:${h.sans};font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -656,7 +685,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
diff --git a/public/portal.html b/public/portal.html
index 006e2ec..4ca4faa 100644
--- a/public/portal.html
+++ b/public/portal.html
@@ -45,7 +45,10 @@ section{padding:0 clamp(24px,7vw,120px);border-top:1px solid var(--line);scroll-
.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}
+.acchead .htext{flex:1;position:relative;padding-left:26px}
+.acchead .htext:before{content:'';position:absolute;left:0;top:3px;bottom:3px;width:1px;background:linear-gradient(180deg,var(--gold),rgba(201,162,75,.14));opacity:.5;transition:opacity .28s}
+.acchead:hover .htext:before,section.open .acchead .htext:before{opacity: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}
@@ -58,6 +61,15 @@ 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:'Jost',sans-serif;font-size:10px;letter-spacing:.24em;text-transform:uppercase;color:rgba(241,236,227,.42);margin-bottom:12px}
+.chartwrap.dgt{display:flex;flex-direction:column}
+.chartwrap.dgt .cwrow{flex:1;min-height:0;display:flex;gap:18px;align-items:stretch}
+.chartwrap.dgt .cwcanvas{position:relative;flex:1 1 auto;min-width:0;height:100%}
+.hleg{list-style:none;margin:0;padding:0;flex:0 0 auto;max-width:46%;display:flex;flex-direction:column;justify-content:center;gap:10px;overflow:auto}
+.hleg li{display:flex;align-items:center;cursor:pointer;font-size:11px;font-weight:500;letter-spacing:.02em;color:rgba(241,236,227,.62);transition:color .2s,opacity .2s;line-height:1.1}
+.hleg li:hover{color:var(--ink)}
+.hleg li.off{opacity:.38}
+.hleg .lgmk{flex:0 0 16px;width:16px;height:2px;border-radius:1px;margin-right:10px}
+.hleg .lgtx{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.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}
@@ -152,13 +164,13 @@ footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color
<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,542</b> active products, <b>16,035</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>281-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>
+ <div class="chartwrap dgt"><div class="ct">Live catalog by product type</div><div class="cwrow"><div class="cwcanvas"><canvas id="typeChart"></canvas></div><ul class="hleg" id="typeChart-legend"></ul></div></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,899</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">Catalog DNA — what the shelves actually hold</div>
<p class="lead2">Tag analysis across all 80,542 actives. The palette runs <b>neutrals-first</b> — Beige + White alone account for ~44,140 products — a texture-led, trade-calibrated assortment. The merchandising read: DW owns the "quiet luxury" wall; bolder saturated stories (the DTC entrants' lane) are the underweighted shelf.</p>
<div class="duo">
<div class="chartwrap"><div class="ct">Style mix — tag-matched across actives</div><canvas id="styleChart"></canvas></div>
- <div class="chartwrap"><div class="ct">Color mix — rendered in the actual hues</div><canvas id="colorChart"></canvas></div>
+ <div class="chartwrap dgt"><div class="ct">Color mix — rendered in the actual hues</div><div class="cwrow"><div class="cwcanvas"><canvas id="colorChart"></canvas></div><ul class="hleg" id="colorChart-legend"></ul></div></div>
</div>
<div class="mosaic"><a class="mtile" title="Willow Pearl - Cream Wallcovering | 1838 Wallcoverings — 1838 Wallcoverings"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/2008-148-04-Willow-Pearl-scaled_27cc3134-1291-4605-85ca-d870cd905b85.jpg?v=1773305872&width=360" loading="lazy" alt="Willow Pearl - Cream Wallcovering | 1838 Wallcoverings"><span>1838 Wallcoverings</span></a><a class="mtile" title="Designdrop - Colourful Wallcovering | A.s. Création — A.S. Création"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/66e3a5f29fd1fd50090f5d5fce9b4ddc.jpg?v=1773629119&width=360" loading="lazy" alt="Designdrop - Colourful Wallcovering | A.s. Création"><span>A.S. Création</span></a><a class="mtile" title="Brown on Tint | Alan Campbell — Alan Campbell"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Criss-Cross-Brown-on-Tint-AC403-16_015244-sm-thumb.jpg?v=1783597230&width=360" loading="lazy" alt="Brown on Tint | Alan Campbell"><span>Alan Campbell</span></a><a class="mtile" title="Riviera Wallcovering | Ananbo — Ananbo"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/riviera.webp?v=1761541180&width=360" loading="lazy" alt="Riviera Wallcovering | Ananbo"><span>Ananbo</span></a><a class="mtile" title="Ark - Parchment - beige Wallcovering | Andrew Martin — Andrew Martin"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AMW10001_1611_11959302-5997-4bcd-9a99-c54a9b0919e8.jpg?v=1775761440&width=360" loading="lazy" alt="Ark - Parchment - beige Wallcovering | Andrew Martin"><span>Andrew Martin</span></a><a class="mtile" title="Gibson, Navy Wallcoverings | Anna French — Anna French"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/AT78793_4d4910ee-a9f9-4534-ae47-bed6b7d9942d.jpg?v=1782985244&width=360" loading="lazy" alt="Gibson, Navy Wallcoverings | Anna French"><span>Anna French</span></a><a class="mtile" title="Anthology - Stria Stone/Amber/Plum Wallcovering | Anthology — Anthology"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/ESHE131796.jpg?v=1784735551&width=360" loading="lazy" alt="Anthology - Stria Stone/Amber/Plum Wallcovering | Anthology"><span>Anthology</span></a><a class="mtile" title="Caswell Sage Green Wallcovering | Jeffrey Stevens — Apartment Wallpaper"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/PSW1213RL.jpg?v=1740775136&width=360" loading="lazy" alt="Caswell Sage Green Wallcovering | Jeffrey Stevens"><span>Apartment Wallpaper</span></a><a class="mtile" title="Atlantic Cay - Verdant | Architectural Fabrics — Architectural Fabrics"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Skintex-SF_Aspect_Teal.jpg?v=1773218078&width=360" loading="lazy" alt="Atlantic Cay - Verdant | Architectural Fabrics"><span>Architectural Fabrics</span></a><a class="mtile" title="Agra Okra Wallcovering | Arte International — Arte International"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/Indienne_Agra_18310_Roomshot_Web_LR-medium-two-thirds.jpg?v=1775694511&width=360" loading="lazy" alt="Agra Okra Wallcovering | Arte International"><span>Arte International</span></a><a class="mtile" title="Tabula Wax Yellow Wallcovering | Artmura — Artmura"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/TABW-002.jpg?v=1781283018&width=360" loading="lazy" alt="Tabula Wax Yellow Wallcovering | Artmura"><span>Artmura</span></a><a class="mtile" title="History of Art 2 - Green Wallcovering | AS Creation — AS Creation"><img src="https://cdn.shopify.com/s/files/1/0015/4117/7456/files/792889b95340fba909e80a1654dba520_26de4b84-bada-44c9-8ff0-d634e951ba3c.jpg?v=1776187521&width=360" loading="lazy" alt="History of Art 2 - Green Wallcovering | AS Creation"><span>AS Creation</span></a></div>
<p class="lead2" style="font-size:14px;opacity:.6;margin-top:10px">Live catalog, not stock photography — one current product from each of twelve vendor lines, straight off the store's own CDN.</p>
@@ -350,14 +362,26 @@ function initCharts(){if(charted||!window.Chart)return;charted=true;
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,4260,1486,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,2899,2761,2616,2469]},"types":{"labels":["Wallcovering","Fabric","Commercial Fabric","Mural","Wallcoverings","Memo Sample"],"counts":[58298,16200,1797,1305,453,451]},"integrity":{"labels":["Missing sellable variant","Missing sample variant","Zero / null price","Missing image","Missing description"],"counts":[26742,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]},"sampleRoll":{"labels":["Phillipe Romano","Phillip Jeffries","Koroseal","China Seas","Coordonné","Hollywood Wallcoverings","Designers Guild","Osborne & Little"],"converted":[4064,8,1,0,131,2426,0,111],"leak":[3521,2461,2368,1776,1300,842,839,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]},"monthly":{"labels":["Jan","Feb","Mar","Apr","May","Jun","Jul"],"added":[223,1363,4578,3416,493,5547,10349]},"needs":{"labels":["Needs Price","Needs Image","Needs Width","Needs Description"],"counts":[19246,16531,19656,27]},"styles":{"labels":["Contemporary","Textured","Traditional","Geometric","Floral","Grasscloth","Stripe","Mural","Metallic","Damask"],"counts":[32580,29302,22704,11748,10286,9846,9153,4769,3212,1926]},"colors":{"labels":["Beige","White","Gray","Blue","Green","Brown","Black","Gold","Pink","Red"],"counts":[22079,22061,12163,8551,7749,5192,4883,4326,3456,2946],"hex":["#d9c9a8","#f2efe8","#9a9a99","#5a7fa8","#6b8f6d","#8a6a4c","#2b2b2b","#c9a24b","#d3a0a6","#a84a44"]}};
function mk(id,cfg){var el=document.getElementById(id);if(el)new Chart(el,cfg);}
+ // Custom HTML legend for the doughnuts — thin 2x16px line markers instead of box swatches, click-to-toggle
+ var htmlLegend={id:'htmlLegend',afterUpdate:function(chart){
+ var ul=document.getElementById(chart.canvas.id+'-legend');if(!ul)return;ul.innerHTML='';
+ var items=chart.options.plugins.legend.labels.generateLabels(chart);
+ items.forEach(function(item){
+ var li=document.createElement('li');if(item.hidden)li.className='off';
+ li.onclick=function(){chart.toggleDataVisibility(item.index);chart.update();};
+ var mk=document.createElement('span');mk.className='lgmk';mk.style.background=item.fillStyle;
+ var tx=document.createElement('span');tx.className='lgtx';tx.textContent=item.text;
+ li.appendChild(mk);li.appendChild(tx);ul.appendChild(li);
+ });
+ }};
// Vertical gold gradient for area fills — scriptable so it re-derives per chart area
function goldFill(a){return function(c){var ch=c.chart,area=ch.chartArea;if(!area)return 'rgba(201,162,75,.12)';var g=ch.ctx.createLinearGradient(0,area.top,0,area.bottom);g.addColorStop(0,'rgba(201,162,75,'+a+')');g.addColorStop(1,'rgba(201,162,75,0)');return g;};}
mk('rampChart',{type:'bar',data:{labels:D.monthly.labels,datasets:[{label:'New actives / month',data:D.monthly.added,backgroundColor:function(c){var ch=c.chart,area=ch.chartArea;if(!area)return 'rgba(201,162,75,.7)';var g=ch.ctx.createLinearGradient(0,area.bottom,0,area.top);g.addColorStop(0,'rgba(201,162,75,.25)');g.addColorStop(1,'rgba(201,162,75,.9)');return g;},borderRadius:5}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
mk('needsChart',{type:'bar',data:{labels:D.needs.labels,datasets:[{label:'Actives tagged',data:D.needs.counts,backgroundColor:'rgba(212,100,122,.85)',borderRadius:5}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
mk('styleChart',{type:'bar',data:{labels:D.styles.labels,datasets:[{label:'Actives tagged',data:D.styles.counts,backgroundColor:'rgba(201,162,75,.72)',borderRadius:5}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line}},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
- mk('colorChart',{type:'doughnut',data:{labels:D.colors.labels,datasets:[{data:D.colors.counts,backgroundColor:D.colors.hex,borderColor:'#0e0c09',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'right',labels:{color:dim,boxWidth:12}}},cutout:'58%'}});
+ mk('colorChart',{type:'doughnut',plugins:[htmlLegend],data:{labels:D.colors.labels,datasets:[{data:D.colors.counts,backgroundColor:D.colors.hex,borderColor:'#0e0c09',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false},htmlLegend:{}},cutout:'58%'}});
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('typeChart',{type:'doughnut',plugins:[htmlLegend],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:{display:false},htmlLegend:{}},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(212,100,122,.9)':'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(212,100,122,.8)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
mk('srChart',{type:'bar',data:{labels:D.sampleRoll.labels,datasets:[{label:'Roll available (sample converts)',data:D.sampleRoll.converted,backgroundColor:'rgba(201,162,75,.8)',borderRadius:3},{label:'Recoverable backlog (memo, no roll)',data:D.sampleRoll.leak,backgroundColor:'rgba(212,100,122,.85)',borderRadius:3}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{stacked:true,grid:{color:line}},y:{stacked:true,grid:{display:false}}},plugins:{legend:{labels:{color:dim}}}}});
diff --git a/public/versions/atelier.html b/public/versions/atelier.html
index d5f8cc6..f69e0a5 100644
--- a/public/versions/atelier.html
+++ b/public/versions/atelier.html
@@ -29,7 +29,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:'Jost',system-ui,sans-serif;font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -57,7 +62,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
diff --git a/public/versions/gallery.html b/public/versions/gallery.html
index a90f8d7..7832184 100644
--- a/public/versions/gallery.html
+++ b/public/versions/gallery.html
@@ -29,7 +29,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:'Inter',system-ui,sans-serif;font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -57,7 +62,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
diff --git a/public/versions/heritage.html b/public/versions/heritage.html
index 80c110c..158635d 100644
--- a/public/versions/heritage.html
+++ b/public/versions/heritage.html
@@ -29,7 +29,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:'Jost',system-ui,sans-serif;font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -57,7 +62,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
diff --git a/public/versions/maison.html b/public/versions/maison.html
index 5a4afce..715e6fc 100644
--- a/public/versions/maison.html
+++ b/public/versions/maison.html
@@ -29,7 +29,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:'Inter',system-ui,sans-serif;font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -57,7 +62,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
diff --git a/public/versions/studio.html b/public/versions/studio.html
index 0d2b750..adf6e65 100644
--- a/public/versions/studio.html
+++ b/public/versions/studio.html
@@ -29,7 +29,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:'Inter',system-ui,sans-serif;font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -57,7 +62,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
diff --git a/public/versions/texture.html b/public/versions/texture.html
index d9775da..b039659 100644
--- a/public/versions/texture.html
+++ b/public/versions/texture.html
@@ -29,7 +29,12 @@ nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.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 .selwrap{position:relative;display:inline-flex;align-items:center}
+.controls .selwrap:after{content:'';position:absolute;right:12px;top:50%;width:6px;height:6px;border-right:1.5px solid var(--gold);border-bottom:1.5px solid var(--gold);transform:translateY(-72%) rotate(45deg);pointer-events:none;transition:transform .2s,border-color .2s}
+.controls select{appearance:none;-webkit-appearance:none;-moz-appearance:none;background:var(--panel);color:var(--ink);border:1px solid var(--line);padding:7px 32px 7px 13px;border-radius:4px;font-family:'Jost',system-ui,sans-serif;font-size:12px;letter-spacing:.04em;cursor:pointer;transition:border-color .2s,box-shadow .2s}
+.controls select:hover{border-color:var(--gold)}
+.controls select:focus{outline:none;border-color:var(--gold);box-shadow:inset 0 0 0 1px var(--gold)}
+.controls .selwrap:hover:after{border-color:var(--gold);transform:translateY(-55%) rotate(45deg)}
.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;overflow:hidden;background:var(--panel)}.gcard:hover .gimg{transform:translateY(-4px);box-shadow:0 14px 40px rgba(0,0,0,.28)}
@@ -57,7 +62,7 @@ footer .in{max-width:1240px;margin:0 auto;padding:36px 22px;display:flex;justify
<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>
+ <span class="selwrap"><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></span>
<label for="dens">Density</label>
<input type="range" id="dens" min="2" max="6" step="1" value="4">
</div>
← 26ca9ee Unlikely Revenue: quantify sample→roll funnel (Pool 2) from
·
back to Consulting Designerwallcoverings Com
·
sample-only backlog WORK ORDERS: per-vendor remediation CSVs 4e62b5a →