← back to Model Arena

data/artifacts/104018fe5adc/claude-code.html

524 lines

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Designer Wallcoverings — This or That</title>
<style>
  /* ============ DESIGN TOKENS ============ */
  :root{
    --bg:#f4f1ea;              /* warm ivory ground */
    --surface:#ffffff;
    --ink:#1c1a17;            /* darkest near-black ink */
    --ink-soft:#3a352d;
    --muted:#9b948a;
    --accent:#a9884f;          /* single metallic accent — antique brass */
    --accent-deep:#8a6c38;
    --line:rgba(28,26,23,.12);
    --line-strong:rgba(28,26,23,.22);
    --shadow:0 10px 40px rgba(28,26,23,.14);
    --shadow-soft:0 4px 18px rgba(28,26,23,.08);
    --story-bg:#161310;        /* espresso story canvas */
    --ease:cubic-bezier(.22,1,.36,1);

    /* editable swatch palettes */
    --l-ground:#33403a;        /* Damask ground — deep sage */
    --l-motif:#c8a86a;         /* Damask motif — brass */
    --r-ground:#2b3550;        /* Geometric ground — deep indigo */
    --r-motif:#e6ddcf;         /* Geometric motif — cream */

    --serif:'Cormorant Garamond','Playfair Display','EB Garamond',Georgia,'Times New Roman',serif;
    --sans:-apple-system,'Segoe UI','Helvetica Neue',Helvetica,Arial,sans-serif;
  }

  *{box-sizing:border-box;margin:0;padding:0}
  html,body{height:100%}
  body{
    background:
      radial-gradient(120% 90% at 50% -10%, #faf8f3 0%, var(--bg) 55%, #ece7dc 100%);
    color:var(--ink);
    font-family:var(--sans);
    -webkit-font-smoothing:antialiased;
    min-height:100vh;
    padding-bottom:56px;
  }

  /* ============ HEADER / WORDMARK LOCKUP ============ */
  header.topbar{
    position:sticky;top:0;z-index:50;
    display:flex;align-items:center;justify-content:space-between;
    gap:24px;
    padding:20px 32px;
    background:rgba(244,241,234,.82);
    backdrop-filter:saturate(120%) blur(10px);
    border-bottom:1px solid var(--line);
  }
  .wordmark{
    font-family:var(--serif);
    color:var(--ink);              /* darkest ink — never a surface token */
    font-weight:600;
    font-size:44px;                /* >=40px */
    line-height:.92;
    letter-spacing:.18em;
    text-transform:uppercase;
    max-width:280px;                /* compact upper-left lockup, wraps to 2 lines */
    text-indent:.18em;
  }
  .topbar .kicker{
    font-family:var(--sans);
    font-size:12px;letter-spacing:.28em;text-transform:uppercase;
    color:var(--muted);
    text-align:right;
    line-height:1.7;
  }
  .topbar .kicker b{display:block;color:var(--accent-deep);font-weight:600;letter-spacing:.22em}

  /* ============ LAYOUT ============ */
  main{
    max-width:520px;margin:0 auto;padding:40px 24px 0;
    display:flex;flex-direction:column;align-items:center;gap:34px;
    animation:fadeUp .8s var(--ease) both;
  }
  @keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}

  /* ============ PHONE FRAME 9:16 ============ */
  .phone{
    position:relative;
    width:100%;max-width:340px;
    aspect-ratio:9/16;
    background:#0c0a08;
    border-radius:42px;
    padding:12px;
    box-shadow:var(--shadow), 0 0 0 1px rgba(28,26,23,.4), inset 0 0 0 2px rgba(255,255,255,.05);
  }
  .phone::before{ /* notch */
    content:"";position:absolute;top:18px;left:50%;transform:translateX(-50%);
    width:108px;height:26px;background:#0c0a08;border-radius:0 0 16px 16px;z-index:6;
  }
  .story{
    position:relative;height:100%;width:100%;
    border-radius:32px;overflow:hidden;
    background:var(--story-bg);
    display:flex;flex-direction:column;
    color:#f5f2ea;
  }

  /* ---- Story chrome ---- */
  .progress{position:absolute;top:12px;left:12px;right:12px;display:flex;gap:5px;z-index:5}
  .progress span{flex:1;height:2.5px;border-radius:2px;background:rgba(255,255,255,.28);overflow:hidden}
  .progress span i{display:block;height:100%;width:0;background:#fff;border-radius:2px}
  .progress span:first-child i{width:64%;animation:load 6s linear forwards}
  @keyframes load{to{width:100%}}

  .story-head{
    position:absolute;top:24px;left:14px;right:14px;z-index:5;
    display:flex;align-items:center;gap:9px;
  }
  .avatar{
    width:32px;height:32px;border-radius:50%;flex:none;
    padding:2px;background:conic-gradient(from 210deg,var(--accent),#e7d3a6,var(--accent-deep),var(--accent));
  }
  .avatar div{
    width:100%;height:100%;border-radius:50%;
    background:var(--story-bg);
    display:flex;align-items:center;justify-content:center;
    font-family:var(--serif);font-size:15px;color:var(--accent);font-weight:600;
  }
  .handle{font-size:12.5px;font-weight:600;letter-spacing:.02em}
  .handle b{font-weight:600}
  .handle span{color:rgba(245,242,234,.6);font-weight:400;margin-left:6px}
  .story-head .x{margin-left:auto;font-size:20px;color:rgba(245,242,234,.85);line-height:1;cursor:pointer}

  /* ---- Story body ---- */
  .story-body{
    flex:1;display:flex;flex-direction:column;
    padding:70px 18px 16px;
  }
  .poll-eyebrow{
    font-size:11px;letter-spacing:.32em;text-transform:uppercase;
    color:var(--accent);text-align:center;margin-bottom:6px;font-weight:600;
  }
  .poll-title{
    font-family:var(--serif);
    font-size:34px;                /* heading >=24px */
    line-height:1;text-align:center;font-weight:600;font-style:italic;
    letter-spacing:.01em;
    text-shadow:0 2px 18px rgba(0,0,0,.4);
  }
  .poll-sub{
    text-align:center;color:rgba(245,242,234,.62);
    font-size:12px;letter-spacing:.06em;margin-top:8px;
  }

  /* ---- Arena ---- */
  .arena{
    position:relative;flex:1;margin-top:16px;
    display:flex;gap:2px;border-radius:20px;overflow:hidden;
    box-shadow:0 8px 30px rgba(0,0,0,.45), inset 0 0 0 1px rgba(255,255,255,.06);
  }
  .swatch{
    position:relative;flex:1;overflow:hidden;cursor:pointer;
    display:flex;flex-direction:column;justify-content:flex-end;
    border:none;background:transparent;
    transition:flex .55s var(--ease);
    isolation:isolate;
  }
  .swatch .ground{position:absolute;inset:0;z-index:0;transition:background-color .3s ease}
  .swatch.left  .ground{background-color:var(--l-ground)}
  .swatch.right .ground{background-color:var(--r-ground)}
  .swatch .tex{position:absolute;inset:0;z-index:1;opacity:.9;transition:transform .6s var(--ease)}
  .swatch:hover .tex{transform:scale(1.06)}
  .swatch .veil{position:absolute;inset:0;z-index:2;
    background:linear-gradient(to top,rgba(10,8,6,.72) 0%,rgba(10,8,6,.15) 45%,rgba(10,8,6,0) 70%);}

  /* rising vote fill */
  .swatch .fill{
    position:absolute;left:0;right:0;bottom:0;height:0;z-index:3;
    background:linear-gradient(to top,rgba(169,136,79,.55),rgba(169,136,79,.14));
    border-top:1.5px solid rgba(231,211,166,.9);
    transition:height .8s var(--ease);
  }
  .swatch .name{
    position:relative;z-index:4;
    font-family:var(--serif);font-size:19px;font-weight:600;
    text-align:center;padding:0 8px 6px;line-height:1.1;
    text-shadow:0 2px 10px rgba(0,0,0,.6);
    outline:none;border-radius:6px;
  }
  .swatch .name:focus{box-shadow:0 0 0 1px rgba(231,211,166,.7)}
  .swatch .pct{
    position:relative;z-index:4;text-align:center;
    font-family:var(--serif);font-size:30px;font-weight:600;
    color:#fff;letter-spacing:.02em;
    height:0;opacity:0;overflow:hidden;
    transition:opacity .5s ease .2s, height .5s var(--ease);
    text-shadow:0 2px 12px rgba(0,0,0,.7);
    padding-bottom:14px;
  }
  .voted .swatch .pct{height:40px;opacity:1}

  /* VS badge */
  .vs{
    position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:6;
    width:46px;height:46px;border-radius:50%;
    background:var(--surface);color:var(--ink);
    display:flex;align-items:center;justify-content:center;
    font-family:var(--serif);font-style:italic;font-weight:600;font-size:19px;
    box-shadow:0 6px 20px rgba(0,0,0,.5), 0 0 0 4px rgba(22,19,16,.9), 0 0 0 5px var(--accent);
  }

  /* winner wax seal */
  .seal{
    position:absolute;top:14px;left:50%;transform:translateX(-50%) scale(.4) rotate(-12deg);
    z-index:7;width:74px;height:74px;border-radius:50%;
    background:radial-gradient(circle at 35% 30%,#c8a86a,var(--accent) 55%,var(--accent-deep));
    box-shadow:0 6px 18px rgba(0,0,0,.5), inset 0 0 0 2px rgba(255,255,255,.35), inset 0 0 0 6px rgba(138,108,56,.5);
    display:flex;flex-direction:column;align-items:center;justify-content:center;
    color:#26200f;opacity:0;pointer-events:none;
    transition:opacity .45s ease, transform .55s var(--ease);
  }
  .seal small{font-size:8px;letter-spacing:.22em;text-transform:uppercase;font-weight:700}
  .seal b{font-family:var(--serif);font-size:13px;letter-spacing:.14em;font-weight:700;line-height:1;margin-top:1px}
  .seal.show{opacity:1;transform:translateX(-50%) scale(1) rotate(-12deg)}

  /* ---- Results split bar ---- */
  .results{margin-top:14px;height:0;opacity:0;overflow:hidden;transition:height .5s var(--ease),opacity .4s ease}
  .voted .results{height:44px;opacity:1}
  .bar{height:8px;border-radius:5px;overflow:hidden;display:flex;background:rgba(255,255,255,.12)}
  .bar .bl{background:linear-gradient(90deg,var(--accent-deep),var(--accent));transition:width .8s var(--ease)}
  .bar .br{background:rgba(245,242,234,.55);transition:width .8s var(--ease)}
  .rlabels{display:flex;justify-content:space-between;margin-top:8px;
    font-size:11px;letter-spacing:.08em;color:rgba(245,242,234,.75)}
  .rlabels b{color:var(--accent);font-weight:600}

  /* ---- Story footer ---- */
  .story-foot{padding:12px 16px 18px;display:flex;align-items:center;gap:12px}
  .reply{
    flex:1;border:1px solid rgba(245,242,234,.4);border-radius:22px;
    padding:9px 16px;font-size:12px;color:rgba(245,242,234,.7);letter-spacing:.04em;
  }
  .story-foot svg{width:22px;height:22px;stroke:rgba(245,242,234,.9);fill:none;stroke-width:1.6}
  .tap-hint{
    text-align:center;font-size:11px;letter-spacing:.14em;text-transform:uppercase;
    color:var(--accent);padding:0 16px 6px;transition:opacity .3s ease;
  }
  .voted .tap-hint{color:rgba(245,242,234,.5)}
  .votecount{font-weight:600;color:#fff}

  /* ============ CONTROLS (ivory) ============ */
  .controls{
    width:100%;max-width:340px;
    background:var(--surface);
    border:1px solid var(--line);border-radius:16px;
    box-shadow:var(--shadow-soft);
    padding:22px 22px 24px;
  }
  .controls h2{
    font-family:var(--serif);font-size:24px;font-weight:600;color:var(--ink);
    letter-spacing:.01em;margin-bottom:3px;
  }
  .controls .lead{font-size:12.5px;color:var(--muted);letter-spacing:.02em;line-height:1.5;margin-bottom:18px}
  .field-label{
    font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);
    font-weight:600;margin:16px 0 9px;
  }
  .pickrow{display:grid;grid-template-columns:1fr 1fr;gap:12px}
  .pick{display:flex;flex-direction:column;gap:6px}
  .pick span{font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-soft)}
  .pick .swatchrow{display:flex;gap:8px}
  .pick label{
    display:flex;align-items:center;gap:6px;font-size:10px;color:var(--muted);
    letter-spacing:.06em;cursor:pointer;
  }
  input[type=color]{
    -webkit-appearance:none;appearance:none;
    width:26px;height:26px;border:1px solid var(--line-strong);border-radius:50%;
    padding:0;background:none;cursor:pointer;
  }
  input[type=color]::-webkit-color-swatch-wrapper{padding:0}
  input[type=color]::-webkit-color-swatch{border:none;border-radius:50%}
  input[type=color]::-moz-color-swatch{border:none;border-radius:50%}

  .btnrow{display:flex;gap:10px;margin-top:22px}
  button.act{
    flex:1;font-family:var(--sans);
    font-size:11px;letter-spacing:.18em;text-transform:uppercase;font-weight:600;
    padding:13px 14px;border-radius:10px;cursor:pointer;border:1px solid var(--line-strong);
    background:var(--surface);color:var(--ink);
    transition:all .18s ease;
  }
  button.act:hover{border-color:var(--accent);color:var(--accent-deep)}
  button.act.primary{background:var(--ink);color:var(--bg);border-color:var(--ink)}
  button.act.primary:hover{background:var(--accent-deep);border-color:var(--accent-deep);color:#fff}

  .foot-note{
    max-width:340px;text-align:center;font-size:11px;letter-spacing:.12em;
    text-transform:uppercase;color:var(--muted);margin-top:6px;
  }
</style>
</head>
<body>

<header class="topbar">
  <div class="wordmark">Designer Wallcoverings</div>
  <div class="kicker"><b>Atelier</b>Story Poll · No.14</div>
</header>

<main>
  <!-- PHONE -->
  <div class="phone">
    <div class="story" id="story">
      <div class="progress"><span><i></i></span><span><i></i></span><span><i></i></span><span><i></i></span></div>

      <div class="story-head">
        <div class="avatar"><div>D</div></div>
        <div class="handle"><b>designerwallcoverings</b><span>2h</span></div>
        <div class="x">&times;</div>
      </div>

      <div class="story-body">
        <div class="poll-eyebrow">This&nbsp;·&nbsp;or&nbsp;·&nbsp;That</div>
        <div class="poll-title">Which wall<br>speaks to you?</div>
        <div class="poll-sub">Tap a side — the room will tell.</div>

        <div class="arena" id="arena">
          <!-- LEFT -->
          <div class="swatch left" data-side="left">
            <div class="ground"></div>
            <svg class="tex" viewBox="0 0 90 120" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
              <defs>
                <pattern id="pat-damask" width="90" height="120" patternUnits="userSpaceOnUse">
                  <g fill="var(--l-motif)" fill-opacity="0.94">
                    <path d="M45 6 C55 18 55 30 45 40 C35 30 35 18 45 6 Z"/>
                    <path d="M45 15 C61 10 71 21 66 33 C58 29 50 27 45 31 Z"/>
                    <path d="M45 15 C29 10 19 21 24 33 C32 29 40 27 45 31 Z"/>
                    <path d="M45 44 C67 56 69 85 45 101 C21 85 23 56 45 44 Z"/>
                    <path d="M45 57 C58 67 58 85 45 93 C32 85 32 67 45 57 Z" fill="var(--l-ground)"/>
                    <path d="M45 104 C55 112 58 119 52 120 L38 120 C32 119 35 112 45 104 Z"/>
                    <circle cx="8" cy="60" r="3.2"/><circle cx="82" cy="60" r="3.2"/>
                    <circle cx="0" cy="0" r="3"/><circle cx="90" cy="0" r="3"/>
                    <circle cx="0" cy="120" r="3"/><circle cx="90" cy="120" r="3"/>
                  </g>
                </pattern>
              </defs>
              <rect width="90" height="120" fill="url(#pat-damask)"/>
            </svg>
            <div class="veil"></div>
            <div class="fill"></div>
            <div class="seal"><small>Winner</small><b>WINNER</b></div>
            <div class="name" contenteditable="true" spellcheck="false" data-name="left">Damask</div>
            <div class="pct" data-pct="left">50%</div>
          </div>

          <!-- RIGHT -->
          <div class="swatch right" data-side="right">
            <div class="ground"></div>
            <svg class="tex" viewBox="0 0 108 120" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
              <defs>
                <pattern id="pat-geo" width="54" height="54" patternUnits="userSpaceOnUse">
                  <g stroke="var(--r-motif)" stroke-width="1.6" fill="none">
                    <polygon points="27,3 51,27 27,51 3,27"/>
                    <polygon points="27,14 40,27 27,40 14,27"/>
                  </g>
                  <circle cx="27" cy="27" r="2.4" fill="var(--r-motif)"/>
                  <circle cx="0" cy="0" r="2.4" fill="var(--r-motif)"/>
                  <circle cx="54" cy="0" r="2.4" fill="var(--r-motif)"/>
                  <circle cx="0" cy="54" r="2.4" fill="var(--r-motif)"/>
                  <circle cx="54" cy="54" r="2.4" fill="var(--r-motif)"/>
                </pattern>
              </defs>
              <rect width="108" height="120" fill="url(#pat-geo)"/>
            </svg>
            <div class="veil"></div>
            <div class="fill"></div>
            <div class="seal"><small>Winner</small><b>WINNER</b></div>
            <div class="name" contenteditable="true" spellcheck="false" data-name="right">Geometric</div>
            <div class="pct" data-pct="right">50%</div>
          </div>

          <div class="vs">vs</div>
        </div>

        <div class="results" id="results">
          <div class="bar"><div class="bl" style="width:50%"></div><div class="br" style="width:50%"></div></div>
          <div class="rlabels">
            <span><b id="rl-name">Damask</b> · <span id="rl-count">0</span></span>
            <span><span id="rr-count">0</span> · <b id="rr-name">Geometric</b></span>
          </div>
        </div>
      </div>

      <div class="tap-hint" id="hint">Tap a side to cast your vote</div>
      <div class="story-foot">
        <div class="reply">Send message…</div>
        <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20.8 4.6a5.5 5.5 0 0 0-7.8 0L12 5.6l-1-1a5.5 5.5 0 1 0-7.8 7.8L12 21l8.8-8.6a5.5 5.5 0 0 0 0-7.8Z"/></svg>
        <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M22 2 11 13"/><path d="M22 2 15 22l-4-9-9-4 20-7Z"/></svg>
      </div>
    </div>
  </div>

  <!-- CONTROLS -->
  <div class="controls">
    <h2>Style the Poll</h2>
    <p class="lead">Rename either style directly on the swatch, and set each palette below. Colours flow live into the CSS-drawn wallcovering.</p>

    <div class="field-label">Left — Palette</div>
    <div class="pickrow">
      <div class="pick"><span>Ground</span><input type="color" value="#33403a" data-var="--l-ground"></div>
      <div class="pick"><span>Motif</span><input type="color" value="#c8a86a" data-var="--l-motif"></div>
    </div>

    <div class="field-label">Right — Palette</div>
    <div class="pickrow">
      <div class="pick"><span>Ground</span><input type="color" value="#2b3550" data-var="--r-ground"></div>
      <div class="pick"><span>Motif</span><input type="color" value="#e6ddcf" data-var="--r-motif"></div>
    </div>

    <div class="btnrow">
      <button class="act" id="reset">Reset Votes</button>
      <button class="act primary" id="demo">Simulate Audience</button>
    </div>
  </div>

  <p class="foot-note">Designer Wallcoverings · Interactive Story Mockup</p>
</main>

<script>
  const story   = document.getElementById('story');
  const arena   = document.getElementById('arena');
  const results = document.getElementById('results');
  const hint    = document.getElementById('hint');
  const root    = document.documentElement;

  const state = { left:0, right:0 };
  const names = { left:'Damask', right:'Geometric' };

  const el = {
    lFill: document.querySelector('.swatch.left .fill'),
    rFill: document.querySelector('.swatch.right .fill'),
    lPct:  document.querySelector('[data-pct="left"]'),
    rPct:  document.querySelector('[data-pct="right"]'),
    lSeal: document.querySelector('.swatch.left .seal'),
    rSeal: document.querySelector('.swatch.right .seal'),
    bl: results.querySelector('.bl'),
    br: results.querySelector('.br'),
    rlName: document.getElementById('rl-name'),
    rrName: document.getElementById('rr-name'),
    rlCount: document.getElementById('rl-count'),
    rrCount: document.getElementById('rr-count'),
  };

  function render(){
    const total = state.left + state.right;
    const voted = total > 0;
    story.classList.toggle('voted', voted);

    let lp = 50, rp = 50;
    if (voted){ lp = Math.round(state.left/total*100); rp = 100 - lp; }

    el.lFill.style.height = voted ? lp+'%' : '0';
    el.rFill.style.height = voted ? rp+'%' : '0';
    el.lPct.textContent = lp+'%';
    el.rPct.textContent = rp+'%';
    el.bl.style.width = lp+'%';
    el.br.style.width = rp+'%';
    el.rlCount.textContent = state.left;
    el.rrCount.textContent = state.right;

    // grow the leader's tile slightly
    document.querySelector('.swatch.left').style.flex  = voted ? Math.max(lp,25) : 1;
    document.querySelector('.swatch.right').style.flex = voted ? Math.max(rp,25) : 1;

    // winner seal
    const lead = state.left === state.right ? null : (state.left > state.right ? 'left' : 'right');
    el.lSeal.classList.toggle('show', voted && lead==='left');
    el.rSeal.classList.toggle('show', voted && lead==='right');

    hint.innerHTML = voted
      ? `<span class="votecount">${total}</span> votes cast · tap to keep voting`
      : 'Tap a side to cast your vote';
  }

  function vote(side){
    state[side]++;
    render();
  }

  arena.addEventListener('click', (e)=>{
    if (e.target.closest('.name')) return;      // editing the label, not voting
    const sw = e.target.closest('.swatch');
    if (sw) vote(sw.dataset.side);
  });

  // editable style names
  document.querySelectorAll('.name').forEach(n=>{
    n.addEventListener('input', ()=>{
      const side = n.dataset.name;
      names[side] = n.textContent.trim() || (side==='left'?'Style A':'Style B');
      el.rlName.textContent = names.left;
      el.rrName.textContent = names.right;
    });
    n.addEventListener('keydown', ev=>{ if(ev.key==='Enter'){ ev.preventDefault(); n.blur(); }});
  });

  // live color tokens
  document.querySelectorAll('input[type=color]').forEach(inp=>{
    inp.addEventListener('input', ()=> root.style.setProperty(inp.dataset.var, inp.value));
  });

  // buttons
  document.getElementById('reset').addEventListener('click', ()=>{
    state.left = 0; state.right = 0; render();
  });
  document.getElementById('demo').addEventListener('click', ()=>{
    let n = 0;
    const iv = setInterval(()=>{
      vote(Math.random() < 0.56 ? 'left' : 'right');
      if(++n >= 18) clearInterval(iv);
    }, 70);
  });

  render();
</script>
</body>
</html>