← back to Model Arena

data/artifacts/258516d076e6/claude-code.html

482 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>Designer Wallcoverings — Shop by Colour</title>
<style>
  :root{
    /* ——— design tokens (ivory-gallery) ——— */
    --bg:#faf8f4;
    --surface:#ffffff;
    --ink:#1c1a17;          /* darkest ink — used for wordmark */
    --text:#1c1a17;
    --muted:#9b948a;
    --accent:#b0472e;       /* the one jewel accent */
    --accent-deep:#8a3521;
    --line:rgba(28,26,23,.14);
    --line-soft:rgba(28,26,23,.08);
    --shadow:0 8px 24px rgba(28,26,23,.10);
    --shadow-hover:0 16px 48px rgba(28,26,23,.18);
    --ease:cubic-bezier(.22,1,.36,1);
    --serif:'Cormorant Garamond','Didot','Bodoni MT','Playfair Display','EB Garamond',Georgia,serif;
    --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
    --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-6:24px; --sp-8:32px; --sp-12:48px; --sp-16:64px;
  }

  *{box-sizing:border-box;-webkit-tap-highlight-color:transparent;}
  html,body{margin:0;padding:0;}
  body{
    background:var(--bg);
    color:var(--text);
    font-family:var(--sans);
    font-size:16px;
    line-height:1.55;
    -webkit-font-smoothing:antialiased;
    overflow-x:hidden;
  }
  /* ambient slow drift */
  body::before{
    content:"";position:fixed;inset:-20%;z-index:-1;pointer-events:none;
    background:
      radial-gradient(60% 50% at 18% 8%, rgba(176,71,46,.05), transparent 60%),
      radial-gradient(55% 55% at 88% 92%, rgba(47,76,57,.05), transparent 60%);
    animation:drift 20s ease-in-out infinite alternate;
  }
  @keyframes drift{from{transform:translate3d(-2%,-1%,0) scale(1);}to{transform:translate3d(2%,1%,0) scale(1.06);}}

  /* ——— header / wordmark lockup ——— */
  header{
    position:sticky;top:0;z-index:50;
    display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);
    padding:14px clamp(16px,4vw,40px);
    background:rgba(250,248,244,.86);
    backdrop-filter:saturate(1.1) blur(10px);
    border-bottom:1px solid var(--line);
  }
  .wordmark{
    font-family:var(--serif);
    color:var(--ink);
    text-transform:uppercase;
    letter-spacing:.18em;
    font-weight:600;
    line-height:.94;
    display:flex;flex-direction:column;
  }
  .wordmark span{font-size:clamp(26px,5.4vw,40px);display:block;}
  .wordmark .m2{color:var(--ink);}
  .scoreboard{
    font-family:var(--sans);
    text-transform:uppercase;
    letter-spacing:.22em;
    font-size:11px;
    color:var(--muted);
    text-align:right;
    line-height:1.5;
    flex-shrink:0;
  }
  .scoreboard b{display:block;color:var(--accent);font-weight:600;}

  main{max-width:960px;margin:0 auto;padding:clamp(24px,5vw,64px) clamp(16px,4vw,40px) 96px;}

  .eyebrow{
    font-size:12px;letter-spacing:.28em;text-transform:uppercase;color:var(--accent);
    font-weight:600;margin:0 0 var(--sp-3);
  }
  .hero-title{
    font-family:var(--serif);font-weight:600;
    font-size:clamp(38px,8vw,66px);line-height:1.02;letter-spacing:.005em;
    margin:0 0 var(--sp-4);color:var(--ink);
  }
  .hero-title em{font-style:italic;color:var(--accent);}
  .lede{
    font-size:clamp(16px,2.4vw,21px);color:#4a463f;max-width:52ch;margin:0 auto var(--sp-8);
    text-align:center;
  }
  .hero{text-align:center;animation:fadeUp .8s var(--ease) both;}

  /* ——— colour wheel ——— */
  .wheel-wrap{
    position:relative;width:min(78vw,340px);aspect-ratio:1;margin:var(--sp-6) auto var(--sp-8);
    animation:fadeUp .8s var(--ease) .12s both;
    filter:drop-shadow(0 18px 34px rgba(28,26,23,.14));
  }
  .wheel{width:100%;height:100%;touch-action:none;cursor:grab;display:block;user-select:none;}
  .wheel:active{cursor:grabbing;}
  .wheel path.seg{transition:opacity .28s var(--ease), stroke-width .2s var(--ease);}
  .wheel .knob{transition:transform .35s var(--ease);}

  .wheel-center{
    position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
    pointer-events:none;text-align:center;
  }
  .wc-cap{font-size:10.5px;letter-spacing:.26em;text-transform:uppercase;color:var(--muted);}
  .wc-name{
    font-family:var(--serif);font-size:clamp(24px,6.6vw,34px);color:var(--ink);line-height:1;margin:4px 0 2px;
    font-weight:600;transition:opacity .3s var(--ease);
  }
  .wc-hex{font-size:11px;letter-spacing:.14em;color:var(--accent);font-weight:600;}
  .hint{text-align:center;font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);margin:-14px 0 34px;}

  /* ——— filmstrip ——— */
  .strip-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-4);margin:0 0 var(--sp-4);
    border-top:1px solid var(--line);padding-top:var(--sp-6);}
  .strip-head h2{font-family:var(--serif);font-weight:600;font-size:clamp(24px,4.4vw,32px);margin:0;color:var(--ink);}
  .strip-head .cnt{font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);}

  .filmstrip{
    display:flex;gap:var(--sp-6);overflow-x:auto;padding:4px 2px 20px;scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;scrollbar-width:none;
  }
  .filmstrip::-webkit-scrollbar{display:none;}
  .card{
    flex:0 0 auto;width:min(64vw,220px);scroll-snap-align:center;
    background:var(--surface);border:1px solid var(--line);border-radius:14px;overflow:hidden;
    box-shadow:var(--shadow);transition:transform .25s var(--ease),box-shadow .25s var(--ease);
    opacity:0;transform:translateY(24px);
  }
  .card.in{animation:fadeUp .6s var(--ease) both;}
  .card:hover{transform:translateY(-4px);box-shadow:var(--shadow-hover);}
  .swatch{aspect-ratio:4/5;background-repeat:repeat;background-position:center;}
  .meta{padding:14px 16px 16px;border-top:1px solid var(--line-soft);}
  .cname{font-family:var(--serif);font-size:21px;font-weight:600;color:var(--ink);line-height:1.1;}
  .ccode{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);margin-top:5px;}
  .ccode i{font-style:normal;color:var(--accent);}

  /* ——— share bar ——— */
  .share{
    display:flex;align-items:center;justify-content:center;gap:var(--sp-4);flex-wrap:wrap;
    margin:var(--sp-12) auto 0;padding-top:var(--sp-8);border-top:1px solid var(--line);
  }
  .share .lbl{font-size:11px;letter-spacing:.24em;text-transform:uppercase;color:var(--muted);margin-right:2px;}
  .sbtn{
    display:inline-flex;align-items:center;justify-content:center;gap:8px;
    height:44px;padding:0 18px;border-radius:999px;border:1px solid var(--line);
    background:var(--surface);color:var(--ink);cursor:pointer;
    font-family:var(--sans);font-size:11px;letter-spacing:.16em;text-transform:uppercase;font-weight:600;
    transition:transform .18s var(--ease),border-color .18s var(--ease),color .18s var(--ease),box-shadow .18s var(--ease);
  }
  .sbtn svg{width:16px;height:16px;display:block;}
  .sbtn:hover{transform:translateY(-2px);border-color:var(--accent);color:var(--accent);box-shadow:var(--shadow);}
  .sbtn.icon{width:44px;padding:0;}

  /* footer brand */
  .foot{
    text-align:center;margin-top:var(--sp-16);padding-top:var(--sp-8);border-top:1px solid var(--line-soft);
  }
  .foot .fw{font-family:var(--serif);text-transform:uppercase;letter-spacing:.2em;font-size:15px;color:var(--ink);font-weight:600;}
  .foot .fc{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);margin-top:6px;}

  /* toast overlay */
  .toast{
    position:fixed;left:50%;bottom:28px;transform:translate(-50%,20px);z-index:100;
    background:var(--ink);color:var(--bg);padding:14px 22px;border-radius:12px;
    font-size:12px;letter-spacing:.14em;text-transform:uppercase;font-weight:600;
    box-shadow:0 12px 40px rgba(28,26,23,.3);opacity:0;pointer-events:none;
    transition:opacity .3s var(--ease),transform .3s var(--ease);
  }
  .toast.show{opacity:1;transform:translate(-50%,0);}
  .toast b{color:var(--accent);}

  @keyframes fadeUp{from{opacity:0;transform:translateY(28px);}to{opacity:1;transform:none;}}
  @media (prefers-reduced-motion:reduce){*{animation-duration:.001ms!important;}}
</style>
</head>
<body>
  <header>
    <div class="wordmark" aria-label="Designer Wallcoverings">
      <span class="m1">Designer</span>
      <span class="m2">Wallcoverings</span>
    </div>
    <div class="scoreboard">
      Colour Atelier
      <b>Shop by Colour</b>
    </div>
  </header>

  <main>
    <section class="hero">
      <p class="eyebrow">The Palette Edit</p>
      <h1 class="hero-title">Shop by <em>Colour</em></h1>
      <p class="lede">Turn the wheel to a hue you love. Each tone unfurls a curated filmstrip of four wallcoverings — drawn in that colour family, named the way our studio names them.</p>
    </section>

    <div class="wheel-wrap">
      <svg class="wheel" id="wheel" viewBox="0 0 300 300" role="slider" aria-label="Colour selector" tabindex="0" aria-valuemin="0" aria-valuemax="11" aria-valuenow="0">
        <g id="segs"></g>
        <circle cx="150" cy="150" r="60" fill="var(--surface)"></circle>
        <circle cx="150" cy="150" r="60" fill="none" stroke="var(--line)" stroke-width="1"></circle>
        <g id="knob" class="knob">
          <circle cx="150" cy="16" r="11" fill="var(--surface)" stroke="var(--accent)" stroke-width="2"></circle>
          <circle cx="150" cy="16" r="4" fill="var(--accent)"></circle>
        </g>
      </svg>
      <div class="wheel-center">
        <div class="wc-cap">Colour Family</div>
        <div class="wc-name" id="wcName">Rouge</div>
        <div class="wc-hex" id="wcHex">#B0472E</div>
      </div>
    </div>
    <p class="hint">Drag the wheel · tap a hue</p>

    <div class="strip-head">
      <h2 id="stripTitle">In the Rouge family</h2>
      <span class="cnt">Four Patterns</span>
    </div>
    <div class="filmstrip" id="strip" aria-live="polite"></div>

    <div class="share">
      <span class="lbl">Share this palette</span>
      <button class="sbtn" id="copyBtn" type="button" aria-label="Copy link">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7 0l2-2a5 5 0 0 0-7-7l-1 1"/><path d="M14 11a5 5 0 0 0-7 0l-2 2a5 5 0 0 0 7 7l1-1"/></svg>
        Copy Link
      </button>
      <button class="sbtn icon" data-net="Pinterest" type="button" aria-label="Share on Pinterest">
        <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.5 2 4 5.9 4 9.1c0 1.9.7 3.6 2.3 4.2.3.1.5 0 .5-.3l.2-.9c.1-.3 0-.4-.2-.6-.4-.5-.7-1.2-.7-2.1 0-2.7 2-5.1 5.3-5.1 2.9 0 4.5 1.8 4.5 4.1 0 3.1-1.4 5.7-3.4 5.7-1.1 0-2-.9-1.7-2.1.3-1.3.9-2.7.9-3.7 0-.9-.5-1.6-1.4-1.6-1.1 0-2 1.2-2 2.7 0 1 .3 1.6.3 1.6l-1.3 5.6c-.4 1.7-.1 3.7 0 3.9 0 .1.2.2.3.1.1-.1 1.6-2 2.1-3.8l.8-3c.4.8 1.6 1.4 2.8 1.4 3.6 0 6.1-3.3 6.1-7.7C21 5.3 17.9 2 12 2z"/></svg>
      </button>
      <button class="sbtn icon" data-net="Facebook" type="button" aria-label="Share on Facebook">
        <svg viewBox="0 0 24 24" fill="currentColor"><path d="M14 9h3l.4-3H14V4.3c0-.9.3-1.5 1.5-1.5H17V.1C16.7.1 15.6 0 14.4 0 11.9 0 10.2 1.5 10.2 4v2H7v3h3.2v9H14V9z"/></svg>
      </button>
      <button class="sbtn icon" data-net="Instagram" type="button" aria-label="Share on Instagram">
        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.2" cy="6.8" r="1" fill="currentColor" stroke="none"/></svg>
      </button>
    </div>

    <div class="foot">
      <div class="fw">Designer Wallcoverings</div>
      <div class="fc">Est. Interiors · Handcrafted Palettes</div>
    </div>
  </main>

  <div class="toast" id="toast">Copied</div>

<script>
(function(){
  "use strict";

  /* ——— colour families ——— */
  var FAMS = [
    {family:'Rouge',      h:2,   names:['Cinnabar','Oxblood','Rosewood','Claret']},
    {family:'Terracotta', h:18,  names:['Terracotta','Sienna','Persimmon','Umber']},
    {family:'Ochre',      h:40,  names:['Ochre','Saffron','Honey','Antique Gold']},
    {family:'Citrine',    h:66,  names:['Citrine','Chartreuse','Absinthe','Lichen']},
    {family:'Sage',       h:98,  names:['Sage','Celadon','Verdigris','Moss']},
    {family:'Forest',     h:140, names:['Fern','Eucalyptus','Juniper','Pine']},
    {family:'Teal',       h:176, names:['Teal','Viridian','Peacock','Deep Sea']},
    {family:'Cerulean',   h:202, names:['Cerulean','Aquamarine','Delft','Prussian']},
    {family:'Indigo',     h:226, names:['Indigo','Sapphire','Cobalt','Midnight']},
    {family:'Violet',     h:262, names:['Violet','Amethyst','Wisteria','Iris']},
    {family:'Aubergine',  h:292, names:['Aubergine','Plum','Mulberry','Damson']},
    {family:'Blush',      h:330, names:['Blush','Rose','Fuchsia','Mauve']}
  ];
  /* per-card [saturation, lightness] — 4 distinct shades of the family */
  var SHADES = [[56,45],[50,32],[44,60],[62,73]];
  var N = FAMS.length;
  var CX=150, CY=150, R=140, r=60;

  /* ——— helpers ——— */
  function hslHex(h,s,l){
    s/=100; l/=100;
    var k=function(n){return (n+h/30)%12;};
    var a=s*Math.min(l,1-l);
    var f=function(n){var c=l-a*Math.max(-1,Math.min(k(n)-3,Math.min(9-k(n),1)));return Math.round(255*c);};
    var t=function(v){return ('0'+v.toString(16)).slice(-2);};
    return ('#'+t(f(0))+t(f(8))+t(f(4))).toUpperCase();
  }
  function hsl(h,s,l){return 'hsl('+h+','+s+'%,'+l+'%)';}
  function svgURL(s){return 'url("data:image/svg+xml,'+encodeURIComponent(s)+'")';}

  /* ——— four visually-distinct CSS/SVG motifs ——— */
  function motifDamask(g,c,c2){
    var s="<svg xmlns='http://www.w3.org/2000/svg' width='72' height='96' viewBox='0 0 72 96'>"
      +"<rect width='72' height='96' fill='"+g+"'/>"
      +"<g fill='"+c+"'>"
      +"<path d='M36 6 C52 22 52 40 36 52 C20 40 20 22 36 6 Z'/>"
      +"<path d='M36 90 C52 74 52 56 36 44 C20 56 20 74 36 90 Z'/>"
      +"<path d='M0 48 C10 40 10 56 0 48 Z'/><path d='M72 48 C62 40 62 56 72 48 Z'/>"
      +"</g>"
      +"<circle cx='36' cy='29' r='5.5' fill='"+g+"'/><circle cx='36' cy='67' r='5.5' fill='"+g+"'/>"
      +"<g fill='"+c2+"'><circle cx='36' cy='29' r='2.4'/><circle cx='36' cy='67' r='2.4'/>"
      +"<circle cx='12' cy='48' r='3'/><circle cx='60' cy='48' r='3'/></g>"
      +"</svg>";
    return {img:svgURL(s), size:'72px 96px'};
  }
  function motifStripe(g,c,c2){
    var s="<svg xmlns='http://www.w3.org/2000/svg' width='48' height='24' viewBox='0 0 48 24'>"
      +"<rect width='48' height='24' fill='"+g+"'/>"
      +"<rect x='5' width='11' height='24' fill='"+c+"'/>"
      +"<rect x='24' width='3' height='24' fill='"+c2+"'/>"
      +"<rect x='31' width='3' height='24' fill='"+c2+"'/>"
      +"</svg>";
    return {img:svgURL(s), size:'44px 22px'};
  }
  function motifTrellis(g,c,c2){
    var s="<svg xmlns='http://www.w3.org/2000/svg' width='56' height='56' viewBox='0 0 56 56'>"
      +"<rect width='56' height='56' fill='"+g+"'/>"
      +"<g stroke='"+c+"' stroke-width='2.2' fill='none' stroke-linecap='round'>"
      +"<path d='M0 28 L28 0 L56 28 L28 56 Z'/>"
      +"<path d='M28 0 L28 -0 M0 28 L56 28 M28 56 L28 56'/>"
      +"</g>"
      +"<circle cx='28' cy='28' r='4' fill='"+c2+"'/>"
      +"<circle cx='0' cy='0' r='2.6' fill='"+c2+"'/><circle cx='56' cy='0' r='2.6' fill='"+c2+"'/>"
      +"<circle cx='0' cy='56' r='2.6' fill='"+c2+"'/><circle cx='56' cy='56' r='2.6' fill='"+c2+"'/>"
      +"</svg>";
    return {img:svgURL(s), size:'52px 52px'};
  }
  function motifFloral(g,c,c2){
    function flower(cx,cy,rr){
      return "<g fill='"+c+"'>"
        +"<circle cx='"+cx+"' cy='"+(cy-rr)+"' r='"+(rr*0.72)+"'/>"
        +"<circle cx='"+(cx+rr)+"' cy='"+cy+"' r='"+(rr*0.72)+"'/>"
        +"<circle cx='"+cx+"' cy='"+(cy+rr)+"' r='"+(rr*0.72)+"'/>"
        +"<circle cx='"+(cx-rr)+"' cy='"+cy+"' r='"+(rr*0.72)+"'/>"
        +"</g><circle cx='"+cx+"' cy='"+cy+"' r='"+(rr*0.5)+"' fill='"+c2+"'/>";
    }
    var s="<svg xmlns='http://www.w3.org/2000/svg' width='64' height='64' viewBox='0 0 64 64'>"
      +"<rect width='64' height='64' fill='"+g+"'/>"
      +flower(16,16,7)+flower(48,48,7)+flower(48,16,5)+flower(16,48,5)
      +"</svg>";
    return {img:svgURL(s), size:'60px 60px'};
  }
  var MOTIFS=[motifDamask,motifStripe,motifTrellis,motifFloral];

  /* ——— build wheel wedges ——— */
  var SVGNS='http://www.w3.org/2000/svg';
  var segG=document.getElementById('segs');
  function pt(rad,deg){var t=deg*Math.PI/180;return [CX+rad*Math.cos(t), CY+rad*Math.sin(t)];}
  function segAngle(i){return i*(360/N)-90;}
  for(var i=0;i<N;i++){
    var deg=segAngle(i), half=(360/N)/2-0.6;
    var a=deg-half, b=deg+half;
    var o1=pt(R,a), o2=pt(R,b), in2=pt(r,b), in1=pt(r,a);
    var d="M"+o1[0]+" "+o1[1]+" A"+R+" "+R+" 0 0 1 "+o2[0]+" "+o2[1]
      +" L"+in2[0]+" "+in2[1]+" A"+r+" "+r+" 0 0 0 "+in1[0]+" "+in1[1]+" Z";
    var p=document.createElementNS(SVGNS,'path');
    p.setAttribute('d',d);
    p.setAttribute('class','seg');
    p.setAttribute('fill', hsl(FAMS[i].h,58,46));
    p.setAttribute('stroke','var(--bg)');
    p.setAttribute('stroke-width','2');
    p.setAttribute('data-i',i);
    segG.appendChild(p);
  }

  /* ——— render selection ——— */
  var wheel=document.getElementById('wheel');
  var knob=document.getElementById('knob');
  var segs=segG.querySelectorAll('.seg');
  var wcName=document.getElementById('wcName');
  var wcHex=document.getElementById('wcHex');
  var stripTitle=document.getElementById('stripTitle');
  var strip=document.getElementById('strip');
  var current=-1;

  function select(i, silent){
    i=((i%N)+N)%N;
    if(i===current) return;
    current=i;
    var fam=FAMS[i];
    for(var k=0;k<segs.length;k++){
      var on=(k===i);
      segs[k].style.opacity = on?'1':'.5';
      segs[k].setAttribute('stroke', on?'var(--accent)':'var(--bg)');
      segs[k].setAttribute('stroke-width', on?'3':'2');
    }
    knob.style.transform='rotate('+(i*(360/N))+'deg)';
    wcName.style.opacity=0;
    setTimeout(function(){
      wcName.textContent=fam.family;
      wcHex.textContent=hslHex(fam.h,58,45);
      wcName.style.opacity=1;
    }, silent?0:130);
    stripTitle.textContent='In the '+fam.family+' family';
    wheel.setAttribute('aria-valuenow', i);

    /* filmstrip */
    strip.innerHTML='';
    for(var c=0;c<4;c++){
      var sh=SHADES[c];
      var main=hsl(fam.h, sh[0], sh[1]);
      var dark=hsl(fam.h, Math.min(sh[0]+10,90), Math.max(sh[1]-16,12));
      var ground=hsl(fam.h, 22, 95);
      var m=MOTIFS[c](ground, main, dark);
      var card=document.createElement('article');
      card.className='card';
      card.style.animationDelay=(c*0.09)+'s';
      card.innerHTML=
        "<div class='swatch' style=\"background-color:"+ground+";background-image:"+m.img+";background-size:"+m.size+"\"></div>"
        +"<div class='meta'><div class='cname'>"+fam.names[c]+"</div>"
        +"<div class='ccode'>"+fam.family+" · <i>"+hslHex(fam.h,sh[0],sh[1])+"</i></div></div>";
      strip.appendChild(card);
      void card.offsetWidth;
      card.classList.add('in');
    }
  }

  /* ——— pointer interaction ——— */
  function angleToIndex(clientX,clientY){
    var rect=wheel.getBoundingClientRect();
    var x=(clientX-rect.left)/rect.width*300 - CX;
    var y=(clientY-rect.top)/rect.height*300 - CY;
    var dist=Math.sqrt(x*x+y*y);
    if(dist < 30) return null; /* ignore dead center */
    var deg=Math.atan2(y,x)*180/Math.PI;
    return Math.round((deg+90)/(360/N));
  }
  var dragging=false;
  function onDown(e){
    dragging=true;
    try{wheel.setPointerCapture(e.pointerId);}catch(_){}
    var idx=angleToIndex(e.clientX,e.clientY);
    if(idx!==null) select(idx);
    e.preventDefault();
  }
  function onMove(e){
    if(!dragging) return;
    var idx=angleToIndex(e.clientX,e.clientY);
    if(idx!==null) select(idx);
    e.preventDefault();
  }
  function onUp(){dragging=false;}
  wheel.addEventListener('pointerdown',onDown);
  wheel.addEventListener('pointermove',onMove);
  window.addEventListener('pointerup',onUp);
  wheel.addEventListener('pointercancel',onUp);
  wheel.addEventListener('keydown',function(e){
    if(e.key==='ArrowRight'||e.key==='ArrowDown'){select(current+1);e.preventDefault();}
    else if(e.key==='ArrowLeft'||e.key==='ArrowUp'){select(current-1);e.preventDefault();}
  });

  /* ——— share bar ——— */
  var toast=document.getElementById('toast');
  var toastTimer;
  function showToast(html){
    toast.innerHTML=html;
    toast.classList.add('show');
    clearTimeout(toastTimer);
    toastTimer=setTimeout(function(){toast.classList.remove('show');},2200);
  }
  document.getElementById('copyBtn').addEventListener('click',function(){
    var link=(location.href||'designerwallcoverings.com')+'#'+FAMS[current].family.toLowerCase();
    if(navigator.clipboard&&navigator.clipboard.writeText){
      navigator.clipboard.writeText(link).then(
        function(){showToast('Link <b>copied</b> — '+FAMS[current].family);},
        function(){showToast('Share the <b>'+FAMS[current].family+'</b> palette');}
      );
    } else {
      showToast('Share the <b>'+FAMS[current].family+'</b> palette');
    }
  });
  var netBtns=document.querySelectorAll('.sbtn[data-net]');
  for(var b=0;b<netBtns.length;b++){
    netBtns[b].addEventListener('click',function(){
      showToast('Shared to <b>'+this.getAttribute('data-net')+'</b> — '+FAMS[current].family);
    });
  }

  /* init */
  select(0,true);
})();
</script>
</body>
</html>