← back to Model Arena
auto-save: 2026-07-25T08:04:52 (4 files) — data/challenges.json data/costlog.jsonl data/artifacts/57af693363f2/ data/artifacts/70eea6613a73/
e3d5e37c8550f4fb33e492daf15f78916dcd0760 · 2026-07-25 08:04:58 -0700 · Steve Abrams
Files touched
A data/artifacts/57af693363f2/claude-code.htmlA data/artifacts/57af693363f2/claude-code.pngA data/artifacts/57af693363f2/gpt.htmlA data/artifacts/57af693363f2/gpt.pngA data/artifacts/57af693363f2/grok.htmlA data/artifacts/57af693363f2/grok.pngA data/artifacts/57af693363f2/qwen25-7b.htmlA data/artifacts/57af693363f2/qwen25-7b.pngA data/artifacts/57af693363f2/qwen3-14b.htmlA data/artifacts/57af693363f2/qwen3-14b.pngA data/artifacts/70eea6613a73/claude-code.htmlA data/artifacts/70eea6613a73/claude-code.pngA data/artifacts/70eea6613a73/gemma3-12b.htmlA data/artifacts/70eea6613a73/gemma3-12b.pngA data/artifacts/70eea6613a73/gpt.htmlA data/artifacts/70eea6613a73/gpt.pngA data/artifacts/70eea6613a73/grok.htmlA data/artifacts/70eea6613a73/grok.pngA data/artifacts/70eea6613a73/hermes3-8b.htmlA data/artifacts/70eea6613a73/hermes3-8b.pngA data/artifacts/70eea6613a73/hf-qwen-coder-32b.htmlA data/artifacts/70eea6613a73/hf-qwen-coder-32b.pngA data/artifacts/70eea6613a73/kimi.htmlA data/artifacts/70eea6613a73/kimi.pngA data/artifacts/70eea6613a73/qwen25-7b.htmlA data/artifacts/70eea6613a73/qwen25-7b.pngA data/artifacts/70eea6613a73/qwen3-14b.htmlA data/artifacts/70eea6613a73/qwen3-14b.pngM data/challenges.jsonM data/costlog.jsonl
Diff
commit e3d5e37c8550f4fb33e492daf15f78916dcd0760
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Jul 25 08:04:58 2026 -0700
auto-save: 2026-07-25T08:04:52 (4 files) — data/challenges.json data/costlog.jsonl data/artifacts/57af693363f2/ data/artifacts/70eea6613a73/
---
data/artifacts/57af693363f2/claude-code.html | 673 +++++++++++
data/artifacts/57af693363f2/claude-code.png | Bin 0 -> 127461 bytes
data/artifacts/57af693363f2/gpt.html | 1194 +++++++++++++++++++
data/artifacts/57af693363f2/gpt.png | Bin 0 -> 176574 bytes
data/artifacts/57af693363f2/grok.html | 1233 ++++++++++++++++++++
data/artifacts/57af693363f2/grok.png | Bin 0 -> 82106 bytes
data/artifacts/57af693363f2/qwen25-7b.html | 158 +++
data/artifacts/57af693363f2/qwen25-7b.png | Bin 0 -> 21916 bytes
data/artifacts/57af693363f2/qwen3-14b.html | 380 ++++++
data/artifacts/57af693363f2/qwen3-14b.png | Bin 0 -> 20062 bytes
data/artifacts/70eea6613a73/claude-code.html | 521 +++++++++
data/artifacts/70eea6613a73/claude-code.png | Bin 0 -> 80774 bytes
data/artifacts/70eea6613a73/gemma3-12b.html | 274 +++++
data/artifacts/70eea6613a73/gemma3-12b.png | Bin 0 -> 29131 bytes
data/artifacts/70eea6613a73/gpt.html | 1104 ++++++++++++++++++
data/artifacts/70eea6613a73/gpt.png | Bin 0 -> 233554 bytes
data/artifacts/70eea6613a73/grok.html | 937 +++++++++++++++
data/artifacts/70eea6613a73/grok.png | Bin 0 -> 53121 bytes
data/artifacts/70eea6613a73/hermes3-8b.html | 151 +++
data/artifacts/70eea6613a73/hermes3-8b.png | Bin 0 -> 45511 bytes
data/artifacts/70eea6613a73/hf-qwen-coder-32b.html | 204 ++++
data/artifacts/70eea6613a73/hf-qwen-coder-32b.png | Bin 0 -> 38638 bytes
data/artifacts/70eea6613a73/kimi.html | 1041 +++++++++++++++++
data/artifacts/70eea6613a73/kimi.png | Bin 0 -> 27072 bytes
data/artifacts/70eea6613a73/qwen25-7b.html | 162 +++
data/artifacts/70eea6613a73/qwen25-7b.png | Bin 0 -> 25646 bytes
data/artifacts/70eea6613a73/qwen3-14b.html | 272 +++++
data/artifacts/70eea6613a73/qwen3-14b.png | Bin 0 -> 24762 bytes
data/challenges.json | 232 ++--
data/costlog.jsonl | 5 +
30 files changed, 8456 insertions(+), 85 deletions(-)
diff --git a/data/artifacts/57af693363f2/claude-code.html b/data/artifacts/57af693363f2/claude-code.html
new file mode 100644
index 0000000..b7bb5b5
--- /dev/null
+++ b/data/artifacts/57af693363f2/claude-code.html
@@ -0,0 +1,673 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
+<title>Designer Wallcoverings — Roller Run</title>
+<style>
+ :root{
+ --bg:#0d0d0f;
+ --surface:#17171c;
+ --surface-2:#1e1e24;
+ --ink:#f5f2ea;
+ --muted:#8a8578;
+ --accent:#c9a961;
+ --accent-2:#7d6a45;
+ --line:rgba(201,169,97,.22);
+ --shadow:0 8px 24px rgba(0,0,0,.45);
+ --glow:0 0 28px rgba(201,169,97,.30);
+ --ease:cubic-bezier(.22,1,.36,1);
+ --serif:'Didot','Bodoni MT','Playfair Display','Cormorant Garamond',Georgia,serif;
+ --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+ }
+ *{box-sizing:border-box;margin:0;padding:0}
+ html,body{height:100%}
+ body{
+ background:
+ radial-gradient(1200px 600px at 50% -10%, #1a1a20 0%, transparent 60%),
+ var(--bg);
+ color:var(--ink);
+ font-family:var(--sans);
+ -webkit-font-smoothing:antialiased;
+ overflow:hidden;
+ display:flex;
+ flex-direction:column;
+ min-height:100vh;
+ user-select:none;
+ }
+
+ /* ---------- Header / Wordmark lockup ---------- */
+ header.topbar{
+ position:fixed;top:0;left:0;right:0;
+ z-index:30;
+ display:flex;align-items:center;justify-content:space-between;
+ gap:24px;
+ padding:18px 32px;
+ background:linear-gradient(180deg, rgba(13,13,15,.92) 0%, rgba(13,13,15,.55) 70%, transparent 100%);
+ backdrop-filter:blur(4px);
+ pointer-events:none;
+ }
+ .wordmark{
+ display:flex;flex-direction:column;line-height:1;
+ max-width:300px;
+ }
+ .wordmark .brand{
+ font-family:var(--serif);
+ color:var(--ink);
+ font-size:44px;
+ font-weight:500;
+ text-transform:uppercase;
+ letter-spacing:.18em;
+ white-space:nowrap;
+ }
+ .wordmark .sub{
+ margin-top:8px;
+ font-family:var(--sans);
+ font-size:11px;
+ letter-spacing:.34em;
+ text-transform:uppercase;
+ color:var(--accent);
+ padding-left:.18em;
+ }
+ .hairline{
+ height:1px;background:var(--line);
+ margin-top:10px;width:100%;
+ }
+ .scoreboard{
+ display:flex;gap:28px;align-items:flex-start;
+ text-align:right;
+ }
+ .stat{display:flex;flex-direction:column;gap:6px}
+ .stat .label{
+ font-family:var(--sans);
+ font-size:11px;letter-spacing:.16em;text-transform:uppercase;
+ color:var(--muted);
+ }
+ .stat .value{
+ font-family:var(--serif);
+ font-size:30px;color:var(--accent);letter-spacing:.02em;
+ font-variant-numeric:tabular-nums;
+ }
+
+ /* ---------- Stage ---------- */
+ .stage{
+ position:relative;flex:1;display:flex;align-items:center;justify-content:center;
+ }
+ #game{
+ display:block;
+ width:100%;height:100%;
+ position:absolute;inset:0;
+ }
+
+ /* ---------- Overlays ---------- */
+ .overlay{
+ position:absolute;inset:0;z-index:20;
+ display:flex;align-items:center;justify-content:center;
+ padding:24px;
+ }
+ .panel{
+ position:relative;
+ background:linear-gradient(180deg,var(--surface) 0%, var(--surface-2) 100%);
+ border:1px solid var(--line);
+ border-radius:14px;
+ box-shadow:var(--shadow),var(--glow);
+ padding:56px 64px;
+ max-width:560px;width:100%;
+ text-align:center;
+ animation:fadeUp .7s var(--ease) both;
+ }
+ .panel::before{
+ content:"";position:absolute;inset:10px;border:1px solid rgba(201,169,97,.12);
+ border-radius:8px;pointer-events:none;
+ }
+ .eyebrow{
+ font-size:12px;letter-spacing:.32em;text-transform:uppercase;color:var(--accent);
+ margin-bottom:22px;
+ }
+ .panel h1{
+ font-family:var(--serif);
+ font-size:52px;font-weight:500;line-height:1.02;letter-spacing:.01em;
+ margin-bottom:18px;color:var(--ink);
+ }
+ .panel h1 .thin{color:var(--muted);font-style:italic;display:block;font-size:34px;margin-top:6px}
+ .panel p.lead{
+ font-size:16px;line-height:1.7;color:var(--muted);
+ max-width:400px;margin:0 auto 34px;
+ }
+ .legend{
+ display:flex;justify-content:center;gap:26px;flex-wrap:wrap;
+ margin:0 auto 34px;
+ }
+ .legend .item{display:flex;flex-direction:column;align-items:center;gap:10px}
+ .swatch{width:46px;height:46px;border-radius:10px;border:1px solid rgba(255,255,255,.08);box-shadow:0 6px 16px rgba(0,0,0,.4)}
+ .legend .name{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
+ .btn{
+ display:inline-flex;align-items:center;gap:12px;
+ font-family:var(--sans);
+ font-size:13px;letter-spacing:.2em;text-transform:uppercase;
+ color:var(--bg);
+ background:linear-gradient(180deg,var(--accent) 0%, var(--accent-2) 130%);
+ border:none;border-radius:40px;
+ padding:16px 40px;cursor:pointer;
+ box-shadow:0 8px 24px rgba(201,169,97,.28);
+ transition:transform .2s var(--ease), box-shadow .2s var(--ease);
+ }
+ .btn:hover{transform:translateY(-2px);box-shadow:0 14px 34px rgba(201,169,97,.4)}
+ .btn:active{transform:translateY(0)}
+ .finalscores{
+ display:flex;justify-content:center;gap:56px;margin:8px auto 34px;
+ }
+ .finalscores .fs{display:flex;flex-direction:column;gap:8px}
+ .finalscores .fs .l{font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted)}
+ .finalscores .fs .v{font-family:var(--serif);font-size:48px;color:var(--accent);font-variant-numeric:tabular-nums;line-height:1}
+ .hint{
+ margin-top:26px;font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--muted);opacity:.7;
+ }
+ .hide{display:none !important}
+
+ @keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
+
+ @media (max-width:640px){
+ .wordmark .brand{font-size:30px;letter-spacing:.14em;white-space:normal}
+ header.topbar{padding:14px 18px}
+ .scoreboard{gap:16px}
+ .stat .value{font-size:22px}
+ .panel{padding:40px 28px}
+ .panel h1{font-size:38px}
+ .finalscores{gap:36px}
+ }
+</style>
+</head>
+<body>
+
+ <header class="topbar">
+ <div class="wordmark">
+ <span class="brand">Designer Wallcoverings</span>
+ <span class="sub">Roller Run · The Atelier Game</span>
+ <span class="hairline"></span>
+ </div>
+ <div class="scoreboard">
+ <div class="stat">
+ <span class="label">Score</span>
+ <span class="value" id="scoreVal">0</span>
+ </div>
+ <div class="stat">
+ <span class="label">Best</span>
+ <span class="value" id="bestVal">0</span>
+ </div>
+ </div>
+ </header>
+
+ <div class="stage">
+ <canvas id="game"></canvas>
+
+ <!-- Start overlay -->
+ <div class="overlay" id="startOverlay">
+ <div class="panel">
+ <div class="eyebrow">An Endless Roll</div>
+ <h1>Roller Run<span class="thin">collect the collection</span></h1>
+ <p class="lead">Guide the paint-roller along the gallery wall. Gather wallpaper rolls by their design style, dodge the pails and ladders, and let the wall reveal itself faster with every pass.</p>
+ <div class="legend" id="legend"></div>
+ <button class="btn" id="startBtn">Begin the Run</button>
+ <div class="hint">Tap · Click · Press Space to Jump</div>
+ </div>
+ </div>
+
+ <!-- Game over overlay -->
+ <div class="overlay hide" id="overOverlay">
+ <div class="panel">
+ <div class="eyebrow">The Wall Rests</div>
+ <h1>Game Over</h1>
+ <div class="finalscores">
+ <div class="fs"><span class="l">Your Score</span><span class="v" id="finalScore">0</span></div>
+ <div class="fs"><span class="l">Best</span><span class="v" id="finalBest">0</span></div>
+ </div>
+ <p class="lead" id="overMsg">A refined effort. Every roll gathered adds to the pattern.</p>
+ <button class="btn" id="restartBtn">Roll Again</button>
+ <div class="hint">Tap · Click · Press Space</div>
+ </div>
+ </div>
+ </div>
+
+<script>
+(function(){
+ "use strict";
+
+ const canvas = document.getElementById('game');
+ const ctx = canvas.getContext('2d');
+
+ const scoreEl = document.getElementById('scoreVal');
+ const bestEl = document.getElementById('bestVal');
+ const startOverlay = document.getElementById('startOverlay');
+ const overOverlay = document.getElementById('overOverlay');
+ const startBtn = document.getElementById('startBtn');
+ const restartBtn = document.getElementById('restartBtn');
+ const finalScore = document.getElementById('finalScore');
+ const finalBest = document.getElementById('finalBest');
+ const overMsg = document.getElementById('overMsg');
+ const legendEl = document.getElementById('legend');
+
+ // ---- Palette tokens (mirrors CSS) ----
+ const C = {
+ bg:'#0d0d0f', surface:'#17171c', surface2:'#1e1e24',
+ ink:'#f5f2ea', muted:'#8a8578', accent:'#c9a961', accent2:'#7d6a45',
+ line:'rgba(201,169,97,0.22)'
+ };
+
+ // Wallpaper roll "styles" — each visually distinct, no letters.
+ const STYLES = [
+ { name:'Damask', base:'#7d6a45', motif:'#e6cd8f' },
+ { name:'Moiré', base:'#3a4c5a', motif:'#9fc0d1' },
+ { name:'Botanical', base:'#2f4c39', motif:'#a6cf9d' },
+ { name:'Terracotta',base:'#8a4632', motif:'#e0a458' },
+ { name:'Noir Silk', base:'#232028', motif:'#c9a961' }
+ ];
+
+ // Build legend swatches (bare luxury swatches, no letters)
+ STYLES.forEach(s=>{
+ const item = document.createElement('div');
+ item.className='item';
+ const sw = document.createElement('div');
+ sw.className='swatch';
+ sw.style.background = `linear-gradient(135deg, ${s.base} 0%, ${s.motif} 140%)`;
+ const nm = document.createElement('div');
+ nm.className='name'; nm.textContent = s.name;
+ item.appendChild(sw); item.appendChild(nm);
+ legendEl.appendChild(item);
+ });
+
+ // ---- Device / sizing ----
+ let W=0,H=0,DPR=1, groundY=0;
+ function resize(){
+ DPR = Math.min(window.devicePixelRatio||1, 2);
+ W = canvas.clientWidth = canvas.parentElement.clientWidth;
+ H = canvas.clientHeight = canvas.parentElement.clientHeight;
+ canvas.width = Math.floor(W*DPR);
+ canvas.height= Math.floor(H*DPR);
+ ctx.setTransform(DPR,0,0,DPR,0,0);
+ groundY = H*0.80;
+ }
+ window.addEventListener('resize', resize);
+
+ // ---- Game state ----
+ let state='start'; // start | playing | over
+ let best = parseInt(localStorage.getItem('dw_rollerrun_best')||'0',10) || 0;
+ bestEl.textContent = best;
+
+ const player = { x:0, y:0, r:26, vy:0, onGround:true, rot:0, squash:1 };
+ let gravity, jumpV, baseSpeed, speed, distance, score, spawnTimer, spawnGap;
+ let obstacles=[], collectibles=[], particles=[], sparkles=[];
+ let bgOffset=0, shake=0, lastT=0, comboMsg=null;
+
+ function reset(){
+ player.x = W*0.22;
+ player.y = groundY - player.r;
+ player.vy=0; player.onGround=true; player.rot=0; player.squash=1;
+ gravity = H*0.0028;
+ jumpV = -H*0.017;
+ baseSpeed = W*0.0052;
+ speed = baseSpeed;
+ distance=0; score=0; spawnTimer=0; spawnGap=95;
+ obstacles=[]; collectibles=[]; particles=[]; sparkles=[];
+ bgOffset=0; shake=0; comboMsg=null;
+ scoreEl.textContent='0';
+ }
+
+ function start(){
+ resize(); reset();
+ state='playing';
+ startOverlay.classList.add('hide');
+ overOverlay.classList.add('hide');
+ lastT = performance.now();
+ requestAnimationFrame(loop);
+ }
+
+ function gameOver(){
+ state='over';
+ shake = 14;
+ if(score>best){ best=score; localStorage.setItem('dw_rollerrun_best', String(best)); }
+ bestEl.textContent = best;
+ finalScore.textContent = score;
+ finalBest.textContent = best;
+ overMsg.textContent = score>=200
+ ? 'A masterwork of a run — the full collection is nearly yours.'
+ : (score>=80 ? 'Beautifully done. The pattern is taking shape.'
+ : 'A refined effort. Every roll gathered adds to the pattern.');
+ overOverlay.classList.remove('hide');
+ }
+
+ function jump(){
+ if(state!=='playing') return;
+ if(player.onGround){
+ player.vy = jumpV;
+ player.onGround=false;
+ player.squash=0.8;
+ // launch dust
+ for(let i=0;i<8;i++){
+ particles.push({x:player.x, y:groundY, vx:(Math.random()-0.5)*3, vy:-Math.random()*2-0.5, life:1, r:2+Math.random()*2, col:C.muted});
+ }
+ }
+ }
+
+ // ---- Input ----
+ function onPress(e){
+ if(state==='playing'){ jump(); }
+ }
+ window.addEventListener('keydown', e=>{
+ if(e.code==='Space'||e.code==='ArrowUp'){
+ e.preventDefault();
+ if(state==='start') start();
+ else if(state==='over') start();
+ else jump();
+ }
+ });
+ canvas.addEventListener('pointerdown', onPress);
+ startBtn.addEventListener('click', start);
+ restartBtn.addEventListener('click', start);
+
+ // ---- Spawning ----
+ function spawnObstacle(){
+ const kinds=['pail','ladder','pail'];
+ const k = kinds[(Math.random()*kinds.length)|0];
+ if(k==='ladder'){
+ obstacles.push({type:'ladder', x:W+40, w:20, h:64+Math.random()*26});
+ } else {
+ obstacles.push({type:'pail', x:W+40, w:34, h:34+Math.random()*16});
+ }
+ }
+ function spawnCollectible(){
+ const s = STYLES[(Math.random()*STYLES.length)|0];
+ const highJump = Math.random()<0.45;
+ const y = highJump ? groundY - 130 - Math.random()*40 : groundY - 60 - Math.random()*30;
+ collectibles.push({x:W+40, y:y, r:16, style:s, spin:Math.random()*Math.PI, taken:false, float:Math.random()*Math.PI*2});
+ }
+
+ // ---- Update ----
+ function update(dt){
+ speed = baseSpeed + Math.min(distance/2600, baseSpeed*1.9);
+ distance += speed;
+ bgOffset = (bgOffset + speed*0.5) % 240;
+
+ // player physics
+ player.vy += gravity;
+ player.y += player.vy;
+ const floor = groundY - player.r;
+ if(player.y >= floor){
+ player.y = floor;
+ if(!player.onGround){
+ player.squash=1.25;
+ for(let i=0;i<6;i++){
+ particles.push({x:player.x, y:groundY, vx:(Math.random()-0.5)*2.5, vy:-Math.random()*1.5, life:1, r:2+Math.random()*2, col:C.muted});
+ }
+ }
+ player.vy=0; player.onGround=true;
+ }
+ player.rot += speed*0.06;
+ player.squash += (1-player.squash)*0.18;
+
+ // spawn cadence tightens with speed
+ spawnTimer += 1;
+ const gap = Math.max(46, spawnGap - distance/260);
+ if(spawnTimer >= gap){
+ spawnTimer = 0;
+ spawnObstacle();
+ if(Math.random()<0.75) {
+ // stagger a collectible slightly after
+ setTimeout(()=>{ if(state==='playing') spawnCollectible(); }, 180);
+ }
+ }
+
+ // obstacles
+ for(let o of obstacles){ o.x -= speed; }
+ obstacles = obstacles.filter(o=> o.x + (o.w||40) > -20);
+
+ // collectibles
+ for(let c of collectibles){ c.x -= speed; c.spin += 0.08; c.float += 0.06; }
+ collectibles = collectibles.filter(c=> c.x > -40 && !c.taken);
+
+ // collision + collection
+ const pr = player.r*0.9;
+ for(let o of obstacles){
+ let ox, oy, ow, oh;
+ if(o.type==='pail'){ ow=o.w; oh=o.h; ox=o.x; oy=groundY-oh; }
+ else { ow=o.w; oh=o.h; ox=o.x; oy=groundY-oh; }
+ // circle vs rect
+ const cx = Math.max(ox, Math.min(player.x, ox+ow));
+ const cy = Math.max(oy, Math.min(player.y, oy+oh));
+ const dx = player.x - cx, dy = player.y - cy;
+ if(dx*dx+dy*dy < pr*pr){ gameOver(); return; }
+ }
+ for(let c of collectibles){
+ const dx = player.x - c.x, dy = player.y - c.y;
+ if(dx*dx+dy*dy < (pr+c.r)*(pr+c.r)){
+ c.taken=true;
+ score += 5;
+ scoreEl.textContent = score;
+ // sparkle burst in style color
+ for(let i=0;i<14;i++){
+ const a=Math.random()*Math.PI*2, sp=Math.random()*4+1;
+ sparkles.push({x:c.x, y:c.y, vx:Math.cos(a)*sp, vy:Math.sin(a)*sp, life:1, r:1.5+Math.random()*2.5, col: Math.random()<0.5?c.style.motif:c.style.base});
+ }
+ comboMsg = { text:c.style.name, x:c.x, y:c.y-24, life:1, col:c.style.motif };
+ }
+ }
+
+ // passive distance score
+ if(((distance/ W)|0) !== (((distance-speed)/W)|0)){
+ score += 1;
+ scoreEl.textContent = score;
+ }
+
+ // particles
+ for(let p of particles){ p.x -= speed*0.3; p.x+=p.vx; p.y+=p.vy; p.vy+=0.12; p.life-=0.03; }
+ particles = particles.filter(p=>p.life>0);
+ for(let s of sparkles){ s.x-=speed*0.4; s.x+=s.vx; s.y+=s.vy; s.vy+=0.08; s.vx*=0.96; s.life-=0.028; }
+ sparkles = sparkles.filter(s=>s.life>0);
+ if(comboMsg){ comboMsg.x-=speed; comboMsg.y-=0.6; comboMsg.life-=0.02; if(comboMsg.life<=0) comboMsg=null; }
+
+ if(shake>0) shake*=0.86;
+ }
+
+ // ---- Draw ----
+ function roundRect(x,y,w,h,r){
+ ctx.beginPath();
+ ctx.moveTo(x+r,y);
+ ctx.arcTo(x+w,y,x+w,y+h,r);
+ ctx.arcTo(x+w,y+h,x,y+h,r);
+ ctx.arcTo(x,y+h,x,y,r);
+ ctx.arcTo(x,y,x+w,y,r);
+ ctx.closePath();
+ }
+
+ function drawWall(){
+ // deep vignette wall
+ const g = ctx.createLinearGradient(0,0,0,H);
+ g.addColorStop(0, '#141419');
+ g.addColorStop(0.62,'#101014');
+ g.addColorStop(1, '#0b0b0d');
+ ctx.fillStyle=g; ctx.fillRect(0,0,W,H);
+
+ // faint damask-style repeating motif on the wall (hairline gold)
+ ctx.save();
+ ctx.globalAlpha=0.05;
+ ctx.strokeStyle=C.accent;
+ ctx.lineWidth=1;
+ const step=120;
+ for(let x=-((bgOffset)%step); x<W+step; x+=step){
+ for(let y=60; y<groundY-30; y+=step){
+ ctx.beginPath();
+ ctx.ellipse(x, y, 26, 40, 0, 0, Math.PI*2);
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.ellipse(x, y, 12, 20, 0, 0, Math.PI*2);
+ ctx.stroke();
+ }
+ }
+ ctx.restore();
+
+ // baseboard / floor line
+ ctx.fillStyle = '#08080a';
+ ctx.fillRect(0, groundY, W, H-groundY);
+ // gold hairline where roller runs
+ ctx.strokeStyle = C.line;
+ ctx.lineWidth=1;
+ ctx.beginPath(); ctx.moveTo(0,groundY+0.5); ctx.lineTo(W,groundY+0.5); ctx.stroke();
+ // subtle floor sheen
+ const fg = ctx.createLinearGradient(0,groundY,0,H);
+ fg.addColorStop(0,'rgba(201,169,97,0.06)');
+ fg.addColorStop(1,'rgba(201,169,97,0)');
+ ctx.fillStyle=fg; ctx.fillRect(0,groundY,W,H-groundY);
+ }
+
+ function drawPlayer(){
+ ctx.save();
+ ctx.translate(player.x, player.y);
+ // shadow
+ ctx.save();
+ ctx.globalAlpha=0.4;
+ ctx.fillStyle='#000';
+ const sc = Math.max(0.4, 1 - (groundY-player.r-player.y)/260);
+ ctx.beginPath();
+ ctx.ellipse(0, (groundY-player.y), player.r*1.1*sc, 6*sc, 0,0,Math.PI*2);
+ ctx.fill();
+ ctx.restore();
+
+ ctx.rotate(player.rot);
+ ctx.scale(1/player.squash, player.squash);
+
+ // roller drum (gold cylinder as a circle w/ nap ridges)
+ ctx.fillStyle = C.surface2;
+ ctx.beginPath(); ctx.arc(0,0,player.r,0,Math.PI*2); ctx.fill();
+ // metallic rim
+ const rg = ctx.createRadialGradient(-6,-6,4,0,0,player.r);
+ rg.addColorStop(0,'#e6cd8f');
+ rg.addColorStop(0.6,C.accent);
+ rg.addColorStop(1,C.accent2);
+ ctx.fillStyle=rg;
+ ctx.beginPath(); ctx.arc(0,0,player.r-3,0,Math.PI*2); ctx.fill();
+ // nap ridges
+ ctx.strokeStyle='rgba(13,13,15,0.35)'; ctx.lineWidth=2;
+ for(let i=0;i<6;i++){
+ const a=i*Math.PI/3;
+ ctx.beginPath();
+ ctx.moveTo(Math.cos(a)*8, Math.sin(a)*8);
+ ctx.lineTo(Math.cos(a)*(player.r-5), Math.sin(a)*(player.r-5));
+ ctx.stroke();
+ }
+ // hub
+ ctx.fillStyle=C.surface;
+ ctx.beginPath(); ctx.arc(0,0,6,0,Math.PI*2); ctx.fill();
+ ctx.restore();
+ }
+
+ function drawObstacles(){
+ for(let o of obstacles){
+ if(o.type==='pail'){
+ const x=o.x, w=o.w, h=o.h, y=groundY-h;
+ // paint pail — dark surface w/ gold rim + accent drip
+ ctx.fillStyle=C.surface2;
+ roundRect(x, y, w, h, 4); ctx.fill();
+ ctx.strokeStyle=C.accent; ctx.lineWidth=1.5;
+ roundRect(x, y, w, h, 4); ctx.stroke();
+ // rim
+ ctx.fillStyle=C.accent;
+ roundRect(x-2, y-4, w+4, 6, 3); ctx.fill();
+ // paint surface
+ ctx.fillStyle=C.accent2;
+ roundRect(x+3, y-1, w-6, 5, 2); ctx.fill();
+ } else {
+ // ladder / obstacle post
+ const x=o.x, w=o.w, h=o.h, y=groundY-h;
+ ctx.strokeStyle=C.muted; ctx.lineWidth=3;
+ ctx.beginPath(); ctx.moveTo(x,groundY); ctx.lineTo(x, y); ctx.stroke();
+ ctx.beginPath(); ctx.moveTo(x+w,groundY); ctx.lineTo(x+w, y); ctx.stroke();
+ ctx.lineWidth=2; ctx.strokeStyle='rgba(138,133,120,0.7)';
+ for(let ry=y+6; ry<groundY; ry+=14){
+ ctx.beginPath(); ctx.moveTo(x, ry); ctx.lineTo(x+w, ry); ctx.stroke();
+ }
+ }
+ }
+ }
+
+ function drawCollectibles(){
+ for(let c of collectibles){
+ const fy = c.y + Math.sin(c.float)*3;
+ ctx.save();
+ ctx.translate(c.x, fy);
+ // glow
+ ctx.save();
+ ctx.globalAlpha=0.35;
+ const gg=ctx.createRadialGradient(0,0,2,0,0,c.r*2.2);
+ gg.addColorStop(0,c.style.motif); gg.addColorStop(1,'rgba(0,0,0,0)');
+ ctx.fillStyle=gg;
+ ctx.beginPath(); ctx.arc(0,0,c.r*2.2,0,Math.PI*2); ctx.fill();
+ ctx.restore();
+ // rolled wallpaper — a small cylinder end-on with style gradient
+ ctx.rotate(Math.sin(c.spin)*0.15);
+ const wg=ctx.createLinearGradient(-c.r,-c.r,c.r,c.r);
+ wg.addColorStop(0,c.style.base); wg.addColorStop(1,c.style.motif);
+ ctx.fillStyle=wg;
+ roundRect(-c.r, -c.r, c.r*2, c.r*2, 5); ctx.fill();
+ // rolled edge spiral suggestion
+ ctx.strokeStyle='rgba(13,13,15,0.35)'; ctx.lineWidth=2;
+ ctx.beginPath(); ctx.arc(0,0,c.r-4,0,Math.PI*1.6); ctx.stroke();
+ ctx.strokeStyle=c.style.motif; ctx.lineWidth=1.5;
+ roundRect(-c.r,-c.r,c.r*2,c.r*2,5); ctx.stroke();
+ ctx.restore();
+ }
+ }
+
+ function drawFX(){
+ for(let p of particles){
+ ctx.globalAlpha=Math.max(0,p.life);
+ ctx.fillStyle=p.col;
+ ctx.beginPath(); ctx.arc(p.x,p.y,p.r,0,Math.PI*2); ctx.fill();
+ }
+ for(let s of sparkles){
+ ctx.globalAlpha=Math.max(0,s.life);
+ ctx.fillStyle=s.col;
+ ctx.beginPath(); ctx.arc(s.x,s.y,s.r*s.life,0,Math.PI*2); ctx.fill();
+ }
+ ctx.globalAlpha=1;
+ if(comboMsg){
+ ctx.globalAlpha=Math.max(0,comboMsg.life);
+ ctx.fillStyle=comboMsg.col;
+ ctx.font='600 13px -apple-system,Segoe UI,Arial,sans-serif';
+ ctx.textAlign='center';
+ ctx.fillText('+5 '+comboMsg.text.toUpperCase(), comboMsg.x, comboMsg.y);
+ ctx.globalAlpha=1;
+ }
+ }
+
+ function render(){
+ ctx.save();
+ if(shake>0.4){
+ ctx.translate((Math.random()-0.5)*shake, (Math.random()-0.5)*shake);
+ }
+ drawWall();
+ drawCollectibles();
+ drawObstacles();
+ drawFX();
+ drawPlayer();
+ ctx.restore();
+ }
+
+ // ---- Main loop ----
+ function loop(t){
+ const dt = Math.min(50, t-lastT); lastT=t;
+ if(state==='playing'){
+ update(dt);
+ render();
+ requestAnimationFrame(loop);
+ } else {
+ render();
+ }
+ }
+
+ // idle preview render behind start overlay
+ resize(); reset(); render();
+
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/57af693363f2/claude-code.png b/data/artifacts/57af693363f2/claude-code.png
new file mode 100644
index 0000000..791f504
Binary files /dev/null and b/data/artifacts/57af693363f2/claude-code.png differ
diff --git a/data/artifacts/57af693363f2/gpt.html b/data/artifacts/57af693363f2/gpt.html
new file mode 100644
index 0000000..32c2840
--- /dev/null
+++ b/data/artifacts/57af693363f2/gpt.html
@@ -0,0 +1,1194 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Designer Wallcoverings Runner</title>
+ <style>
+ :root {
+ /* Design tokens */
+ --bg: #0d0d0f;
+ --surface: #17171c;
+ --surface-soft: #1f2026;
+ --ink: #f5f2ea;
+ --ink-muted: #8a8578;
+ --accent: #c9a961; /* metallic gold */
+ --accent-deep: #7d6a45;
+ --line: rgba(245, 242, 234, 0.14);
+ --line-strong: rgba(245, 242, 234, 0.32);
+ --shadow-soft: 0 18px 45px rgba(0, 0, 0, 0.6);
+ --shadow-subtle: 0 1px 3px rgba(0, 0, 0, 0.5);
+ --radius-lg: 18px;
+ --radius-md: 12px;
+ --radius-pill: 999px;
+
+ --font-display: "Playfair Display", "Didot", "Bodoni MT", Georgia, serif;
+ --font-serif: "EB Garamond", "Cormorant Garamond", "Playfair Display", Georgia, serif;
+ --font-sans: "Avenir Next", "Century Gothic", -apple-system, "Segoe UI", "Helvetica Neue", sans-serif;
+
+ --fs-logo: 44px;
+ --fs-body: 16px;
+ --fs-label: 11px;
+ --fs-hud: 13px;
+
+ --ease-default: cubic-bezier(.22,.9,.24,1); /* swift-out */
+ --ease-hero: cubic-bezier(.22,1,.36,1); /* ease-out-quint */
+ --ease-pop: cubic-bezier(.34,1.56,.64,1); /* overshoot */
+
+ --transition-fast: 160ms var(--ease-default);
+ --transition-med: 260ms var(--ease-default);
+ }
+
+ * {
+ box-sizing: border-box;
+ }
+
+ html, body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ background: radial-gradient(circle at top, #15151b 0, var(--bg) 52%, #050508 100%);
+ color: var(--ink);
+ font-family: var(--font-sans);
+ -webkit-font-smoothing: antialiased;
+ }
+
+ body {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+ justify-content: flex-start;
+ }
+
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 78px;
+ padding: 18px 32px 14px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ background: linear-gradient(to bottom, rgba(13,13,15,0.96), rgba(13,13,15,0.86));
+ border-bottom: 1px solid var(--line);
+ box-shadow: 0 12px 30px rgba(0,0,0,0.7);
+ z-index: 20;
+ backdrop-filter: blur(18px);
+ }
+
+ .wordmark-lockup {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ max-width: 320px;
+ }
+
+ .wordmark {
+ font-family: var(--font-serif);
+ font-size: var(--fs-logo);
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: #1c1a17; /* darkest ink variant to satisfy requirement */
+ color: var(--bg); /* near-black text over luminous accent panel */
+ line-height: 1.05;
+ padding: 10px 16px 9px;
+ border-radius: 999px;
+ border: 1px solid rgba(0,0,0,0.28);
+ background:
+ linear-gradient(135deg, rgba(255,255,255,0.05), rgba(0,0,0,0.40)),
+ radial-gradient(circle at 10% 0%, rgba(255,255,255,0.35), transparent 55%),
+ linear-gradient(135deg, #f7f3e6 0%, #d9c394 45%, #b59654 100%);
+ box-shadow:
+ 0 0 0 1px rgba(255,255,255,0.05),
+ 0 14px 38px rgba(0,0,0,0.65),
+ inset 0 0 0 0.5px rgba(255,255,255,0.3);
+ white-space: normal;
+ }
+
+ .hud {
+ display: flex;
+ align-items: center;
+ gap: 18px;
+ font-family: var(--font-sans);
+ font-size: var(--fs-hud);
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--ink-muted);
+ }
+
+ .hud-group {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 6px 12px;
+ border-radius: var(--radius-pill);
+ background: rgba(23,23,28,0.9);
+ border: 1px solid var(--line);
+ box-shadow: var(--shadow-subtle);
+ }
+
+ .hud-label {
+ opacity: 0.7;
+ }
+
+ .hud-value {
+ color: var(--ink);
+ }
+
+ .hud-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: radial-gradient(circle at 30% 20%, #fff, #f1e2b0 45%, #b59242 100%);
+ box-shadow: 0 0 0 1px rgba(0,0,0,0.7);
+ }
+
+ main {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 96px 32px 32px;
+ }
+
+ .shell {
+ width: 100%;
+ max-width: 960px;
+ aspect-ratio: 16 / 9;
+ min-height: 420px;
+ position: relative;
+ border-radius: var(--radius-lg);
+ background: radial-gradient(circle at top left, #262632 0, #14141a 40%, #050507 100%);
+ border: 1px solid var(--line-strong);
+ box-shadow: var(--shadow-soft);
+ overflow: hidden;
+ display: flex;
+ align-items: stretch;
+ justify-content: stretch;
+ }
+
+ .canvas-wrap {
+ position: relative;
+ flex: 1;
+ margin: 18px;
+ border-radius: calc(var(--radius-lg) - 10px);
+ background:
+ radial-gradient(circle at 0% 0%, rgba(255,255,255,0.06), transparent 55%),
+ repeating-linear-gradient(
+ 90deg,
+ rgba(255,255,255,0.05) 0,
+ rgba(255,255,255,0.05) 1px,
+ transparent 1px,
+ transparent 32px
+ ),
+ linear-gradient(to bottom, #201f28, #111018 42%, #08070c 100%);
+ border: 1px solid var(--line);
+ overflow: hidden;
+ }
+
+ canvas {
+ width: 100%;
+ height: 100%;
+ display: block;
+ }
+
+ .side-panel {
+ position: absolute;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 220px;
+ padding: 18px 18px 18px 0;
+ pointer-events: none;
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+ }
+
+ .card {
+ pointer-events: auto;
+ background: radial-gradient(circle at top, rgba(255,255,255,0.05), transparent 55%), rgba(12,12,18,0.92);
+ border-radius: var(--radius-md);
+ border: 1px solid var(--line);
+ box-shadow: var(--shadow-subtle);
+ padding: 14px 16px 13px;
+ }
+
+ .card-label {
+ font-size: var(--fs-label);
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--ink-muted);
+ margin-bottom: 8px;
+ }
+
+ .card-body {
+ font-size: 13px;
+ line-height: 1.5;
+ color: var(--ink);
+ }
+
+ .pattern-row {
+ display: flex;
+ gap: 6px;
+ margin-top: 6px;
+ }
+
+ .swatch {
+ flex: 1;
+ height: 34px;
+ border-radius: 999px;
+ border: 1px solid rgba(245,242,234,0.3);
+ box-shadow: inset 0 0 0 0.5px rgba(255,255,255,0.25);
+ overflow: hidden;
+ }
+
+ .swatch--marble {
+ background:
+ radial-gradient(circle at 20% 0%, rgba(255,255,255,0.65), transparent 55%),
+ repeating-linear-gradient(
+ 135deg,
+ rgba(255,255,255,0.28) 0,
+ rgba(255,255,255,0.16) 5px,
+ rgba(0,0,0,0.18) 10px,
+ rgba(0,0,0,0.4) 16px
+ );
+ filter: saturate(1.1);
+ }
+
+ .swatch--geo {
+ background:
+ radial-gradient(circle at 0 0, rgba(255,255,255,0.55), transparent 60%),
+ repeating-linear-gradient(
+ 45deg,
+ transparent 0,
+ transparent 6px,
+ rgba(255,255,255,0.28) 6px,
+ rgba(255,255,255,0.28) 7px
+ ),
+ repeating-linear-gradient(
+ -45deg,
+ transparent 0,
+ transparent 6px,
+ rgba(201,169,97,0.75) 6px,
+ rgba(201,169,97,0.75) 7px
+ );
+ }
+
+ .swatch--silk {
+ background:
+ linear-gradient(135deg, rgba(255,255,255,0.4), transparent 50%),
+ linear-gradient(315deg, rgba(255,255,255,0.45), transparent 55%),
+ linear-gradient(90deg, #22212b 0%, #4a3b2f 40%, #b38a4a 70%, #f3e6c7 100%);
+ background-size: 200% 200%;
+ animation: sheen 10s linear infinite;
+ }
+
+ @keyframes sheen {
+ 0% { background-position: 0% 50%; }
+ 50% { background-position: 100% 50%; }
+ 100% { background-position: 0% 50%; }
+ }
+
+ .controls {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px 10px;
+ margin-top: 8px;
+ font-size: 11px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--ink-muted);
+ }
+
+ .key {
+ min-width: 18px;
+ padding: 3px 6px;
+ border-radius: 8px;
+ border: 1px solid var(--line);
+ background: rgba(23,23,28,0.9);
+ color: var(--ink);
+ text-align: center;
+ box-shadow: inset 0 0 0 0.5px rgba(255,255,255,0.08);
+ }
+
+ .button-row {
+ display: flex;
+ gap: 8px;
+ margin-top: 10px;
+ }
+
+ .btn {
+ pointer-events: auto;
+ flex: 1;
+ padding: 7px 10px;
+ border-radius: var(--radius-pill);
+ border: 1px solid var(--line);
+ background: linear-gradient(to bottom, #23222e, #13121a);
+ color: var(--ink);
+ font-family: var(--font-sans);
+ font-size: 11px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ transition:
+ background-color var(--transition-med),
+ border-color var(--transition-med),
+ transform var(--transition-fast),
+ box-shadow var(--transition-med);
+ }
+
+ .btn-primary {
+ background:
+ radial-gradient(circle at 0 0, rgba(255,255,255,0.15), transparent 55%),
+ linear-gradient(135deg, #d7bf7c, #b6934b);
+ color: #201d12;
+ border-color: rgba(248,241,221,0.9);
+ box-shadow:
+ 0 0 0 1px rgba(0,0,0,0.55),
+ 0 10px 24px rgba(0,0,0,0.7);
+ }
+
+ .btn-primary:hover {
+ transform: translateY(-1px);
+ box-shadow:
+ 0 0 0 1px rgba(0,0,0,0.7),
+ 0 12px 32px rgba(0,0,0,0.8);
+ }
+
+ .btn-ghost:hover {
+ background: linear-gradient(to bottom, #2b2a36, #18171f);
+ border-color: var(--line-strong);
+ transform: translateY(-1px);
+ box-shadow: 0 10px 24px rgba(0,0,0,0.7);
+ }
+
+ .btn-icon {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: radial-gradient(circle at 30% 20%, #fff, #f7e8ba 45%, #b6934b 100%);
+ box-shadow: 0 0 0 1px rgba(0,0,0,0.7);
+ }
+
+ .overlay {
+ position: absolute;
+ inset: 18px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ pointer-events: none;
+ z-index: 10;
+ }
+
+ .overlay-inner {
+ pointer-events: auto;
+ min-width: 260px;
+ max-width: 360px;
+ padding: 20px 22px 18px;
+ border-radius: var(--radius-lg);
+ background:
+ radial-gradient(circle at top, rgba(255,255,255,0.1), transparent 55%),
+ linear-gradient(135deg, rgba(13,13,15,0.98), rgba(13,13,15,0.92));
+ border: 1px solid rgba(245,242,234,0.22);
+ box-shadow: 0 28px 60px rgba(0,0,0,0.85);
+ transform: translateY(12px);
+ opacity: 0;
+ transition:
+ opacity 260ms var(--ease-hero),
+ transform 260ms var(--ease-hero);
+ }
+
+ .overlay--visible .overlay-inner {
+ opacity: 1;
+ transform: translateY(0);
+ }
+
+ .overlay-title {
+ font-family: var(--font-serif);
+ font-size: 28px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--ink);
+ margin-bottom: 6px;
+ }
+
+ .overlay-sub {
+ font-size: 13px;
+ color: var(--ink-muted);
+ margin-bottom: 12px;
+ }
+
+ .overlay-metrics {
+ display: flex;
+ justify-content: space-between;
+ gap: 10px;
+ margin-bottom: 14px;
+ font-size: 13px;
+ }
+
+ .overlay-metric-label {
+ text-transform: uppercase;
+ letter-spacing: 0.16em;
+ font-size: 11px;
+ color: var(--ink-muted);
+ margin-bottom: 2px;
+ }
+
+ .overlay-metric-value {
+ color: var(--ink);
+ }
+
+ .pill {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ padding: 3px 9px;
+ border-radius: var(--radius-pill);
+ border: 1px solid rgba(245,242,234,0.24);
+ background: rgba(23,23,28,0.9);
+ font-size: 11px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--ink-muted);
+ }
+
+ .pill-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: radial-gradient(circle at 30% 20%, #fff, #f9eec3 45%, #c9a961 100%);
+ box-shadow: 0 0 0 1px rgba(0,0,0,0.7);
+ }
+
+ .overlay-actions {
+ display: flex;
+ gap: 8px;
+ margin-top: 14px;
+ }
+
+ .hidden {
+ display: none;
+ }
+
+ @media (max-width: 900px) {
+ header {
+ padding: 14px 18px 10px;
+ height: auto;
+ }
+ .wordmark {
+ font-size: 40px;
+ }
+ main {
+ padding: 92px 14px 18px;
+ }
+ .shell {
+ aspect-ratio: 3 / 4;
+ }
+ .side-panel {
+ position: static;
+ width: auto;
+ padding: 0;
+ margin: 0 12px 12px;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ }
+ .card {
+ flex: 1;
+ min-width: 180px;
+ }
+ .overlay-inner {
+ max-width: 90%;
+ }
+ }
+
+ @media (max-width: 640px) {
+ .hud {
+ display: none;
+ }
+ .shell {
+ min-height: 360px;
+ }
+ .wordmark {
+ font-size: 40px;
+ letter-spacing: 0.16em;
+ }
+ }
+ </style>
+</head>
+<body>
+ <header>
+ <div class="wordmark-lockup">
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ </div>
+ <div class="hud">
+ <div class="hud-group">
+ <div class="hud-label">Score</div>
+ <div class="hud-value" id="scoreHud">000</div>
+ </div>
+ <div class="hud-group">
+ <div class="hud-label">Best</div>
+ <div class="hud-value" id="bestHud">000</div>
+ </div>
+ <div class="hud-group">
+ <div class="hud-dot"></div>
+ <div class="hud-label">Tap / Space to jump</div>
+ </div>
+ </div>
+ </header>
+ <main>
+ <div class="shell">
+ <div class="canvas-wrap">
+ <canvas id="gameCanvas"></canvas>
+ <div class="overlay overlay--visible" id="startOverlay">
+ <div class="overlay-inner">
+ <div class="overlay-title">Luxe Roller Run</div>
+ <div class="overlay-sub">
+ Glide your paint roller along the gallery wall, collecting curated wallpapers and gliding past architectural trims.
+ </div>
+ <div class="overlay-metrics">
+ <div>
+ <div class="overlay-metric-label">Best Score</div>
+ <div class="overlay-metric-value" id="bestOverlay">000</div>
+ </div>
+ <div>
+ <div class="overlay-metric-label">Difficulty</div>
+ <div class="overlay-metric-value">Rising Tempo</div>
+ </div>
+ </div>
+ <div class="pill">
+ <span class="pill-dot"></span>
+ <span>Tap / Space / Up to jump</span>
+ </div>
+ <div class="overlay-actions">
+ <button class="btn btn-primary" id="startPlay">
+ <span class="btn-icon"></span>
+ <span>Begin Run</span>
+ </button>
+ <button class="btn btn-ghost" id="startPractice">
+ <span>Practice</span>
+ </button>
+ </div>
+ </div>
+ </div>
+
+ <div class="overlay hidden" id="gameOverOverlay">
+ <div class="overlay-inner">
+ <div class="overlay-title">Wall Scuffed</div>
+ <div class="overlay-sub">
+ The roller clipped a molding. Reset the wall and refine your line.
+ </div>
+ <div class="overlay-metrics">
+ <div>
+ <div class="overlay-metric-label">Run Score</div>
+ <div class="overlay-metric-value" id="runScore">000</div>
+ </div>
+ <div>
+ <div class="overlay-metric-label">Best Score</div>
+ <div class="overlay-metric-value" id="runBest">000</div>
+ </div>
+ </div>
+ <div class="overlay-actions">
+ <button class="btn btn-primary" id="restartBtn">
+ <span class="btn-icon"></span>
+ <span>Run Again</span>
+ </button>
+ <button class="btn btn-ghost" id="resumeBtn">
+ <span>Watch Wall</span>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <aside class="side-panel">
+ <section class="card">
+ <div class="card-label">Controls</div>
+ <div class="card-body">
+ <div class="controls">
+ <span class="key">Tap</span>
+ <span class="key">Space</span>
+ <span class="key">↑</span>
+ <span>Jump</span>
+ </div>
+ </div>
+ </section>
+ <section class="card">
+ <div class="card-label">Palette Styles</div>
+ <div class="card-body">
+ <div class="pattern-row">
+ <div class="swatch swatch--marble" title="Marble Vein"></div>
+ <div class="swatch swatch--geo" title="Art Deco Geo"></div>
+ <div class="swatch swatch--silk" title="Silk Panel"></div>
+ </div>
+ </div>
+ </section>
+ </aside>
+ </div>
+ </main>
+
+ <script>
+ (function() {
+ const canvas = document.getElementById('gameCanvas');
+ const ctx = canvas.getContext('2d');
+
+ function resize() {
+ const rect = canvas.parentElement.getBoundingClientRect();
+ const dpr = window.devicePixelRatio || 1;
+ canvas.width = rect.width * dpr;
+ canvas.height = rect.height * dpr;
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
+ }
+ resize();
+ window.addEventListener('resize', resize);
+
+ const state = {
+ running: false,
+ practice: false,
+ gameOver: false,
+ speed: 4.2,
+ maxSpeed: 10,
+ speedIncrease: 0.00045,
+ gravity: 0.5,
+ jumpVel: -9.6,
+ groundY: 0,
+ roller: { x: 110, y: 0, vy: 0, radius: 20 },
+ collectibles: [],
+ obstacles: [],
+ wallpaperTypes: [
+ { name: 'marble', color: '#f3eadd' },
+ { name: 'geo', color: '#c9a961' },
+ { name: 'silk', color: '#c5b8ff' }
+ ],
+ score: 0,
+ best: 0,
+ lastTime: 0,
+ spawnTimerObs: 0,
+ spawnTimerCol: 0
+ };
+
+ const scoreHud = document.getElementById('scoreHud');
+ const bestHud = document.getElementById('bestHud');
+ const bestOverlay = document.getElementById('bestOverlay');
+ const runScore = document.getElementById('runScore');
+ const runBest = document.getElementById('runBest');
+ const startOverlay = document.getElementById('startOverlay');
+ const gameOverOverlay = document.getElementById('gameOverOverlay');
+
+ function loadBest() {
+ try {
+ const v = localStorage.getItem('dw_runner_best');
+ const n = v ? parseInt(v, 10) : 0;
+ if (!isNaN(n)) state.best = n;
+ } catch(e) {}
+ bestHud.textContent = pad(state.best);
+ bestOverlay.textContent = pad(state.best);
+ }
+
+ function saveBest() {
+ try {
+ localStorage.setItem('dw_runner_best', String(state.best));
+ } catch(e) {}
+ }
+
+ function pad(n) {
+ return String(Math.floor(n)).padStart(3, '0');
+ }
+
+ loadBest();
+
+ function resetRun() {
+ const h = canvas.getBoundingClientRect().height;
+ state.groundY = h * 0.72;
+ state.roller.y = state.groundY - state.roller.radius;
+ state.roller.vy = 0;
+ state.collectibles.length = 0;
+ state.obstacles.length = 0;
+ state.score = 0;
+ state.speed = 4.2;
+ state.spawnTimerObs = 0;
+ state.spawnTimerCol = 0;
+ scoreHud.textContent = pad(0);
+ }
+
+ function startGame(practice) {
+ state.practice = practice;
+ state.running = true;
+ state.gameOver = false;
+ hideOverlay(startOverlay);
+ hideOverlay(gameOverOverlay);
+ resetRun();
+ }
+
+ function showOverlay(el) {
+ el.classList.remove('hidden');
+ requestAnimationFrame(() => el.classList.add('overlay--visible'));
+ }
+
+ function hideOverlay(el) {
+ el.classList.remove('overlay--visible');
+ setTimeout(() => {
+ el.classList.add('hidden');
+ }, 260);
+ }
+
+ function endGame() {
+ state.running = false;
+ state.gameOver = true;
+ runScore.textContent = pad(state.score);
+ if (state.score > state.best) {
+ state.best = state.score;
+ saveBest();
+ }
+ bestHud.textContent = pad(state.best);
+ bestOverlay.textContent = pad(state.best);
+ runBest.textContent = pad(state.best);
+ showOverlay(gameOverOverlay);
+ }
+
+ function spawnObstacle() {
+ const h = canvas.getBoundingClientRect().height;
+ const type = Math.random() < 0.5 ? 'low' : 'tall';
+ const width = type === 'low' ? 30 : 26;
+ const height = type === 'low' ? 30 : 60;
+ const y = state.groundY - height;
+ state.obstacles.push({
+ x: canvas.getBoundingClientRect().width + width,
+ y,
+ width,
+ height,
+ type
+ });
+ }
+
+ function spawnCollectible() {
+ const cType = state.wallpaperTypes[Math.floor(Math.random() * state.wallpaperTypes.length)];
+ const lane = Math.random();
+ const baseY = state.groundY - 40;
+ let y = baseY;
+ if (lane < 0.33) y = baseY - 60;
+ else if (lane < 0.66) y = baseY - 30;
+ const width = 18;
+ const height = 32;
+ state.collectibles.push({
+ x: canvas.getBoundingClientRect().width + width,
+ y,
+ width,
+ height,
+ type: cType
+ });
+ }
+
+ function rollerRect() {
+ const r = state.roller;
+ return {
+ x: r.x - r.radius,
+ y: r.y - r.radius,
+ width: r.radius * 2,
+ height: r.radius * 2
+ };
+ }
+
+ function rectsIntersect(a, b) {
+ return a.x < b.x + b.width &&
+ a.x + a.width > b.x &&
+ a.y < b.y + b.height &&
+ a.y + a.height > b.y;
+ }
+
+ function jump() {
+ if (!state.running) return;
+ if (state.roller.y >= state.groundY - state.roller.radius - 0.5) {
+ state.roller.vy = state.jumpVel;
+ }
+ }
+
+ function drawBackground() {
+ const w = canvas.getBoundingClientRect().width;
+ const h = canvas.getBoundingClientRect().height;
+ const panelHeight = h * 0.65;
+ const baseY = state.groundY - panelHeight + 4;
+
+ const grad = ctx.createLinearGradient(0, baseY, 0, baseY + panelHeight);
+ grad.addColorStop(0, '#25222f');
+ grad.addColorStop(0.4, '#191823');
+ grad.addColorStop(1, '#08070c');
+ ctx.fillStyle = grad;
+ ctx.fillRect(0, baseY, w, panelHeight);
+
+ const seamCount = 7;
+ const seamWidth = w / seamCount;
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(0, baseY, w, panelHeight);
+ ctx.clip();
+
+ const offset = (Date.now() * 0.02 * state.speed) % seamWidth;
+
+ for (let i = -2; i < seamCount + 2; i++) {
+ const x = i * seamWidth - offset;
+ const panelGrad = ctx.createLinearGradient(x, baseY, x + seamWidth, baseY + panelHeight);
+ panelGrad.addColorStop(0, 'rgba(255,255,255,0.04)');
+ panelGrad.addColorStop(0.5, 'rgba(0,0,0,0.4)');
+ panelGrad.addColorStop(1, 'rgba(255,255,255,0.08)');
+ ctx.fillStyle = panelGrad;
+ ctx.fillRect(x, baseY, seamWidth - 1, panelHeight);
+
+ ctx.strokeStyle = 'rgba(0,0,0,0.8)';
+ ctx.lineWidth = 1;
+ ctx.beginPath();
+ ctx.moveTo(x, baseY);
+ ctx.lineTo(x, baseY + panelHeight);
+ ctx.stroke();
+
+ ctx.strokeStyle = 'rgba(255,255,255,0.08)';
+ ctx.beginPath();
+ ctx.moveTo(x + seamWidth - 1, baseY);
+ ctx.lineTo(x + seamWidth - 1, baseY + panelHeight);
+ ctx.stroke();
+ }
+ ctx.restore();
+
+ ctx.strokeStyle = 'rgba(0,0,0,0.85)';
+ ctx.lineWidth = 2;
+ ctx.beginPath();
+ ctx.moveTo(0, state.groundY + 0.5);
+ ctx.lineTo(w, state.groundY + 0.5);
+ ctx.stroke();
+
+ ctx.strokeStyle = 'rgba(255,255,255,0.06)';
+ ctx.beginPath();
+ ctx.moveTo(0, state.groundY - 2);
+ ctx.lineTo(w, state.groundY - 2);
+ ctx.stroke();
+ }
+
+ function drawCollectible(c) {
+ ctx.save();
+ const { x, y, width, height, type } = c;
+ const radius = 6;
+ ctx.beginPath();
+ ctx.moveTo(x + radius, y);
+ ctx.lineTo(x + width - radius, y);
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
+ ctx.lineTo(x + width, y + height - radius);
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+ ctx.lineTo(x + radius, y + height);
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
+ ctx.lineTo(x, y + radius);
+ ctx.quadraticCurveTo(x, y, x + radius, y);
+ ctx.closePath();
+
+ let fill;
+ if (type.name === 'marble') {
+ fill = ctx.createLinearGradient(x, y, x + width, y + height);
+ fill.addColorStop(0, '#faf3e8');
+ fill.addColorStop(0.5, '#e1d4c4');
+ fill.addColorStop(1, '#b2a08d');
+ } else if (type.name === 'geo') {
+ fill = ctx.createLinearGradient(x, y, x + width, y + height);
+ fill.addColorStop(0, '#f3e6c5');
+ fill.addColorStop(0.4, '#d7bd7a');
+ fill.addColorStop(1, '#a88437');
+ } else {
+ fill = ctx.createLinearGradient(x, y, x, y + height);
+ fill.addColorStop(0, '#f7f4ff');
+ fill.addColorStop(0.4, '#d0c5ff');
+ fill.addColorStop(1, '#8576c8');
+ }
+ ctx.fillStyle = fill;
+ ctx.fill();
+
+ ctx.strokeStyle = 'rgba(0,0,0,0.7)';
+ ctx.lineWidth = 1;
+ ctx.stroke();
+
+ ctx.beginPath();
+ ctx.moveTo(x + 3, y + 4);
+ ctx.lineTo(x + width - 3, y + 4);
+ ctx.strokeStyle = 'rgba(255,255,255,0.45)';
+ ctx.lineWidth = 1;
+ ctx.stroke();
+
+ if (type.name === 'geo') {
+ ctx.strokeStyle = 'rgba(0,0,0,0.3)';
+ ctx.lineWidth = 0.8;
+ ctx.beginPath();
+ ctx.moveTo(x + 3, y + height * 0.5);
+ ctx.lineTo(x + width - 3, y + height * 0.3);
+ ctx.lineTo(x + width - 5, y + height - 4);
+ ctx.closePath();
+ ctx.stroke();
+ } else if (type.name === 'marble') {
+ ctx.strokeStyle = 'rgba(0,0,0,0.3)';
+ ctx.lineWidth = 1.2;
+ ctx.beginPath();
+ ctx.moveTo(x + 4, y + height - 6);
+ ctx.bezierCurveTo(x + 6, y + height - 10, x + 10, y + height - 3, x + 14, y + height - 8);
+ ctx.bezierCurveTo(x + 18, y + height - 13, x + 20, y + height - 5, x + width - 4, y + height - 10);
+ ctx.stroke();
+ } else {
+ ctx.strokeStyle = 'rgba(255,255,255,0.38)';
+ ctx.lineWidth = 0.9;
+ ctx.beginPath();
+ ctx.moveTo(x + 2, y + height * 0.3);
+ ctx.lineTo(x + width - 2, y + height * 0.7);
+ ctx.stroke();
+ }
+
+ ctx.restore();
+ }
+
+ function drawObstacle(o) {
+ ctx.save();
+ const { x, y, width, height, type } = o;
+ const radius = 6;
+ ctx.beginPath();
+ ctx.moveTo(x + radius, y);
+ ctx.lineTo(x + width - radius, y);
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
+ ctx.lineTo(x + width, y + height - radius);
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+ ctx.lineTo(x + radius, y + height);
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
+ ctx.lineTo(x, y + radius);
+ ctx.quadraticCurveTo(x, y, x + radius, y);
+ ctx.closePath();
+
+ const grad = ctx.createLinearGradient(x, y, x + width, y + height);
+ if (type === 'low') {
+ grad.addColorStop(0, '#2a272c');
+ grad.addColorStop(0.4, '#17141a');
+ grad.addColorStop(1, '#060509');
+ } else {
+ grad.addColorStop(0, '#25222b');
+ grad.addColorStop(1, '#0b0a10');
+ }
+ ctx.fillStyle = grad;
+ ctx.fill();
+
+ ctx.strokeStyle = 'rgba(0,0,0,0.9)';
+ ctx.lineWidth = 1;
+ ctx.stroke();
+
+ const trimGrad = ctx.createLinearGradient(x, y, x, y + 8);
+ trimGrad.addColorStop(0, 'rgba(255,255,255,0.3)');
+ trimGrad.addColorStop(1, 'rgba(255,255,255,0.05)');
+ ctx.fillStyle = trimGrad;
+ ctx.fillRect(x + 2, y + 2, width - 4, 6);
+ }
+
+ function drawRoller() {
+ const r = state.roller;
+ ctx.save();
+
+ const handleX = r.x - 18;
+ const handleY = r.y + 12;
+ ctx.strokeStyle = '#c9a961';
+ ctx.lineWidth = 2;
+ ctx.beginPath();
+ ctx.moveTo(handleX, handleY);
+ ctx.lineTo(handleX - 8, handleY + 14);
+ ctx.stroke();
+ ctx.lineWidth = 4;
+ ctx.strokeStyle = '#ded3b3';
+ ctx.beginPath();
+ ctx.moveTo(handleX - 8, handleY + 14);
+ ctx.lineTo(handleX - 18, handleY + 26);
+ ctx.stroke();
+
+ ctx.fillStyle = '#c9a961';
+ ctx.beginPath();
+ ctx.arc(r.x, r.y, r.radius, 0, Math.PI * 2);
+ ctx.fill();
+
+ const innerGrad = ctx.createRadialGradient(r.x - 6, r.y - 8, 4, r.x, r.y, r.radius);
+ innerGrad.addColorStop(0, '#fff8d8');
+ innerGrad.addColorStop(0.4, '#f2dd9d');
+ innerGrad.addColorStop(1, '#7d6a45');
+ ctx.fillStyle = innerGrad;
+ ctx.beginPath();
+ ctx.arc(r.x, r.y, r.radius - 4, 0, Math.PI * 2);
+ ctx.fill();
+
+ ctx.fillStyle = '#0d0d0f';
+ ctx.beginPath();
+ ctx.arc(r.x, r.y, 4, 0, Math.PI * 2);
+ ctx.fill();
+
+ ctx.strokeStyle = 'rgba(255,255,255,0.5)';
+ ctx.lineWidth = 1;
+ ctx.beginPath();
+ ctx.arc(r.x - 4, r.y - 6, r.radius - 7, -Math.PI * 0.3, -Math.PI * 0.9, true);
+ ctx.stroke();
+
+ const trailLength = 100;
+ const trailHeight = 14;
+ const tx = r.x - r.radius - 4;
+ const ty = r.y - trailHeight / 2;
+ const grad = ctx.createLinearGradient(tx - trailLength, ty, tx, ty);
+ grad.addColorStop(0, 'rgba(201,169,97,0)');
+ grad.addColorStop(0.3, 'rgba(201,169,97,0.2)');
+ grad.addColorStop(1, 'rgba(201,169,97,0.8)');
+ ctx.fillStyle = grad;
+ ctx.beginPath();
+ ctx.moveTo(tx, ty);
+ ctx.lineTo(tx - trailLength, ty);
+ ctx.lineTo(tx - trailLength, ty + trailHeight);
+ ctx.lineTo(tx, ty + trailHeight);
+ ctx.closePath();
+ ctx.fill();
+
+ ctx.restore();
+ }
+
+ function update(dt) {
+ const w = canvas.getBoundingClientRect().width;
+ const speedPx = state.speed * (dt / 16.67);
+
+ state.speed = Math.min(state.maxSpeed, state.speed + state.speedIncrease * dt);
+
+ const r = state.roller;
+ r.vy += state.gravity * (dt / 16.67);
+ r.y += r.vy;
+ if (r.y >= state.groundY - r.radius) {
+ r.y = state.groundY - r.radius;
+ r.vy = 0;
+ }
+
+ state.spawnTimerObs += dt;
+ if (state.spawnTimerObs > 800 + Math.random() * 700) {
+ spawnObstacle();
+ state.spawnTimerObs = 0;
+ }
+ state.spawnTimerCol += dt;
+ if (state.spawnTimerCol > 650 + Math.random() * 650) {
+ spawnCollectible();
+ state.spawnTimerCol = 0;
+ }
+
+ const rr = rollerRect();
+
+ for (let i = state.obstacles.length - 1; i >= 0; i--) {
+ const o = state.obstacles[i];
+ o.x -= speedPx;
+ if (!state.practice && rectsIntersect(rr, o)) {
+ endGame();
+ return;
+ }
+ if (o.x + o.width < -40) {
+ state.obstacles.splice(i, 1);
+ }
+ }
+
+ for (let i = state.collectibles.length - 1; i >= 0; i--) {
+ const c = state.collectibles[i];
+ c.x -= speedPx;
+ if (rectsIntersect(rr, c)) {
+ state.collectibles.splice(i, 1);
+ state.score += 5;
+ scoreHud.textContent = pad(state.score);
+ continue;
+ }
+ if (c.x + c.width < -40) {
+ state.collectibles.splice(i, 1);
+ }
+ }
+
+ if (state.running) {
+ state.score += 0.03 * (dt / 16.67);
+ scoreHud.textContent = pad(state.score);
+ }
+ }
+
+ function render() {
+ const w = canvas.getBoundingClientRect().width;
+ const h = canvas.getBoundingClientRect().height;
+ ctx.clearRect(0, 0, w, h);
+ drawBackground();
+
+ ctx.save();
+ const glowGrad = ctx.createRadialGradient(
+ state.roller.x - 30, state.roller.y - 60, 10,
+ state.roller.x - 30, state.roller.y - 60, 180
+ );
+ glowGrad.addColorStop(0, 'rgba(236,217,155,0.22)');
+ glowGrad.addColorStop(1, 'rgba(236,217,155,0)');
+ ctx.fillStyle = glowGrad;
+ ctx.fillRect(0, 0, w, h);
+ ctx.restore();
+
+ for (const c of state.collectibles) drawCollectible(c);
+ for (const o of state.obstacles) drawObstacle(o);
+ drawRoller();
+ }
+
+ function loop(timestamp) {
+ if (!state.lastTime) state.lastTime = timestamp;
+ const dt = Math.min(40, timestamp - state.lastTime);
+ state.lastTime = timestamp;
+
+ if (state.running) {
+ update(dt);
+ }
+ render();
+
+ requestAnimationFrame(loop);
+ }
+
+ requestAnimationFrame(loop);
+
+ function handleKey(e) {
+ if (e.code === 'Space' || e.code === 'ArrowUp') {
+ e.preventDefault();
+ if (!state.running && !state.gameOver) {
+ startGame(false);
+ } else if (!state.running && state.gameOver) {
+ startGame(false);
+ } else {
+ jump();
+ }
+ }
+ }
+
+ function handlePointer(e) {
+ const rect = canvas.getBoundingClientRect();
+ const x = (e.touches ? e.touches[0].clientX : e.clientX);
+ const y = (e.touches ? e.touches[0].clientY : e.clientY);
+ if (x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom) {
+ if (!state.running && !state.gameOver) {
+ startGame(false);
+ } else if (!state.running && state.gameOver) {
+ startGame(false);
+ } else {
+ jump();
+ }
+ }
+ }
+
+ window.addEventListener('keydown', handleKey);
+ window.addEventListener('mousedown', handlePointer);
+ window.addEventListener('touchstart', handlePointer, { passive: false });
+
+ document.getElementById('startPlay').addEventListener('click', function() {
+ startGame(false);
+ });
+ document.getElementById('startPractice').addEventListener('click', function() {
+ startGame(true);
+ });
+ document.getElementById('restartBtn').addEventListener('click', function() {
+ startGame(false);
+ });
+ document.getElementById('resumeBtn').addEventListener('click', function() {
+ hideOverlay(gameOverOverlay);
+ state.gameOver = false;
+ });
+ })();
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/57af693363f2/gpt.png b/data/artifacts/57af693363f2/gpt.png
new file mode 100644
index 0000000..562f86c
Binary files /dev/null and b/data/artifacts/57af693363f2/gpt.png differ
diff --git a/data/artifacts/57af693363f2/grok.html b/data/artifacts/57af693363f2/grok.html
new file mode 100644
index 0000000..76eeea3
--- /dev/null
+++ b/data/artifacts/57af693363f2/grok.html
@@ -0,0 +1,1233 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Designer Wallcoverings — Roll</title>
+<style>
+:root {
+ --bg: #f7f3eb;
+ --bg-deep: #efe8dc;
+ --surface: #fffcf6;
+ --ink: #1c1a17;
+ --ink-soft: #3a3530;
+ --muted: #8a8276;
+ --accent: #b8952c;
+ --accent-deep: #8a6e1f;
+ --accent-soft: rgba(184, 149, 44, 0.14);
+ --line: rgba(28, 26, 23, 0.12);
+ --line-strong: rgba(28, 26, 23, 0.22);
+ --shadow: 0 12px 40px rgba(28, 26, 23, 0.08);
+ --shadow-soft: 0 4px 16px rgba(28, 26, 23, 0.06);
+ --ease: cubic-bezier(.22, .9, .24, 1);
+ --ease-out: cubic-bezier(.22, 1, .36, 1);
+ --ease-pop: cubic-bezier(.34, 1.56, .64, 1);
+ --serif: 'Didot', 'Bodoni MT', 'Playfair Display', 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
+ --sans: 'Avenir Next', 'Century Gothic', 'Helvetica Neue', Futura, sans-serif;
+ --radius: 14px;
+ --radius-sm: 6px;
+ --header-h: 72px;
+}
+
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+
+html, body {
+ height: 100%;
+ overflow: hidden;
+ background: var(--bg);
+ color: var(--ink);
+ font-family: var(--sans);
+ font-size: 16px;
+ line-height: 1.5;
+ -webkit-font-smoothing: antialiased;
+}
+
+/* —— Fixed brand header —— */
+.site-header {
+ position: fixed;
+ top: 0; left: 0; right: 0;
+ z-index: 100;
+ height: var(--header-h);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 28px;
+ background: rgba(247, 243, 235, 0.92);
+ backdrop-filter: blur(12px);
+ border-bottom: 1px solid var(--line);
+}
+
+.wordmark {
+ font-family: var(--serif);
+ font-size: clamp(18px, 2.6vw, 28px);
+ font-weight: 500;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ line-height: 1.15;
+ white-space: normal;
+ max-width: min(520px, 58vw);
+}
+
+.header-meta {
+ display: flex;
+ align-items: center;
+ gap: 28px;
+ font-family: var(--sans);
+ font-size: 11px;
+ font-weight: 600;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.header-meta .stat {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-end;
+ gap: 2px;
+}
+
+.header-meta .stat b {
+ color: var(--ink);
+ font-weight: 600;
+ font-size: 13px;
+ letter-spacing: 0.12em;
+ font-variant-numeric: tabular-nums;
+}
+
+.header-meta .stat b.accent { color: var(--accent-deep); }
+
+/* —— Stage —— */
+.stage {
+ position: fixed;
+ inset: var(--header-h) 0 0 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background:
+ radial-gradient(ellipse 80% 60% at 50% 0%, rgba(184,149,44,0.06), transparent 60%),
+ linear-gradient(180deg, var(--bg) 0%, var(--bg-deep) 100%);
+ padding: 24px;
+}
+
+.canvas-wrap {
+ position: relative;
+ width: min(960px, 100%);
+ aspect-ratio: 16 / 9;
+ max-height: calc(100vh - var(--header-h) - 48px);
+ background: var(--surface);
+ border: 1px solid var(--line);
+ border-radius: var(--radius);
+ box-shadow: var(--shadow);
+ overflow: hidden;
+}
+
+canvas {
+ display: block;
+ width: 100%;
+ height: 100%;
+ cursor: pointer;
+}
+
+/* —— Overlays —— */
+.overlay {
+ position: absolute;
+ inset: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 40px 32px;
+ background: rgba(247, 243, 235, 0.88);
+ backdrop-filter: blur(10px);
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.45s var(--ease-out);
+ text-align: center;
+ z-index: 10;
+}
+
+.overlay.is-on {
+ opacity: 1;
+ pointer-events: auto;
+}
+
+.overlay-kicker {
+ font-family: var(--sans);
+ font-size: 11px;
+ font-weight: 600;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ color: var(--accent-deep);
+ margin-bottom: 16px;
+}
+
+.overlay h1, .overlay h2 {
+ font-family: var(--serif);
+ font-weight: 500;
+ color: var(--ink);
+ letter-spacing: 0.02em;
+ line-height: 1.1;
+}
+
+.overlay h1 {
+ font-size: clamp(36px, 5vw, 50px);
+ margin-bottom: 12px;
+}
+
+.overlay h2 {
+ font-size: clamp(28px, 4vw, 38px);
+ margin-bottom: 12px;
+}
+
+.overlay p {
+ font-size: 15px;
+ color: var(--ink-soft);
+ max-width: 36ch;
+ margin: 0 auto 28px;
+ line-height: 1.6;
+}
+
+.overlay .score-line {
+ font-family: var(--sans);
+ font-size: 12px;
+ font-weight: 600;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 32px;
+}
+
+.overlay .score-line strong {
+ color: var(--ink);
+ font-size: 18px;
+ letter-spacing: 0.08em;
+ display: block;
+ margin-top: 6px;
+ font-variant-numeric: tabular-nums;
+}
+
+.btn {
+ appearance: none;
+ border: 1px solid var(--ink);
+ background: var(--ink);
+ color: var(--bg);
+ font-family: var(--sans);
+ font-size: 12px;
+ font-weight: 600;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ padding: 16px 36px;
+ border-radius: 999px;
+ cursor: pointer;
+ transition: transform 0.35s var(--ease-pop), background 0.25s var(--ease), color 0.25s var(--ease), box-shadow 0.25s var(--ease);
+ box-shadow: var(--shadow-soft);
+}
+
+.btn:hover {
+ background: var(--accent);
+ border-color: var(--accent);
+ color: var(--ink);
+ transform: translateY(-2px);
+}
+
+.btn:active { transform: translateY(0) scale(0.98); }
+
+.hint {
+ margin-top: 28px;
+ font-size: 11px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.swatch-row {
+ display: flex;
+ gap: 10px;
+ justify-content: center;
+ margin-bottom: 28px;
+}
+
+.swatch {
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ border: 1px solid var(--line-strong);
+ box-shadow: var(--shadow-soft);
+}
+
+/* pattern previews via CSS */
+.swatch.damask {
+ background:
+ radial-gradient(circle at 30% 30%, var(--accent) 2px, transparent 2.5px),
+ radial-gradient(circle at 70% 70%, var(--accent) 2px, transparent 2.5px),
+ #2c3a4a;
+}
+.swatch.chinoiserie {
+ background:
+ linear-gradient(135deg, transparent 45%, #c45c4a 45%, #c45c4a 55%, transparent 55%),
+ linear-gradient(45deg, transparent 45%, #c45c4a 45%, #c45c4a 55%, transparent 55%),
+ #f0e6d4;
+}
+.swatch.art-deco {
+ background:
+ repeating-linear-gradient(90deg, #1c1a17 0 3px, transparent 3px 8px),
+ repeating-linear-gradient(0deg, #1c1a17 0 3px, transparent 3px 8px),
+ var(--accent);
+}
+.swatch.toile {
+ background:
+ radial-gradient(ellipse 40% 50% at 50% 50%, transparent 40%, #4a6b5a 41%, #4a6b5a 48%, transparent 49%),
+ #e8dfd0;
+}
+.swatch.geometric {
+ background:
+ conic-gradient(from 45deg, #5c3d6e 0 25%, #d4c4a8 0 50%, #5c3d6e 0 75%, #d4c4a8 0),
+ #5c3d6e;
+ background-size: 12px 12px;
+}
+
+@media (max-width: 640px) {
+ .site-header { padding: 0 16px; height: 64px; }
+ :root { --header-h: 64px; }
+ .wordmark { font-size: 15px; letter-spacing: 0.14em; max-width: 48vw; }
+ .header-meta { gap: 14px; }
+ .stage { padding: 12px; }
+}
+</style>
+</head>
+<body>
+
+<header class="site-header">
+ <div class="wordmark">Designer<br>Wallcoverings</div>
+ <div class="header-meta">
+ <div class="stat">Score <b id="liveScore">0</b></div>
+ <div class="stat">Best <b class="accent" id="liveBest">0</b></div>
+ </div>
+</header>
+
+<main class="stage">
+ <div class="canvas-wrap">
+ <canvas id="game" width="960" height="540"></canvas>
+
+ <div class="overlay is-on" id="startOverlay">
+ <div class="overlay-kicker">An endless atelier run</div>
+ <h1>Paper the Wall</h1>
+ <p>Guide the paint roller. Collect wallpaper rolls — each style a different jewel — and leap the scaffolding.</p>
+ <div class="swatch-row" aria-hidden="true">
+ <div class="swatch damask"></div>
+ <div class="swatch chinoiserie"></div>
+ <div class="swatch art-deco"></div>
+ <div class="swatch toile"></div>
+ <div class="swatch geometric"></div>
+ </div>
+ <button class="btn" id="startBtn" type="button">Begin</button>
+ <div class="hint">Space / tap to jump</div>
+ </div>
+
+ <div class="overlay" id="overOverlay">
+ <div class="overlay-kicker">Session complete</div>
+ <h2>Wall Interrupted</h2>
+ <div class="score-line">Final score <strong id="finalScore">0</strong></div>
+ <button class="btn" id="restartBtn" type="button">Roll Again</button>
+ <div class="hint">Space / tap to restart</div>
+ </div>
+ </div>
+</main>
+
+<script>
+(function () {
+ 'use strict';
+
+ const W = 960, H = 540;
+ const canvas = document.getElementById('game');
+ const ctx = canvas.getContext('2d');
+ const liveScore = document.getElementById('liveScore');
+ const liveBest = document.getElementById('liveBest');
+ const finalScore = document.getElementById('finalScore');
+ const startOverlay = document.getElementById('startOverlay');
+ const overOverlay = document.getElementById('overOverlay');
+ const startBtn = document.getElementById('startBtn');
+ const restartBtn = document.getElementById('restartBtn');
+
+ const BEST_KEY = 'dw_roller_best';
+ let best = parseInt(localStorage.getItem(BEST_KEY) || '0', 10) || 0;
+ liveBest.textContent = String(best);
+
+ // Palette (mirrors CSS tokens)
+ const C = {
+ bg: '#f7f3eb',
+ surface: '#fffcf6',
+ wall: '#ebe4d6',
+ wallDeep: '#e0d6c4',
+ ink: '#1c1a17',
+ inkSoft: '#3a3530',
+ muted: '#8a8276',
+ accent: '#b8952c',
+ accentDeep: '#8a6e1f',
+ cream: '#f5efe3',
+ rollerBody: '#2a2622',
+ rollerMetal: '#c9a961',
+ ground: '#d9cfc0',
+ shadow: 'rgba(28,26,23,0.12)'
+ };
+
+ // Wallpaper style definitions — visually distinct motifs
+ const STYLES = [
+ {
+ name: 'damask',
+ base: '#2c3a4a',
+ ink: '#c9a961',
+ draw(g, s) {
+ g.fillStyle = this.base;
+ g.fillRect(-s, -s, s * 2, s * 2);
+ g.fillStyle = this.ink;
+ // fleur motif
+ for (let i = 0; i < 3; i++) {
+ const a = (i / 3) * Math.PI * 2;
+ g.beginPath();
+ g.ellipse(Math.cos(a) * s * 0.35, Math.sin(a) * s * 0.35, s * 0.18, s * 0.1, a, 0, Math.PI * 2);
+ g.fill();
+ }
+ g.beginPath();
+ g.arc(0, 0, s * 0.12, 0, Math.PI * 2);
+ g.fill();
+ }
+ },
+ {
+ name: 'chinoiserie',
+ base: '#f0e6d4',
+ ink: '#c45c4a',
+ draw(g, s) {
+ g.fillStyle = this.base;
+ g.fillRect(-s, -s, s * 2, s * 2);
+ g.strokeStyle = this.ink;
+ g.lineWidth = 2;
+ // branch + blossom
+ g.beginPath();
+ g.moveTo(-s * 0.6, s * 0.5);
+ g.quadraticCurveTo(-s * 0.1, -s * 0.2, s * 0.5, -s * 0.55);
+ g.stroke();
+ g.fillStyle = this.ink;
+ [[0.1, -0.15], [0.35, -0.4], [-0.2, 0.15]].forEach(([x, y]) => {
+ g.beginPath();
+ g.arc(x * s, y * s, s * 0.14, 0, Math.PI * 2);
+ g.fill();
+ g.fillStyle = this.base;
+ g.beginPath();
+ g.arc(x * s, y * s, s * 0.05, 0, Math.PI * 2);
+ g.fill();
+ g.fillStyle = this.ink;
+ });
+ }
+ },
+ {
+ name: 'artdeco',
+ base: '#1c1a17',
+ ink: '#c9a961',
+ draw(g, s) {
+ g.fillStyle = this.base;
+ g.fillRect(-s, -s, s * 2, s * 2);
+ g.strokeStyle = this.ink;
+ g.lineWidth = 1.5;
+ // sunburst
+ for (let i = 0; i < 8; i++) {
+ const a = (i / 8) * Math.PI - Math.PI / 2;
+ g.beginPath();
+ g.moveTo(0, s * 0.5);
+ g.lineTo(Math.cos(a) * s * 0.85, Math.sin(a) * s * 0.85 + s * 0.15);
+ g.stroke();
+ }
+ g.beginPath();
+ g.arc(0, s * 0.5, s * 0.18, Math.PI, 0);
+ g.stroke();
+ g.strokeRect(-s * 0.7, -s * 0.7, s * 1.4, s * 1.4);
+ }
+ },
+ {
+ name: 'toile',
+ base: '#e8dfd0',
+ ink: '#4a6b5a',
+ draw(g, s) {
+ g.fillStyle = this.base;
+ g.fillRect(-s, -s, s * 2, s * 2);
+ g.strokeStyle = this.ink;
+ g.fillStyle = this.ink;
+ g.lineWidth = 1.5;
+ // pastoral oval scene
+ g.beginPath();
+ g.ellipse(0, 0, s * 0.55, s * 0.7, 0, 0, Math.PI * 2);
+ g.stroke();
+ // little tree
+ g.beginPath();
+ g.moveTo(0, s * 0.35);
+ g.lineTo(0, -s * 0.05);
+ g.stroke();
+ g.beginPath();
+ g.arc(0, -s * 0.2, s * 0.22, 0, Math.PI * 2);
+ g.stroke();
+ // ground line
+ g.beginPath();
+ g.moveTo(-s * 0.4, s * 0.35);
+ g.quadraticCurveTo(0, s * 0.45, s * 0.4, s * 0.35);
+ g.stroke();
+ }
+ },
+ {
+ name: 'geometric',
+ base: '#5c3d6e',
+ ink: '#d4c4a8',
+ draw(g, s) {
+ g.fillStyle = this.base;
+ g.fillRect(-s, -s, s * 2, s * 2);
+ g.fillStyle = this.ink;
+ // tessellated diamonds
+ const drawDia = (x, y, r) => {
+ g.beginPath();
+ g.moveTo(x, y - r);
+ g.lineTo(x + r * 0.7, y);
+ g.lineTo(x, y + r);
+ g.lineTo(x - r * 0.7, y);
+ g.closePath();
+ g.fill();
+ };
+ drawDia(0, 0, s * 0.55);
+ g.fillStyle = this.base;
+ drawDia(0, 0, s * 0.28);
+ g.fillStyle = this.ink;
+ drawDia(-s * 0.55, -s * 0.55, s * 0.22);
+ drawDia(s * 0.55, -s * 0.55, s * 0.22);
+ drawDia(-s * 0.55, s * 0.55, s * 0.22);
+ drawDia(s * 0.55, s * 0.55, s * 0.22);
+ }
+ }
+ ];
+
+ // Game state
+ let running = false;
+ let gameOver = false;
+ let score = 0;
+ let speed = 5.2;
+ const maxSpeed = 14;
+ let distance = 0;
+ let spawnTimer = 0;
+ let decorOffset = 0;
+ let particles = [];
+ let entities = [];
+ let shake = 0;
+ let flash = 0;
+ let wallPaint = []; // painted segments behind roller
+ let raf = 0;
+ let lastT = 0;
+
+ // Player — paint roller
+ const player = {
+ x: 160,
+ y: 0,
+ w: 54,
+ h: 70,
+ vy: 0,
+ onGround: true,
+ rot: 0,
+ jumpCount: 0
+ };
+
+ const GROUND_Y = H - 78;
+ const GRAVITY = 0.72;
+ const JUMP_V = -13.8;
+
+ function resetGame() {
+ score = 0;
+ speed = 5.2;
+ distance = 0;
+ spawnTimer = 40;
+ decorOffset = 0;
+ particles = [];
+ entities = [];
+ shake = 0;
+ flash = 0;
+ wallPaint = [];
+ player.y = GROUND_Y - player.h;
+ player.vy = 0;
+ player.onGround = true;
+ player.rot = 0;
+ player.jumpCount = 0;
+ gameOver = false;
+ liveScore.textContent = '0';
+ // seed a few early collectibles
+ for (let i = 0; i < 3; i++) {
+ spawnCollectible(W + 200 + i * 280);
+ }
+ }
+
+ function spawnCollectible(x) {
+ const style = STYLES[(Math.random() * STYLES.length) | 0];
+ const lane = Math.random() < 0.35 ? 'high' : 'mid';
+ entities.push({
+ type: 'roll',
+ x: x,
+ y: lane === 'high' ? GROUND_Y - 200 : GROUND_Y - 120,
+ r: 22,
+ style,
+ rot: Math.random() * Math.PI * 2,
+ bob: Math.random() * Math.PI * 2,
+ taken: false
+ });
+ }
+
+ function spawnObstacle(x) {
+ const kind = Math.random();
+ if (kind < 0.4) {
+ // low crate / bucket
+ entities.push({
+ type: 'obs',
+ kind: 'crate',
+ x, y: GROUND_Y - 48,
+ w: 44, h: 48
+ });
+ } else if (kind < 0.7) {
+ // tall ladder / scaffolding
+ entities.push({
+ type: 'obs',
+ kind: 'scaffold',
+ x, y: GROUND_Y - 110,
+ w: 36, h: 110
+ });
+ } else {
+ // hanging dropcloth — must duck by timing (it's mid-air low gap... actually it's hanging so jump over low or it's high obstacle)
+ entities.push({
+ type: 'obs',
+ kind: 'hang',
+ x, y: GROUND_Y - 200,
+ w: 50, h: 90
+ });
+ }
+ }
+
+ function jump() {
+ if (!running) return;
+ if (gameOver) return;
+ if (player.jumpCount < 2) {
+ player.vy = JUMP_V * (player.jumpCount === 0 ? 1 : 0.88);
+ player.onGround = false;
+ player.jumpCount++;
+ // dust
+ for (let i = 0; i < 6; i++) {
+ particles.push({
+ x: player.x + player.w * 0.5,
+ y: GROUND_Y - 4,
+ vx: (Math.random() - 0.5) * 3,
+ vy: -Math.random() * 2,
+ life: 1,
+ r: 2 + Math.random() * 3,
+ col: C.muted
+ });
+ }
+ }
+ }
+
+ function endGame() {
+ gameOver = true;
+ running = false;
+ shake = 10;
+ flash = 1;
+ if (score > best) {
+ best = score;
+ localStorage.setItem(BEST_KEY, String(best));
+ liveBest.textContent = String(best);
+ }
+ finalScore.textContent = String(score);
+ overOverlay.classList.add('is-on');
+ }
+
+ function startGame() {
+ startOverlay.classList.remove('is-on');
+ overOverlay.classList.remove('is-on');
+ resetGame();
+ running = true;
+ lastT = performance.now();
+ cancelAnimationFrame(raf);
+ raf = requestAnimationFrame(loop);
+ }
+
+ // Input
+ function onAction(e) {
+ if (e.type === 'keydown' && e.code !== 'Space' && e.key !== ' ') return;
+ if (e.type === 'keydown') e.preventDefault();
+ if (!running && !gameOver && startOverlay.classList.contains('is-on')) {
+ startGame();
+ return;
+ }
+ if (gameOver && overOverlay.classList.contains('is-on')) {
+ startGame();
+ return;
+ }
+ jump();
+ }
+
+ window.addEventListener('keydown', onAction);
+ canvas.addEventListener('pointerdown', onAction);
+ startBtn.addEventListener('click', (e) => { e.stopPropagation(); startGame(); });
+ restartBtn.addEventListener('click', (e) => { e.stopPropagation(); startGame(); });
+
+ // —— Drawing helpers ——
+ function roundRect(x, y, w, h, r) {
+ const rr = Math.min(r, w / 2, h / 2);
+ ctx.beginPath();
+ ctx.moveTo(x + rr, y);
+ ctx.arcTo(x + w, y, x + w, y + h, rr);
+ ctx.arcTo(x + w, y + h, x, y + h, rr);
+ ctx.arcTo(x, y + h, x, y, rr);
+ ctx.arcTo(x, y, x + w, y, rr);
+ ctx.closePath();
+ }
+
+ function drawBackground() {
+ // wall field
+ const g = ctx.createLinearGradient(0, 0, 0, H);
+ g.addColorStop(0, '#f3eee4');
+ g.addColorStop(1, C.wall);
+ ctx.fillStyle = g;
+ ctx.fillRect(0, 0, W, H);
+
+ // subtle vertical paneling lines
+ ctx.strokeStyle = 'rgba(28,26,23,0.04)';
+ ctx.lineWidth = 1;
+ const panelW = 80;
+ const off = -(decorOffset * 0.3) % panelW;
+ for (let x = off; x < W + panelW; x += panelW) {
+ ctx.beginPath();
+ ctx.moveTo(x, 0);
+ ctx.lineTo(x, GROUND_Y);
+ ctx.stroke();
+ }
+
+ // painted trail behind player (collected wallpaper applied)
+ wallPaint.forEach(p => {
+ ctx.save();
+ ctx.globalAlpha = p.a;
+ ctx.translate(p.x, p.y);
+ p.style.draw(ctx, p.s);
+ ctx.restore();
+ });
+
+ // chair rail / dado
+ ctx.fillStyle = C.wallDeep;
+ ctx.fillRect(0, GROUND_Y - 14, W, 6);
+ ctx.fillStyle = 'rgba(28,26,23,0.06)';
+ ctx.fillRect(0, GROUND_Y - 14, W, 1);
+
+ // floor
+ const fg = ctx.createLinearGradient(0, GROUND_Y, 0, H);
+ fg.addColorStop(0, '#d4c9b6');
+ fg.addColorStop(1, '#c4b8a2');
+ ctx.fillStyle = fg;
+ ctx.fillRect(0, GROUND_Y, W, H - GROUND_Y);
+
+ // floor boards
+ ctx.strokeStyle = 'rgba(28,26,23,0.07)';
+ ctx.lineWidth = 1;
+ const board = 48;
+ const bo = -(decorOffset) % board;
+ for (let x = bo; x < W + board; x += board) {
+ ctx.beginPath();
+ ctx.moveTo(x, GROUND_Y);
+ ctx.lineTo(x, H);
+ ctx.stroke();
+ }
+ // floor highlight line
+ ctx.strokeStyle = 'rgba(255,252,246,0.35)';
+ ctx.beginPath();
+ ctx.moveTo(0, GROUND_Y + 1);
+ ctx.lineTo(W, GROUND_Y + 1);
+ ctx.stroke();
+ }
+
+ function drawRoller(p) {
+ const cx = p.x + p.w * 0.5;
+ const cy = p.y + p.h * 0.55;
+ ctx.save();
+ ctx.translate(cx, cy);
+ // soft contact shadow
+ ctx.fillStyle = 'rgba(28,26,23,0.12)';
+ ctx.beginPath();
+ ctx.ellipse(0, p.h * 0.45 + (p.onGround ? 0 : 4), 22, 6, 0, 0, Math.PI * 2);
+ ctx.fill();
+
+ ctx.rotate(p.rot);
+
+ // handle shaft
+ ctx.strokeStyle = C.rollerMetal;
+ ctx.lineWidth = 4;
+ ctx.lineCap = 'round';
+ ctx.beginPath();
+ ctx.moveTo(0, -8);
+ ctx.lineTo(0, -38);
+ ctx.stroke();
+
+ // handle grip
+ ctx.fillStyle = C.ink;
+ roundRect(-5, -52, 10, 18, 3);
+ ctx.fill();
+ // gold ferrule
+ ctx.fillStyle = C.accent;
+ roundRect(-6, -36, 12, 5, 1);
+ ctx.fill();
+
+ // roller frame
+ ctx.strokeStyle = C.rollerMetal;
+ ctx.lineWidth = 3;
+ ctx.beginPath();
+ ctx.moveTo(-22, -8);
+ ctx.lineTo(22, -8);
+ ctx.stroke();
+ ctx.beginPath();
+ ctx.moveTo(-22, -8);
+ ctx.lineTo(-22, 8);
+ ctx.moveTo(22, -8);
+ ctx.lineTo(22, 8);
+ ctx.stroke();
+
+ // nap cylinder
+ const rg = ctx.createLinearGradient(-22, 0, 22, 0);
+ rg.addColorStop(0, '#3d3832');
+ rg.addColorStop(0.5, '#5a534a');
+ rg.addColorStop(1, '#3d3832');
+ ctx.fillStyle = rg;
+ roundRect(-24, 4, 48, 28, 10);
+ ctx.fill();
+ // nap texture lines
+ ctx.strokeStyle = 'rgba(245,242,234,0.08)';
+ ctx.lineWidth = 1;
+ for (let i = -18; i <= 18; i += 6) {
+ ctx.beginPath();
+ ctx.moveTo(i, 8);
+ ctx.lineTo(i, 28);
+ ctx.stroke();
+ }
+ // gold end caps
+ ctx.fillStyle = C.accent;
+ ctx.beginPath();
+ ctx.arc(-24, 18, 7, 0, Math.PI * 2);
+ ctx.arc(24, 18, 7, 0, Math.PI * 2);
+ ctx.fill();
+ ctx.fillStyle = C.accentDeep;
+ ctx.beginPath();
+ ctx.arc(-24, 18, 3, 0, Math.PI * 2);
+ ctx.arc(24, 18, 3, 0, Math.PI * 2);
+ ctx.fill();
+
+ // paint drip accent
+ ctx.fillStyle = C.accent;
+ ctx.globalAlpha = 0.85;
+ ctx.beginPath();
+ ctx.ellipse(8, 34, 4, 6, 0, 0, Math.PI * 2);
+ ctx.fill();
+ ctx.globalAlpha = 1;
+
+ ctx.restore();
+ }
+
+ function drawEntity(e, t) {
+ if (e.type === 'roll') {
+ const bob = Math.sin(t * 0.004 + e.bob) * 5;
+ const x = e.x;
+ const y = e.y + bob;
+ ctx.save();
+ // glow
+ ctx.shadowColor = 'rgba(184,149,44,0.35)';
+ ctx.shadowBlur = 16;
+ ctx.translate(x, y);
+ ctx.rotate(e.rot);
+ // outer ring (tube)
+ ctx.fillStyle = e.style.base;
+ ctx.beginPath();
+ ctx.arc(0, 0, e.r + 4, 0, Math.PI * 2);
+ ctx.fill();
+ // pattern face
+ ctx.save();
+ ctx.beginPath();
+ ctx.arc(0, 0, e.r, 0, Math.PI * 2);
+ ctx.clip();
+ e.style.draw(ctx, e.r);
+ ctx.restore();
+ // cardboard tube hole
+ ctx.fillStyle = '#c4b49a';
+ ctx.beginPath();
+ ctx.arc(0, 0, 5, 0, Math.PI * 2);
+ ctx.fill();
+ ctx.strokeStyle = 'rgba(28,26,23,0.25)';
+ ctx.lineWidth = 1;
+ ctx.beginPath();
+ ctx.arc(0, 0, e.r + 4, 0, Math.PI * 2);
+ ctx.stroke();
+ // rim highlight
+ ctx.strokeStyle = 'rgba(255,252,246,0.35)';
+ ctx.beginPath();
+ ctx.arc(0, 0, e.r + 2, -Math.PI * 0.8, -Math.PI * 0.2);
+ ctx.stroke();
+ ctx.restore();
+ } else if (e.type === 'obs') {
+ ctx.save();
+ if (e.kind === 'crate') {
+ // paint bucket
+ ctx.fillStyle = C.shadow;
+ ctx.beginPath();
+ ctx.ellipse(e.x + e.w / 2, GROUND_Y - 2, e.w * 0.45, 5, 0, 0, Math.PI * 2);
+ ctx.fill();
+ // body
+ const bg = ctx.createLinearGradient(e.x, e.y, e.x + e.w, e.y);
+ bg.addColorStop(0, '#5a534a');
+ bg.addColorStop(0.5, '#7a7268');
+ bg.addColorStop(1, '#4a443c');
+ ctx.fillStyle = bg;
+ roundRect(e.x + 4, e.y + 8, e.w - 8, e.h - 8, 4);
+ ctx.fill();
+ // lid
+ ctx.fillStyle = C.accent;
+ roundRect(e.x, e.y + 4, e.w, 10, 3);
+ ctx.fill();
+ ctx.fillStyle = C.accentDeep;
+ roundRect(e.x + 14, e.y, e.w - 28, 8, 2);
+ ctx.fill();
+ // label band
+ ctx.fillStyle = C.cream;
+ ctx.fillRect(e.x + 8, e.y + 22, e.w - 16, 14);
+ ctx.strokeStyle = C.ink;
+ ctx.lineWidth = 1;
+ ctx.strokeRect(e.x + 8, e.y + 22, e.w - 16, 14);
+ } else if (e.kind === 'scaffold') {
+ ctx.fillStyle = C.shadow;
+ ctx.beginPath();
+ ctx.ellipse(e.x + e.w / 2, GROUND_Y - 2, e.w * 0.55, 5, 0, 0, Math.PI * 2);
+ ctx.fill();
+ ctx.strokeStyle = C.inkSoft;
+ ctx.lineWidth = 4;
+ ctx.lineCap = 'round';
+ // uprights
+ ctx.beginPath();
+ ctx.moveTo(e.x + 6, e.y + e.h);
+ ctx.lineTo(e.x + 6, e.y);
+ ctx.moveTo(e.x + e.w - 6, e.y + e.h);
+ ctx.lineTo(e.x + e.w - 6, e.y);
+ ctx.stroke();
+ // rungs
+ ctx.lineWidth = 3;
+ ctx.strokeStyle = C.muted;
+ for (let ry = e.y + 16; ry < e.y + e.h; ry += 22) {
+ ctx.beginPath();
+ ctx.moveTo(e.x + 6, ry);
+ ctx.lineTo(e.x + e.w - 6, ry);
+ ctx.stroke();
+ }
+ // warning tape top
+ ctx.fillStyle = C.accent;
+ ctx.fillRect(e.x, e.y, e.w, 6);
+ ctx.fillStyle = C.ink;
+ for (let tx = e.x; tx < e.x + e.w; tx += 10) {
+ ctx.fillRect(tx, e.y, 5, 6);
+ }
+ } else if (e.kind === 'hang') {
+ // hanging drop cloth / chandelier obstacle
+ ctx.strokeStyle = C.muted;
+ ctx.lineWidth = 1.5;
+ ctx.setLineDash([3, 4]);
+ ctx.beginPath();
+ ctx.moveTo(e.x + e.w / 2, 0);
+ ctx.lineTo(e.x + e.w / 2, e.y);
+ ctx.stroke();
+ ctx.setLineDash([]);
+ // cloth
+ const cg = ctx.createLinearGradient(e.x, e.y, e.x, e.y + e.h);
+ cg.addColorStop(0, '#f5efe3');
+ cg.addColorStop(1, '#d9cfc0');
+ ctx.fillStyle = cg;
+ ctx.beginPath();
+ ctx.moveTo(e.x, e.y);
+ ctx.lineTo(e.x + e.w, e.y);
+ ctx.quadraticCurveTo(e.x + e.w + 4, e.y + e.h * 0.5, e.x + e.w - 6, e.y + e.h);
+ ctx.lineTo(e.x + 6, e.y + e.h);
+ ctx.quadraticCurveTo(e.x - 4, e.y + e.h * 0.5, e.x, e.y);
+ ctx.fill();
+ ctx.strokeStyle = 'rgba(28,26,23,0.15)';
+ ctx.stroke();
+ // pattern dots on cloth
+ ctx.fillStyle = 'rgba(184,149,44,0.35)';
+ for (let i = 0; i < 5; i++) {
+ ctx.beginPath();
+ ctx.arc(e.x + 12 + (i % 3) * 12, e.y + 20 + Math.floor(i / 3) * 28, 3, 0, Math.PI * 2);
+ ctx.fill();
+ }
+ }
+ ctx.restore();
+ }
+ }
+
+ function drawParticles() {
+ particles.forEach(p => {
+ ctx.globalAlpha = Math.max(0, p.life);
+ ctx.fillStyle = p.col;
+ ctx.beginPath();
+ ctx.arc(p.x, p.y, p.r * p.life, 0, Math.PI * 2);
+ ctx.fill();
+ });
+ ctx.globalAlpha = 1;
+ }
+
+ function drawHUD() {
+ // subtle speed ticks at bottom of canvas
+ ctx.fillStyle = 'rgba(28,26,23,0.05)';
+ ctx.fillRect(0, H - 3, W, 3);
+ ctx.fillStyle = C.accent;
+ const pct = (speed - 5.2) / (maxSpeed - 5.2);
+ ctx.fillRect(0, H - 3, W * Math.min(1, pct), 3);
+ }
+
+ // —— Update ——
+ function update(dt) {
+ if (!running || gameOver) return;
+ const tscale = Math.min(dt, 32) / 16.67; // normalize to ~60fps steps
+
+ distance += speed * tscale;
+ decorOffset += speed * tscale;
+
+ // accelerate gently
+ speed = Math.min(maxSpeed, speed + 0.0018 * tscale);
+
+ // player physics
+ player.vy += GRAVITY * tscale;
+ player.y += player.vy * tscale;
+ if (player.y >= GROUND_Y - player.h) {
+ player.y = GROUND_Y - player.h;
+ player.vy = 0;
+ player.onGround = true;
+ player.jumpCount = 0;
+ }
+ player.rot += (speed * 0.06) * tscale;
+
+ // spawn
+ spawnTimer -= tscale;
+ if (spawnTimer <= 0) {
+ const gap = Math.max(70, 140 - speed * 4);
+ if (Math.random() < 0.62) {
+ spawnCollectible(W + 40);
+ } else {
+ spawnObstacle(W + 40);
+ // sometimes a collectible after obstacle
+ if (Math.random() < 0.5) spawnCollectible(W + 40 + 140);
+ }
+ spawnTimer = gap + Math.random() * 40;
+ }
+
+ // entities
+ const px = player.x + 8;
+ const py = player.y + 10;
+ const pw = player.w - 16;
+ const ph = player.h - 18;
+
+ for (let i = entities.length - 1; i >= 0; i--) {
+ const e = entities[i];
+ e.x -= speed * tscale;
+ if (e.type === 'roll') e.rot += 0.04 * tscale;
+
+ if (e.x < -80) {
+ entities.splice(i, 1);
+ continue;
+ }
+
+ if (e.type === 'roll' && !e.taken) {
+ const dx = e.x - (player.x + player.w * 0.5);
+ const dy = e.y - (player.y + player.h * 0.5);
+ if (dx * dx + dy * dy < (e.r + 28) * (e.r + 28)) {
+ e.taken = true;
+ score += 10;
+ liveScore.textContent = String(score);
+ // paint splash on wall
+ wallPaint.push({
+ x: player.x - 20,
+ y: 80 + Math.random() * (GROUND_Y - 160),
+ s: 28 + Math.random() * 18,
+ style: e.style,
+ a: 0.55,
+ life: 1
+ });
+ if (wallPaint.length > 18) wallPaint.shift();
+ // sparkles
+ for (let k = 0; k < 10; k++) {
+ particles.push({
+ x: e.x, y: e.y,
+ vx: (Math.random() - 0.5) * 6,
+ vy: (Math.random() - 0.5) * 6 - 2,
+ life: 1,
+ r: 2 + Math.random() * 3,
+ col: Math.random() < 0.5 ? C.accent : e.style.ink
+ });
+ }
+ entities.splice(i, 1);
+ // micro score float
+ particles.push({
+ x: e.x, y: e.y - 10,
+ vx: 0, vy: -1.2,
+ life: 1, r: 0,
+ col: C.accent,
+ text: '+10'
+ });
+ }
+ } else if (e.type === 'obs') {
+ // AABB
+ let ox = e.x, oy = e.y, ow = e.w, oh = e.h;
+ if (e.kind === 'crate') { ox += 6; ow -= 12; oy += 8; oh -= 8; }
+ if (e.kind === 'scaffold') { ox += 4; ow -= 8; }
+ if (e.kind === 'hang') { ox += 6; ow -= 12; oy += 4; oh -= 10; }
+ if (px < ox + ow && px + pw > ox && py < oy + oh && py + ph > oy) {
+ endGame();
+ }
+ }
+ }
+
+ // particles
+ for (let i = particles.length - 1; i >= 0; i--) {
+ const p = particles[i];
+ p.x += p.vx * tscale;
+ p.y += p.vy * tscale;
+ p.vy += 0.05 * tscale;
+ p.life -= 0.03 * tscale;
+ if (p.life <= 0) particles.splice(i, 1);
+ }
+
+ // wall paint fade drift
+ wallPaint.forEach(p => {
+ p.x -= speed * 0.35 * tscale;
+ p.a *= 0.999;
+ });
+ wallPaint = wallPaint.filter(p => p.x > -80 && p.a > 0.05);
+
+ // passive score for distance
+ if (Math.floor(distance) % 40 < speed * tscale) {
+ // occasional tick
+ }
+ // score by distance
+ const distScore = Math.floor(distance / 50);
+ const collectPart = score; // already includes collects; keep simple
+ // actually keep score as collect-based + distance
+ // We'll add distance points separately via a base
+ }
+
+ // distance scoring — track last awarded
+ let lastDistAward = 0;
+
+ function updateScoreFromDist() {
+ const award = Math.floor(distance / 80);
+ if (award > lastDistAward) {
+ score += (award - lastDistAward);
+ lastDistAward = award;
+ liveScore.textContent = String(score);
+ }
+ }
+
+ function loop(now) {
+ const dt = now - lastT || 16;
+ lastT = now;
+
+ if (running && !gameOver) {
+ update(dt);
+ updateScoreFromDist();
+ }
+
+ if (shake > 0) shake *= 0.88;
+ if (flash > 0) flash *= 0.9;
+
+ // draw
+ ctx.save();
+ if (shake > 0.4) {
+ ctx.translate((Math.random() - 0.5) * shake, (Math.random() - 0.5) * shake);
+ }
+
+ drawBackground();
+
+ // entities behind player-ish
+ const t = now;
+ entities.forEach(e => drawEntity(e, t));
+ drawRoller(player);
+ drawParticles();
+
+ // floating +10 texts
+ particles.forEach(p => {
+ if (p.text) {
+ ctx.globalAlpha = Math.max(0, p.life);
+ ctx.fillStyle = C.accentDeep;
+ ctx.font = '600 14px "Avenir Next", "Helvetica Neue", sans-serif';
+ ctx.letterSpacing = '0.1em';
+ ctx.fillText(p.text, p.x - 12, p.y);
+ ctx.globalAlpha = 1;
+ }
+ });
+
+ drawHUD();
+
+ if (flash > 0.05) {
+ ctx.fillStyle = `rgba(28,26,23,${flash * 0.25})`;
+ ctx.fillRect(0, 0, W, H);
+ }
+
+ ctx.restore();
+
+ raf = requestAnimationFrame(loop);
+ }
+
+ // Idle preview render
+ function idleDraw() {
+ resetGame();
+ lastDistAward = 0;
+ drawBackground();
+ // decorative rolls on start screen
+ STYLES.forEach((s, i) => {
+ const e = {
+ type: 'roll', x: 220 + i * 130, y: GROUND_Y - 130 - (i % 2) * 30,
+ r: 22, style: s, rot: i * 0.4, bob: i, taken: false
+ };
+ drawEntity(e, performance.now());
+ });
+ player.y = GROUND_Y - player.h;
+ drawRoller(player);
+ }
+
+ idleDraw();
+ // keep a gentle idle animation under the start overlay
+ function idleLoop(now) {
+ if (running) return;
+ lastT = now;
+ decorOffset += 0.6;
+ // drift sample entities
+ ctx.clearRect(0, 0, W, H);
+ drawBackground();
+ STYLES.forEach((s, i) => {
+ const e = {
+ type: 'roll',
+ x: 220 + i * 130,
+ y: GROUND_Y - 130 - (i % 2) * 30,
+ r: 22, style: s,
+ rot: now * 0.001 + i,
+ bob: i * 1.3,
+ taken: false
+ };
+ drawEntity(e, now);
+ });
+ player.rot = now * 0.002;
+ player.y = GROUND_Y - player.h;
+ drawRoller(player);
+ raf = requestAnimationFrame(idleLoop);
+ }
+ raf = requestAnimationFrame(idleLoop);
+
+ // fix reset to also reset distance award
+ const _reset = resetGame;
+ resetGame = function () {
+ _reset();
+ lastDistAward = 0;
+ };
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/57af693363f2/grok.png b/data/artifacts/57af693363f2/grok.png
new file mode 100644
index 0000000..3414cde
Binary files /dev/null and b/data/artifacts/57af693363f2/grok.png differ
diff --git a/data/artifacts/57af693363f2/qwen25-7b.html b/data/artifacts/57af693363f2/qwen25-7b.html
new file mode 100644
index 0000000..991ae3c
--- /dev/null
+++ b/data/artifacts/57af693363f2/qwen25-7b.html
@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Endless Runner</title>
+<style>
+:root {
+ --bg: #0d0d0f;
+ --surface: #17171c;
+ --text: #f5f2ea;
+ --muted: #8a8578;
+ --accent: #c9a961;
+ --line: 1px solid var(--text);
+ --shadow: 0 8px 24px rgba(0,0,0,.12), hover 0 16px 48px rgba(0,0,0,.18);
+ --ease: cubic-bezier(.22,1,.36,1) both;
+}
+
+body {
+ margin: 0;
+ padding: 0;
+ background-color: var(--bg);
+ color: var(--text);
+ font-family: 'Didot', Georgia, serif;
+ overflow-x: hidden;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+}
+
+header {
+ position: fixed;
+ top: 24px;
+ left: 24px;
+ width: calc(100% - 48px);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 8px 0;
+ background-color: var(--surface);
+ border-bottom: var(--line);
+}
+
+.wordmark {
+ font-size: 52px;
+ letter-spacing: .18em;
+ text-transform: uppercase;
+}
+
+.scoreboard {
+ font-size: 16px;
+ letter-spacing: .15em;
+ text-transform: uppercase;
+ margin-left: 40px;
+}
+
+canvas {
+ position: absolute;
+ top: 120px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 80vw;
+ height: 60vh;
+ background-color: var(--surface);
+}
+</style>
+</head>
+<body>
+
+<header>
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ <div class="scoreboard" id="scoreboard">Score: 0 | Best: 0</div>
+</header>
+
+<canvas id="gameCanvas"></canvas>
+
+<script>
+document.addEventListener("DOMContentLoaded", () => {
+ const canvas = document.getElementById('gameCanvas');
+ const ctx = canvas.getContext('2d');
+
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight - 120;
+
+ let score = localStorage.getItem('score') || 0;
+ const scoreboard = document.getElementById('scoreboard');
+ scoreboard.textContent = `Score: ${score} | Best: ${score}`;
+
+ function drawBackground() {
+ ctx.fillStyle = 'var(--surface)';
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
+ }
+
+ function drawWordmark(x, y) {
+ ctx.font = "52px Didot";
+ ctx.textAlign = "left";
+ ctx.fillStyle = 'var(--text)';
+ ctx.fillText("DESIGNER WALLCOVERINGS", x, y);
+ }
+
+ function drawRoller(rollerX, rollerY, rollerW, rollerH) {
+ ctx.fillStyle = 'var(--accent)';
+ ctx.fillRect(rollerX, rollerY, rollerW, rollerH);
+ }
+
+ function drawObstacle(obstacleX, obstacleY, obstacleW, obstacleH) {
+ ctx.fillStyle = 'rgba(255, 69, 134, 0.7)';
+ ctx.fillRect(obstacleX, obstacleY, obstacleW, obstacleH);
+ }
+
+ function drawWallpaper(wallpaperX, wallpaperY, wallpaperW, wallpaperH) {
+ ctx.beginPath();
+ ctx.moveTo(wallpaperX, wallpaperY);
+ ctx.lineTo(wallpaperX + wallpaperW, wallpaperY);
+ ctx.quadraticCurveTo(wallpaperX + wallpaperW / 2, wallpaperY - 10, wallpaperX + wallpaperW, wallpaperY);
+ ctx.closePath();
+ ctx.fillStyle = 'rgba(255, 69, 134, 0.7)';
+ ctx.fill();
+ }
+
+ function gameLoop() {
+ drawBackground();
+ drawWordmark(20, 80);
+
+ // Roller
+ let rollerX = canvas.width / 2 - 50;
+ let rollerY = canvas.height - 100;
+ let rollerW = 100;
+ let rollerH = 50;
+
+ drawRoller(rollerX, rollerY, rollerW, rollerH);
+
+ // Obstacles
+ const obstacleX = Math.random() * (canvas.width - 200) + 100;
+ const obstacleY = canvas.height / 3;
+ const obstacleW = 50;
+ const obstacleH = 50;
+
+ drawObstacle(obstacleX, obstacleY, obstacleW, obstacleH);
+
+ // Wallpaper
+ const wallpaperX = Math.random() * (canvas.width - 200) + 100;
+ const wallpaperY = canvas.height / 3 - 50;
+ const wallpaperW = 200;
+ const wallpaperH = 100;
+
+ drawWallpaper(wallpaperX, wallpaperY, wallpaperW, wallpaperH);
+
+ requestAnimationFrame(gameLoop);
+ }
+
+ gameLoop();
+});
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/57af693363f2/qwen25-7b.png b/data/artifacts/57af693363f2/qwen25-7b.png
new file mode 100644
index 0000000..50f3928
Binary files /dev/null and b/data/artifacts/57af693363f2/qwen25-7b.png differ
diff --git a/data/artifacts/57af693363f2/qwen3-14b.html b/data/artifacts/57af693363f2/qwen3-14b.html
new file mode 100644
index 0000000..42d50fb
--- /dev/null
+++ b/data/artifacts/57af693363f2/qwen3-14b.html
@@ -0,0 +1,380 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>Designer Wallcoverings - Endless Runner</title>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #1c1a17;
+ --muted: #9b948a;
+ --accent: #b0472e;
+ --line: #eaeaea;
+ --shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+ --ease: cubic-bezier(0.22, 1, 0.36, 1);
+ }
+
+ * {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ }
+
+ body {
+ background: var(--bg);
+ color: var(--text);
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ font-size: 16px;
+ line-height: 1.6;
+ display: flex;
+ flex-direction: column;
+ height: 100vh;
+ overflow: hidden;
+ }
+
+ header {
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 48px;
+ letter-spacing: 0.18em;
+ line-height: 1;
+ color: var(--text);
+ padding: 16px 24px;
+ background: var(--surface);
+ box-shadow: var(--shadow);
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 1000;
+ display: flex;
+ align-items: center;
+ justify-content: flex-start;
+ text-transform: uppercase;
+ }
+
+ main {
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+ }
+
+ canvas {
+ display: block;
+ width: 100%;
+ height: 100%;
+ }
+
+ .overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.7);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--text);
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ font-size: 24px;
+ text-transform: uppercase;
+ letter-spacing: 0.15em;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.3s var(--ease);
+ }
+
+ .overlay.visible {
+ opacity: 1;
+ pointer-events: auto;
+ }
+
+ .scoreboard {
+ position: fixed;
+ top: 24px;
+ right: 24px;
+ background: var(--surface);
+ padding: 8px 16px;
+ border: 1px solid var(--line);
+ border-radius: 14px;
+ box-shadow: var(--shadow);
+ font-size: 16px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ }
+
+ .scoreboard span {
+ font-size: 14px;
+ font-weight: bold;
+ }
+
+ .restart-button {
+ margin-top: 16px;
+ padding: 8px 16px;
+ background: var(--accent);
+ color: var(--surface);
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ text-transform: uppercase;
+ letter-spacing: 0.15em;
+ font-size: 14px;
+ transition: background 0.2s var(--ease);
+ }
+
+ .restart-button:hover {
+ background: #d03f26;
+ }
+ </style>
+</head>
+<body>
+ <header>DESIGNER WALLCOVERINGS</header>
+ <main>
+ <canvas id="gameCanvas"></canvas>
+ </main>
+ <div class="overlay" id="gameOverOverlay">
+ <div>
+ <div>GAME OVER</div>
+ <div id="finalScore">SCORE: 0</div>
+ <div id="bestScore">BEST: 0</div>
+ <button class="restart-button" onclick="restartGame()">RESTART</button>
+ </div>
+ </div>
+ <div class="scoreboard" id="scoreboard">
+ <span id="score">SCORE: 0</span>
+ <span id="best">BEST: 0</span>
+ </div>
+
+ <script>
+ const canvas = document.getElementById('gameCanvas');
+ const ctx = canvas.getContext('2d');
+ const gameOverOverlay = document.getElementById('gameOverOverlay');
+ const finalScore = document.getElementById('finalScore');
+ const bestScore = document.getElementById('bestScore');
+ const scoreDisplay = document.getElementById('score');
+ const bestDisplay = document.getElementById('best');
+
+ let score = 0;
+ let best = 0;
+ let gameOver = false;
+ let lastTime = 0;
+ let gravity = 0.5;
+ let velocityY = 0;
+ let positionY = 0;
+ let jumpStrength = -12;
+ let isJumping = false;
+ let lastJump = 0;
+ let jumpCooldown = 200;
+ let groundHeight = 100;
+ let speed = 3;
+
+ const obstacles = [];
+ const wallpaperRolls = [];
+
+ function resizeCanvas() {
+ canvas.width = window.innerWidth;
+ canvas.height = window.innerHeight;
+ }
+
+ window.addEventListener('resize', resizeCanvas);
+ resizeCanvas();
+
+ function drawWallpaper(x, y, color) {
+ ctx.fillStyle = color;
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x + 40, y);
+ ctx.lineTo(x + 40, y + 40);
+ ctx.lineTo(x, y + 40);
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ function drawObstacle(x, y, color) {
+ ctx.fillStyle = color;
+ ctx.beginPath();
+ ctx.moveTo(x, y);
+ ctx.lineTo(x + 30, y);
+ ctx.lineTo(x + 30, y + 40);
+ ctx.lineTo(x, y + 40);
+ ctx.closePath();
+ ctx.fill();
+ }
+
+ function drawPlayer(x, y) {
+ ctx.fillStyle = '#b0472e';
+ ctx.beginPath();
+ ctx.arc(x, y, 20, 0, Math.PI * 2);
+ ctx.fill();
+ }
+
+ function drawGround() {
+ ctx.fillStyle = '#eaeaea';
+ ctx.fillRect(0, canvas.height - groundHeight, canvas.width, groundHeight);
+ }
+
+ function update(deltaTime) {
+ if (gameOver) return;
+
+ velocityY += gravity * deltaTime;
+ positionY += velocityY * deltaTime;
+
+ if (positionY > canvas.height - groundHeight - 20) {
+ positionY = canvas.height - groundHeight - 20;
+ velocityY = 0;
+ isJumping = false;
+ }
+
+ // Move obstacles
+ for (let i = 0; i < obstacles.length; i++) {
+ obstacles[i].x -= speed * deltaTime;
+ if (obstacles[i].x + 30 < 0) {
+ obstacles.splice(i, 1);
+ i--;
+ }
+ }
+
+ // Move wallpaper rolls
+ for (let i = 0; i < wallpaperRolls.length; i++) {
+ wallpaperRolls[i].x -= speed * deltaTime;
+ if (wallpaperRolls[i].x + 40 < 0) {
+ wallpaperRolls.splice(i, 1);
+ i--;
+ }
+ }
+
+ // Check collision with obstacles
+ for (let obstacle of obstacles) {
+ if (
+ positionY + 20 > obstacle.y &&
+ positionY - 20 < obstacle.y + 40 &&
+ positionX + 20 > obstacle.x &&
+ positionX - 20 < obstacle.x + 30
+ ) {
+ gameOver = true;
+ showGameOver();
+ }
+ }
+
+ // Check collision with wallpaper rolls
+ for (let roll of wallpaperRolls) {
+ if (
+ positionY + 20 > roll.y &&
+ positionY - 20 < roll.y + 40 &&
+ positionX + 20 > roll.x &&
+ positionX - 20 < roll.x + 40
+ ) {
+ score += 10;
+ wallpaperRolls.splice(wallpaperRolls.indexOf(roll), 1);
+ updateScore();
+ }
+ }
+ }
+
+ function draw() {
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ drawGround();
+ drawPlayer(canvas.width / 2, positionY);
+ for (let obstacle of obstacles) {
+ drawObstacle(obstacle.x, obstacle.y, '#333');
+ }
+ for (let roll of wallpaperRolls) {
+ drawWallpaper(roll.x, roll.y, roll.color);
+ }
+ }
+
+ function spawnObstacle() {
+ const x = canvas.width + 30;
+ const y = Math.random() * (canvas.height - groundHeight - 40);
+ obstacles.push({ x, y });
+ }
+
+ function spawnWallpaperRoll() {
+ const x = canvas.width + 40;
+ const y = Math.random() * (canvas.height - groundHeight - 40);
+ const color = ['#c65f38', '#e0a458', '#d03f26', '#8a8578', '#7d6a45'][Math.floor(Math.random() * 5)];
+ wallpaperRolls.push({ x, y, color });
+ }
+
+ function gameLoop(timestamp) {
+ if (!lastTime) lastTime = timestamp;
+ const deltaTime = timestamp - lastTime;
+ lastTime = timestamp;
+
+ update(deltaTime);
+ draw();
+
+ if (timestamp % 1000 === 0) {
+ spawnObstacle();
+ spawnWallpaperRoll();
+ }
+
+ if (!gameOver) {
+ requestAnimationFrame(gameLoop);
+ }
+ }
+
+ function showGameOver() {
+ gameOverOverlay.classList.add('visible');
+ finalScore.textContent = `SCORE: ${score}`;
+ bestScore.textContent = `BEST: ${best}`;
+ }
+
+ function updateScore() {
+ scoreDisplay.textContent = `SCORE: ${score}`;
+ if (score > best) {
+ best = score;
+ bestDisplay.textContent = `BEST: ${best}`;
+ }
+ localStorage.setItem('bestScore', best);
+ }
+
+ function restartGame() {
+ gameOver = false;
+ gameOverOverlay.classList.remove('visible');
+ score = 0;
+ updateScore();
+ positionY = canvas.height - groundHeight - 20;
+ velocityY = 0;
+ isJumping = false;
+ obstacles.length = 0;
+ wallpaperRolls.length = 0;
+ lastTime = 0;
+ gameLoop(performance.now());
+ }
+
+ document.addEventListener('keydown', (e) => {
+ if (e.code === 'Space' || e.code === 'ArrowUp') {
+ if (!isJumping && !gameOver) {
+ velocityY = jumpStrength;
+ isJumping = true;
+ lastJump = performance.now();
+ }
+ }
+ });
+
+ document.addEventListener('touchstart', (e) => {
+ if (!isJumping && !gameOver) {
+ velocityY = jumpStrength;
+ isJumping = true;
+ lastJump = performance.now();
+ }
+ });
+
+ // Load best score from localStorage
+ const savedBest = localStorage.getItem('bestScore');
+ if (savedBest) {
+ best = parseInt(savedBest);
+ bestDisplay.textContent = `BEST: ${best}`;
+ }
+
+ // Start game loop
+ gameLoop(performance.now());
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/57af693363f2/qwen3-14b.png b/data/artifacts/57af693363f2/qwen3-14b.png
new file mode 100644
index 0000000..64b8da4
Binary files /dev/null and b/data/artifacts/57af693363f2/qwen3-14b.png differ
diff --git a/data/artifacts/70eea6613a73/claude-code.html b/data/artifacts/70eea6613a73/claude-code.html
new file mode 100644
index 0000000..1045f95
--- /dev/null
+++ b/data/artifacts/70eea6613a73/claude-code.html
@@ -0,0 +1,521 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Designer Wallcoverings — Style Lookbook</title>
+<style>
+ :root{
+ --bg:#faf8f4;
+ --surface:#ffffff;
+ --ink:#1c1a17;
+ --text:#1c1a17;
+ --muted:#9b948a;
+ --accent:#b0472e;
+ --accent-2:#2f4c39;
+ --line:rgba(28,26,23,.12);
+ --shadow:0 8px 24px rgba(28,26,23,.10);
+ --shadow-hover:0 16px 48px rgba(28,26,23,.16);
+ --ease:cubic-bezier(.22,1,.36,1);
+ --serif:'Didot','Bodoni MT','Playfair Display',Georgia,serif;
+ --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+ }
+ *{box-sizing:border-box;margin:0;padding:0;}
+ html,body{height:100%;}
+ body{
+ background:var(--bg);
+ color:var(--text);
+ font-family:var(--sans);
+ -webkit-font-smoothing:antialiased;
+ display:flex;
+ flex-direction:column;
+ min-height:100vh;
+ }
+
+ /* ---------- HEADER / WORDMARK ---------- */
+ header.topbar{
+ position:sticky;top:0;z-index:40;
+ background:rgba(250,248,244,.92);
+ backdrop-filter:blur(10px);
+ border-bottom:1px solid var(--line);
+ display:flex;align-items:center;justify-content:space-between;
+ padding:18px 28px;
+ gap:20px;
+ }
+ .wordmark{
+ font-family:var(--serif);
+ color:var(--ink);
+ text-transform:uppercase;
+ letter-spacing:.18em;
+ line-height:1.02;
+ font-weight:600;
+ font-size:clamp(20px,3.4vw,30px);
+ white-space:normal;
+ max-width:280px;
+ }
+ .wordmark .l2{display:block;font-size:.9em;letter-spacing:.20em;}
+ .header-tag{
+ font-family:var(--sans);
+ font-size:11px;
+ text-transform:uppercase;
+ letter-spacing:.15em;
+ color:var(--muted);
+ text-align:right;
+ line-height:1.5;
+ }
+
+ /* ---------- STAGE ---------- */
+ .stage-wrap{
+ flex:1;
+ display:flex;
+ flex-direction:column;
+ align-items:center;
+ justify-content:center;
+ padding:32px 16px 12px;
+ }
+ .frame{
+ width:100%;
+ max-width:440px;
+ aspect-ratio:4/5;
+ background:var(--surface);
+ border:1px solid var(--line);
+ border-radius:14px;
+ box-shadow:var(--shadow);
+ overflow:hidden;
+ position:relative;
+ }
+ .track{
+ display:flex;
+ height:100%;
+ width:100%;
+ transition:transform .7s var(--ease);
+ }
+ .slide{
+ min-width:100%;
+ height:100%;
+ position:relative;
+ overflow:hidden;
+ display:flex;
+ flex-direction:column;
+ }
+
+ /* ---------- COVER SLIDE ---------- */
+ .cover{
+ background:
+ radial-gradient(120% 80% at 50% 0%, rgba(176,71,46,.06), transparent 60%),
+ var(--surface);
+ align-items:center;
+ justify-content:center;
+ text-align:center;
+ padding:44px 34px;
+ }
+ .cover .kicker{
+ font-size:11px;letter-spacing:.28em;text-transform:uppercase;
+ color:var(--muted);margin-bottom:22px;
+ }
+ .cover-rule{width:44px;height:1px;background:var(--accent);margin:0 auto 26px;}
+ .cover h1{
+ font-family:var(--serif);
+ font-weight:600;
+ line-height:1.04;
+ font-size:clamp(38px,10vw,54px);
+ letter-spacing:.01em;
+ color:var(--ink);
+ }
+ .cover .edit-name{
+ font-family:var(--serif);
+ font-weight:600;
+ line-height:1.04;
+ font-size:clamp(38px,10vw,54px);
+ letter-spacing:.01em;
+ color:var(--ink);
+ text-align:center;
+ border:none;background:transparent;
+ outline:none;width:100%;
+ caret-color:var(--accent);
+ }
+ .cover .edit-name:focus{
+ box-shadow:0 1px 0 var(--accent);
+ }
+ .cover .sub{
+ margin-top:24px;font-size:14px;letter-spacing:.06em;color:var(--muted);
+ max-width:280px;line-height:1.7;
+ }
+ .cover .palette-row{
+ display:flex;gap:10px;margin-top:30px;
+ }
+ .cover .palette-row .dot{
+ width:26px;height:26px;border-radius:50%;
+ border:1px solid var(--line);
+ box-shadow:inset 0 0 0 2px rgba(255,255,255,.5);
+ cursor:pointer;
+ transition:transform .2s var(--ease);
+ }
+ .cover .palette-row .dot:hover{transform:scale(1.12);}
+
+ /* ---------- PATTERN SLIDES ---------- */
+ .swatch{
+ height:52%;
+ position:relative;
+ border-bottom:1px solid var(--line);
+ }
+ .vignette{
+ height:48%;
+ position:relative;
+ background:var(--surface);
+ padding:22px 26px;
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ }
+ .vignette .idx{
+ font-size:11px;letter-spacing:.22em;text-transform:uppercase;
+ color:var(--accent);margin-bottom:10px;
+ }
+ .vignette h3{
+ font-family:var(--serif);font-weight:600;
+ font-size:26px;line-height:1.12;color:var(--ink);margin-bottom:10px;
+ }
+ .vignette p{
+ font-size:13.5px;line-height:1.6;color:var(--muted);letter-spacing:.02em;
+ }
+ .room{
+ position:absolute;inset:0;
+ }
+ /* room vignette overlay elements drawn in CSS */
+ .room .floor{position:absolute;left:0;right:0;bottom:0;height:26%;background:linear-gradient(180deg,rgba(28,26,23,.05),rgba(28,26,23,.14));}
+ .room .furn{position:absolute;border-radius:8px 8px 4px 4px;box-shadow:var(--shadow);}
+ .room .lamp{position:absolute;}
+
+ /* ---------- CTA SLIDE ---------- */
+ .cta{
+ background:
+ radial-gradient(130% 90% at 50% 100%, rgba(47,76,57,.07), transparent 60%),
+ var(--surface);
+ align-items:center;justify-content:center;text-align:center;
+ padding:44px 34px;
+ }
+ .cta .mono{
+ font-size:11px;letter-spacing:.28em;text-transform:uppercase;color:var(--muted);margin-bottom:22px;
+ }
+ .cta h2{
+ font-family:var(--serif);font-weight:600;font-size:clamp(30px,8vw,42px);
+ line-height:1.08;color:var(--ink);margin-bottom:18px;
+ }
+ .cta p{font-size:14px;line-height:1.7;color:var(--muted);max-width:280px;margin:0 auto 30px;letter-spacing:.03em;}
+ .cta .btn{
+ font-family:var(--sans);font-size:12px;letter-spacing:.18em;text-transform:uppercase;
+ color:var(--surface);background:var(--ink);
+ border:none;border-radius:999px;
+ padding:15px 34px;cursor:pointer;
+ transition:background .2s var(--ease),transform .2s var(--ease),box-shadow .2s var(--ease);
+ box-shadow:var(--shadow);
+ }
+ .cta .btn:hover{background:var(--accent);transform:translateY(-2px);box-shadow:var(--shadow-hover);}
+ .cta .handle{margin-top:26px;font-size:12px;letter-spacing:.14em;color:var(--accent);text-transform:uppercase;}
+
+ /* ---------- CONTROLS ---------- */
+ .nav-btn{
+ position:absolute;top:50%;transform:translateY(-50%);
+ width:42px;height:42px;border-radius:50%;
+ background:rgba(255,255,255,.86);border:1px solid var(--line);
+ backdrop-filter:blur(6px);
+ display:flex;align-items:center;justify-content:center;
+ cursor:pointer;z-index:10;color:var(--ink);
+ transition:background .2s var(--ease),transform .2s var(--ease);
+ box-shadow:var(--shadow);
+ font-size:18px;
+ }
+ .nav-btn:hover{background:#fff;}
+ .nav-btn.prev{left:12px;}
+ .nav-btn.next{right:12px;}
+ .nav-btn:disabled{opacity:.28;cursor:default;}
+ .nav-btn.prev:active{transform:translateY(-50%) scale(.94);}
+ .nav-btn.next:active{transform:translateY(-50%) scale(.94);}
+
+ .counter{
+ position:absolute;top:14px;right:16px;z-index:10;
+ font-size:11px;letter-spacing:.16em;color:var(--muted);
+ background:rgba(255,255,255,.75);padding:4px 10px;border-radius:999px;
+ border:1px solid var(--line);
+ }
+
+ .dots{
+ display:flex;gap:9px;justify-content:center;margin-top:22px;
+ }
+ .dots .dot{
+ width:8px;height:8px;border-radius:50%;
+ background:var(--line);border:none;cursor:pointer;padding:0;
+ transition:all .3s var(--ease);
+ }
+ .dots .dot.active{background:var(--accent);width:22px;border-radius:999px;}
+
+ .hint{
+ margin-top:16px;text-align:center;font-size:10.5px;letter-spacing:.16em;
+ text-transform:uppercase;color:var(--muted);
+ }
+ footer.footbar{
+ padding:14px;text-align:center;border-top:1px solid var(--line);
+ font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
+ }
+ .edit-hint{
+ display:inline-block;margin-top:14px;font-size:10px;letter-spacing:.14em;
+ text-transform:uppercase;color:var(--accent);opacity:.8;
+ }
+</style>
+</head>
+<body>
+
+<header class="topbar">
+ <div class="wordmark">Designer<span class="l2">Wallcoverings</span></div>
+ <div class="header-tag">Style Lookbook<br>Carousel</div>
+</header>
+
+<div class="stage-wrap">
+ <div class="frame">
+ <div class="counter" id="counter">01 / 05</div>
+ <button class="nav-btn prev" id="prev" aria-label="Previous">‹</button>
+ <button class="nav-btn next" id="next" aria-label="Next">›</button>
+ <div class="track" id="track">
+
+ <!-- COVER -->
+ <section class="slide cover">
+ <div class="kicker">The Style Edit · No. 01</div>
+ <div class="cover-rule"></div>
+ <input class="edit-name" id="styleName" value="Grandmillennial" spellcheck="false" aria-label="Edit style name">
+ <div class="sub">A curated wallcovering study — pattern, palette & the rooms they belong in.</div>
+ <div class="palette-row" id="paletteRow" title="Click a swatch to shift the accent"></div>
+ <span class="edit-hint">Tap the title to rename · tap a dot to recolor</span>
+ </section>
+
+ <!-- PATTERN 1 -->
+ <section class="slide">
+ <div class="swatch" id="sw1"></div>
+ <div class="vignette">
+ <div class="room" id="room1">
+ <div class="floor"></div>
+ </div>
+ </div>
+ </section>
+
+ <!-- PATTERN 2 -->
+ <section class="slide">
+ <div class="swatch" id="sw2"></div>
+ <div class="vignette">
+ <div class="idx">Pattern Two · Trellis</div>
+ <h3>Garden Lattice</h3>
+ <p>Layer a hand-drawn trellis behind skirted furniture to soften rigid architecture with movement.</p>
+ </div>
+ </section>
+
+ <!-- PATTERN 3 -->
+ <section class="slide">
+ <div class="swatch" id="sw3"></div>
+ <div class="vignette">
+ <div class="idx">Pattern Three · Chinoiserie</div>
+ <h3>Painted Bough</h3>
+ <p>Reserve the scenic for a single feature wall, then echo one motif color in your lampshades.</p>
+ </div>
+ </section>
+
+ <!-- CTA -->
+ <section class="slide cta">
+ <div class="mono">Bring The Look Home</div>
+ <h2>Order Your<br>Swatch Box</h2>
+ <p>Five curated wallcoverings, cut to hand and posted to your studio — styled the way you saw them here.</p>
+ <button class="btn" id="ctaBtn">Request Samples</button>
+ <div class="handle">@designerwallcoverings</div>
+ </section>
+
+ </div>
+ </div>
+
+ <div class="dots" id="dots"></div>
+ <div class="hint">Swipe · Arrow keys · Dots to navigate</div>
+</div>
+
+<footer class="footbar">Designer Wallcoverings — The Style Lookbook</footer>
+
+<!-- CTA overlay (in-page, token-styled) -->
+<div id="overlay" style="position:fixed;inset:0;z-index:100;display:none;align-items:center;justify-content:center;padding:24px;background:rgba(28,26,23,.55);backdrop-filter:blur(4px);">
+ <div style="background:var(--surface);border:1px solid var(--line);border-radius:14px;max-width:360px;width:100%;padding:40px 32px;text-align:center;box-shadow:var(--shadow-hover);">
+ <div style="width:44px;height:1px;background:var(--accent);margin:0 auto 22px;"></div>
+ <h3 style="font-family:var(--serif);font-weight:600;font-size:28px;color:var(--ink);margin-bottom:14px;">Swatch Box Reserved</h3>
+ <p style="font-size:13.5px;line-height:1.7;color:var(--muted);margin-bottom:28px;">Your <span id="ovStyle" style="color:var(--accent);">Grandmillennial</span> edit is on its way. Watch your inbox for a tracking note.</p>
+ <button id="ovClose" style="font-family:var(--sans);font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:var(--surface);background:var(--ink);border:none;border-radius:999px;padding:13px 30px;cursor:pointer;">Close</button>
+ </div>
+</div>
+
+<script>
+(function(){
+ "use strict";
+
+ /* ----- PALETTE (editable accent) ----- */
+ var palette = [
+ {name:'Terracotta', v:'#b0472e'},
+ {name:'Forest', v:'#2f4c39'},
+ {name:'Ochre', v:'#c08a2d'},
+ {name:'Ink Blue', v:'#2c3e57'},
+ {name:'Plum', v:'#6b3a56'}
+ ];
+ var root = document.documentElement;
+
+ function setAccent(hex){
+ root.style.setProperty('--accent', hex);
+ buildSwatches();
+ document.getElementById('room1Note') && null;
+ }
+
+ /* build palette dots on cover */
+ var paletteRow = document.getElementById('paletteRow');
+ palette.forEach(function(c){
+ var d = document.createElement('button');
+ d.className = 'dot';
+ d.style.background = c.v;
+ d.title = c.name + ' — set as accent';
+ d.setAttribute('aria-label', c.name);
+ d.addEventListener('click', function(){ setAccent(c.v); });
+ paletteRow.appendChild(d);
+ });
+
+ /* ----- CSS PATTERN SWATCHES (each visually distinct) ----- */
+ function accent(){ return getComputedStyle(root).getPropertyValue('--accent').trim() || '#b0472e'; }
+
+ function buildSwatches(){
+ var a = accent();
+ var ivory = '#faf6ef';
+
+ // 1 — Scalloped ogee / medallion (radial + repeating)
+ document.getElementById('sw1').style.background =
+ 'radial-gradient(circle at 50% 50%, '+a+'22 0 18%, transparent 19%),'+
+ 'radial-gradient(circle at 0% 0%, '+a+'22 0 18%, transparent 19%),'+
+ 'radial-gradient(circle at 100% 0%, '+a+'22 0 18%, transparent 19%),'+
+ 'radial-gradient(circle at 0% 100%, '+a+'22 0 18%, transparent 19%),'+
+ 'radial-gradient(circle at 100% 100%, '+a+'22 0 18%, transparent 19%),'+
+ ivory;
+ document.getElementById('sw1').style.backgroundSize = '52px 52px';
+
+ // 2 — Garden lattice / trellis (crossed diagonal lines)
+ document.getElementById('sw2').style.background =
+ 'repeating-linear-gradient(45deg, '+a+'55 0 2px, transparent 2px 26px),'+
+ 'repeating-linear-gradient(-45deg, '+a+'55 0 2px, transparent 2px 26px),'+
+ 'linear-gradient('+ivory+','+ivory+')';
+
+ // 3 — Chinoiscerie painted bough (organic conic + dots)
+ document.getElementById('sw3').style.background =
+ 'radial-gradient(ellipse 14px 26px at 30% 20%, '+a+'40 0 60%, transparent 62%),'+
+ 'radial-gradient(ellipse 22px 12px at 70% 55%, '+a+'33 0 60%, transparent 62%),'+
+ 'radial-gradient(circle at 50% 85%, '+a+'55 0 8%, transparent 9%),'+
+ 'linear-gradient(120deg, '+ivory+', #f3ede2)';
+ document.getElementById('sw3').style.backgroundSize = '90px 120px,90px 120px,40px 40px, cover';
+ }
+ buildSwatches();
+
+ /* Pattern 1 vignette content (built dynamically to include styling note) */
+ (function(){
+ var v = document.querySelector('#room1').parentElement;
+ v.innerHTML =
+ '<div class="idx">Pattern One · Medallion</div>'+
+ '<h3>Scalloped Ogee</h3>'+
+ '<p>Pair a soft medallion repeat with a skirted table and blue-and-white ginger jars for instant heritage warmth.</p>';
+ })();
+
+ /* Build a small styled room vignette (CSS shapes) inside cover-adjacent?
+ Keep patterns clean — decorative room bars behind swatch tops. */
+ function decorateRoom(swId, sofa){
+ var el = document.getElementById(swId);
+ var r = document.createElement('div');
+ r.className='room';
+ r.innerHTML =
+ '<div class="floor"></div>'+
+ '<div class="furn" style="left:14%;bottom:9%;width:52%;height:22%;background:'+sofa+';"></div>'+
+ '<div class="furn" style="right:12%;bottom:9%;width:16%;height:34%;background:#efe7d8;border:1px solid var(--line);"></div>'+
+ '<div class="lamp" style="right:16%;bottom:40%;width:8%;height:10%;background:radial-gradient(circle,#f7e9c8,#e8d3a4);border-radius:50% 50% 4px 4px;"></div>';
+ el.appendChild(r);
+ }
+ decorateRoom('sw1','#e9dfce');
+ decorateRoom('sw2','#dde4dc');
+ decorateRoom('sw3','#efe1e6');
+
+ /* ----- CAROUSEL LOGIC ----- */
+ var track = document.getElementById('track');
+ var slides = track.children;
+ var total = slides.length;
+ var idx = 0;
+ var prevBtn = document.getElementById('prev');
+ var nextBtn = document.getElementById('next');
+ var counter = document.getElementById('counter');
+ var dotsWrap= document.getElementById('dots');
+
+ for(var i=0;i<total;i++){
+ (function(n){
+ var b=document.createElement('button');
+ b.className='dot'+(n===0?' active':'');
+ b.setAttribute('aria-label','Slide '+(n+1));
+ b.addEventListener('click',function(){ go(n); });
+ dotsWrap.appendChild(b);
+ })(i);
+ }
+ var dots=dotsWrap.children;
+
+ function pad(n){ return (n<10?'0':'')+n; }
+
+ function render(){
+ track.style.transform = 'translateX(-'+(idx*100)+'%)';
+ counter.textContent = pad(idx+1)+' / '+pad(total);
+ for(var i=0;i<dots.length;i++) dots[i].className='dot'+(i===idx?' active':'');
+ prevBtn.disabled = idx===0;
+ nextBtn.disabled = idx===total-1;
+ }
+ function go(n){ idx=Math.max(0,Math.min(total-1,n)); render(); }
+
+ prevBtn.addEventListener('click',function(){ go(idx-1); });
+ nextBtn.addEventListener('click',function(){ go(idx+1); });
+ document.addEventListener('keydown',function(e){
+ if(e.key==='ArrowLeft') go(idx-1);
+ else if(e.key==='ArrowRight') go(idx+1);
+ });
+
+ /* swipe */
+ var startX=null;
+ track.addEventListener('touchstart',function(e){ startX=e.touches[0].clientX; },{passive:true});
+ track.addEventListener('touchend',function(e){
+ if(startX===null) return;
+ var dx=e.changedTouches[0].clientX-startX;
+ if(Math.abs(dx)>40){ dx<0 ? go(idx+1) : go(idx-1); }
+ startX=null;
+ });
+ /* mouse drag */
+ var mDown=false,mStart=0;
+ track.addEventListener('mousedown',function(e){ mDown=true;mStart=e.clientX; });
+ window.addEventListener('mouseup',function(e){
+ if(!mDown) return; mDown=false;
+ var dx=e.clientX-mStart;
+ if(Math.abs(dx)>50){ dx<0 ? go(idx+1) : go(idx-1); }
+ });
+
+ render();
+
+ /* ----- editable style name syncs to CTA + overlay ----- */
+ var styleName=document.getElementById('styleName');
+ function syncName(){
+ var t=styleName.value.trim()||'Your';
+ document.getElementById('ovStyle').textContent=t;
+ }
+ styleName.addEventListener('input',syncName);
+ styleName.addEventListener('keydown',function(e){ if(e.key==='Enter'){ e.preventDefault(); styleName.blur(); }});
+ syncName();
+
+ /* ----- CTA overlay ----- */
+ var overlay=document.getElementById('overlay');
+ document.getElementById('ctaBtn').addEventListener('click',function(){
+ syncName();
+ overlay.style.display='flex';
+ });
+ document.getElementById('ovClose').addEventListener('click',function(){ overlay.style.display='none'; });
+ overlay.addEventListener('click',function(e){ if(e.target===overlay) overlay.style.display='none'; });
+
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/claude-code.png b/data/artifacts/70eea6613a73/claude-code.png
new file mode 100644
index 0000000..167dc37
Binary files /dev/null and b/data/artifacts/70eea6613a73/claude-code.png differ
diff --git a/data/artifacts/70eea6613a73/gemma3-12b.html b/data/artifacts/70eea6613a73/gemma3-12b.html
new file mode 100644
index 0000000..da1ed7c
--- /dev/null
+++ b/data/artifacts/70eea6613a73/gemma3-12b.html
@@ -0,0 +1,274 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Grandmillennial Lookbook</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #3a2c22;
+ --muted: #9b948a;
+ --accent: #b0472e;
+ --line: rgba(51, 43, 34, 0.1); /* a subtle line color */
+ --shadow: rgba(0, 0, 0, 0.12);
+ --ease: cubic-bezier(.22,1,.36,1);
+ }
+
+ body {
+ font-family: 'apple-system', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ background-color: var(--bg);
+ color: var(--text);
+ margin: 0;
+ padding: 0;
+ overflow-x: hidden; /* Prevent horizontal scrolling */
+ }
+
+ header {
+ background-color: transparent;
+ padding: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: left;
+ width: 100%;
+ position: fixed; /* Fix the header to the top */
+ top: 0;
+ left: 0;
+ z-index: 100;
+ }
+
+ .wordmark {
+ font-family: 'Didot', Georgia, serif;
+ font-size: 67px;
+ letter-spacing: .18em;
+ text-transform: uppercase;
+ line-height: 1; /* Adjust line height for better typography */
+ }
+
+ .carousel {
+ position: relative;
+ width: 100%;
+ overflow-x: auto;
+ scroll-snap-type: x mandatory;
+ padding-top: 128px; /* Account for fixed header */
+ padding-bottom: 64px;
+ }
+
+ .carousel-slide {
+ width: 100vw;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ scroll-snap-align: start;
+ padding: 96px;
+ position: relative;
+ }
+
+ .card {
+ background-color: var(--surface);
+ border-radius: 14px;
+ box-shadow: 0 8px 24px var(--shadow);
+ width: 80%; /* Adjusted width for better layout */
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ text-align: center;
+ margin-bottom: 32px;
+ }
+
+ .card h2 {
+ font-family: 'Didot', Georgia, serif;
+ font-size: 38px;
+ margin-bottom: 16px;
+ }
+
+ .swatch {
+ width: 200px;
+ height: 200px;
+ border: 1px solid var(--line);
+ background-color: var(--accent);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 32px;
+ }
+
+ .vignette {
+ width: 100%; /* Take full width of the card */
+ height: 300px;
+ background-color: #e6dada; /* Placeholder - replace with SVG/gradient*/
+ border-radius: 8px;
+ margin-top: 32px;
+ }
+
+ .note {
+ font-size: 16px;
+ line-height: 1.5;
+ color: var(--muted);
+ }
+
+ .cta {
+ background-color: var(--accent);
+ color: white;
+ padding: 24px;
+ border-radius: 8px;
+ text-align: center;
+ margin-top: 64px;
+ font-size: 18px;
+ letter-spacing: .15em;
+ }
+
+ .dots {
+ position: fixed;
+ bottom: 32px;
+ left: 50%;
+ transform: translateX(-50%);
+ display: flex;
+ gap: 8px;
+ }
+
+ .dot {
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ background-color: var(--muted);
+ cursor: pointer;
+ }
+
+ .dot.active {
+ background-color: var(--accent);
+ }
+
+ /* Animations */
+ @keyframes fadeUp {
+ from { opacity: 0; transform: translateY(28px) }
+ to { opacity: 1; transform: none }
+ }
+
+ </style>
+</head>
+<body>
+
+ <header>
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ </header>
+
+
+ <div class="carousel" id="carousel">
+ <div class="carousel-slide">
+ <h1>Grandmillennial Lookbook</h1>
+ </div>
+
+ <div class="carousel-slide">
+ <div class="card">
+ <h2>Pattern 1: Floral Toile</h2>
+ <div class="swatch" style="background-color:#f2e6d9;"></div>
+ <div class="vignette" style="background: linear-gradient(to bottom, #f2e6d9, #edeae0);"></div>
+ <p class="note">Combine traditional toile with antique furniture for a cozy and nostalgic feel.</p>
+ </div>
+ </div>
+
+ <div class="carousel-slide">
+ <div class="card">
+ <h2>Pattern 2: Striped Wallpaper</h2>
+ <div class="swatch" style="background-color:#d9e6ff;"></div>
+ <div class="vignette" style="background: linear-gradient(to bottom, #d9e6ff, #ccebe4);"></div>
+ <p class="note">Vertical stripes add height and a touch of formality to the space.</p>
+ </div>
+ </div>
+
+ <div class="carousel-slide">
+ <div class="card">
+ <h2>Pattern 3: Chintz Fabric</h2>
+ <div class="swatch" style="background-color:#ffffe6;"></div>
+ <div class="vignette" style="background: linear-gradient(to bottom, #ffffe6, #fdfaf0);"></div>
+ <p class="note">Layer chintz with soft textures and warm lighting for a welcoming atmosphere.</p>
+ </div>
+ </div>
+
+ <div class="carousel-slide">
+ <a href="#" class="cta">Explore the Collection</a>
+ </div>
+ </div>
+
+ <div class="dots" id="dots">
+ <!-- Dots will be dynamically generated by JavaScript -->
+ </div>
+
+
+ <script>
+ const carousel = document.getElementById('carousel');
+ const dotsContainer = document.getElementById('dots');
+ let currentSlide = 0;
+ const totalSlides = document.querySelectorAll('.carousel-slide').length;
+
+ // Generate dots dynamically
+ for (let i = 0; i < totalSlides; i++) {
+ const dot = document.createElement('div');
+ dot.classList.add('dot');
+ dotsContainer.appendChild(dot);
+ }
+
+ const dots = document.querySelectorAll('.dot');
+ dots[0].classList.add('active');
+
+
+ function showSlide(n) {
+ currentSlide = n;
+ carousel.scrollTo({left: carousel.offsetWidth * currentSlide, behavior: 'smooth'});
+ dots.forEach((dot, index) => {
+ if (index === currentSlide) {
+ dot.classList.add('active');
+ } else {
+ dot.classList.remove('active');
+ }
+ });
+
+ }
+
+ // Swipe functionality - basic placeholder; needs refinement for real-world use
+ let startX = 0;
+ let isSwiping = false;
+ carousel.addEventListener('touchstart', (e) => {
+ startX = e.touches[0].clientX;
+ isSwiping = true;
+ });
+
+ carousel.addEventListener('touchmove', (e) => {
+ if (!isSwiping) return;
+ const diffX = e.touches[0].clientX - startX;
+ carousel.scrollTo({left: carousel.scrollLeft + diffX, behavior: 'smooth'});
+ startX = e.touches[0].clientX;
+
+ });
+
+
+ carousel.addEventListener('touchend', (e) => {
+ if (!isSwiping) return;
+ isSwiping = false;
+ const threshold = 50;
+ if (currentSlide > 0 && carousel.scrollLeft < carousel.offsetWidth * currentSlide - threshold ) {
+ showSlide(currentSlide -1);
+ } else if (currentSlide < totalSlides-1 && carousel.scrollLeft > carousel.offsetWidth * currentSlide + threshold) {
+ showSlide(currentSlide+1);
+ }
+
+ });
+
+
+
+
+ // Dot click functionality
+ dots.forEach((dot, index) => {
+ dot.addEventListener('click', () => {
+ showSlide(index);
+ });
+ });
+
+
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/gemma3-12b.png b/data/artifacts/70eea6613a73/gemma3-12b.png
new file mode 100644
index 0000000..486b57a
Binary files /dev/null and b/data/artifacts/70eea6613a73/gemma3-12b.png differ
diff --git a/data/artifacts/70eea6613a73/gpt.html b/data/artifacts/70eea6613a73/gpt.html
new file mode 100644
index 0000000..20f6e0c
--- /dev/null
+++ b/data/artifacts/70eea6613a73/gpt.html
@@ -0,0 +1,1104 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8" />
+<title>DESIGNER WALLCOVERINGS – Art Deco Noir Lookbook</title>
+<style>
+:root {
+ /* Color tokens – luxe-noir palette */
+ --bg: #0d0d0f;
+ --surface: #17171c;
+ --surface-soft: #111117;
+ --text: #f5f2ea;
+ --muted: #8a8578;
+ --accent: #c9a961; /* warm metallic gold */
+ --accent-deep: #7d6a45;
+ --line: rgba(249, 244, 232, 0.12);
+ --line-strong: rgba(249, 244, 232, 0.28);
+
+ /* Type tokens */
+ --font-display: 'Playfair Display', 'Didot', 'Bodoni MT', Georgia, serif;
+ --font-sans: 'Avenir Next', 'Century Gothic', 'Helvetica Neue', system-ui, sans-serif;
+ --fs-caption: 12px;
+ --fs-body: 16px;
+ --fs-lead: 21px;
+ --fs-h3: 28px;
+ --fs-h2: 38px;
+ --fs-h1: 50px;
+ --fs-display: 67px;
+
+ /* Motion tokens (HyperFrames-inspired) */
+ --ease-swift-out: cubic-bezier(.22,.9,.24,1); /* swift-out */
+ --ease-hero: cubic-bezier(.22,1,.36,1); /* ease-out-quint */
+ --ease-power: cubic-bezier(.77,0,.18,1);
+
+ /* Elevation */
+ --shadow-soft: 0 18px 40px rgba(0, 0, 0, 0.45);
+
+ /* Layout */
+ --radius-card: 18px;
+ --radius-pill: 999px;
+ --header-height: 88px;
+}
+
+/* Global reset */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+html, body {
+ margin: 0;
+ padding: 0;
+ background: radial-gradient(circle at top left, #181821 0, var(--bg) 55%, #050507 100%);
+ color: var(--text);
+ font-family: var(--font-sans);
+ font-size: var(--fs-body);
+ line-height: 1.6;
+ -webkit-font-smoothing: antialiased;
+}
+
+body {
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+/* Header / Wordmark */
+.app-shell {
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+.app-header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: var(--header-height);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 18px 32px 16px;
+ background: linear-gradient(to bottom, rgba(13,13,15,0.96), rgba(13,13,15,0.92), rgba(13,13,15,0.85));
+ border-bottom: 1px solid var(--line);
+ z-index: 10;
+ backdrop-filter: blur(18px);
+}
+
+.wordmark-lockup {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ max-width: 280px;
+}
+
+.wordmark {
+ font-family: var(--font-display);
+ font-size: 42px;
+ line-height: 1.05;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--text); /* darkest ink token */
+ white-space: normal;
+}
+
+.wordmark-sub {
+ font-family: var(--font-sans);
+ font-size: 10px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-top: 4px;
+}
+
+.header-meta {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+ font-family: var(--font-sans);
+}
+
+.meta-pill {
+ padding: 6px 12px 5px;
+ border-radius: var(--radius-pill);
+ border: 1px solid var(--line);
+ font-size: 11px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--muted);
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.meta-dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 999px;
+ background: radial-gradient(circle at 30% 20%, #f9f3d5 0, var(--accent) 40%, var(--accent-deep) 100%);
+ box-shadow: 0 0 0 1px rgba(249, 244, 232, 0.25), 0 0 10px rgba(201, 169, 97, 0.7);
+}
+
+/* Main */
+.main {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: calc(var(--header-height) + 16px) 20px 32px;
+}
+
+.carousel-shell {
+ width: min(980px, 100%);
+ max-width: 980px;
+}
+
+/* Carousel card */
+.carousel-card {
+ background: radial-gradient(circle at top, #232330 0, var(--surface) 55%, #0d0d10 100%);
+ border-radius: 26px;
+ box-shadow: var(--shadow-soft);
+ border: 1px solid rgba(255, 255, 255, 0.03);
+ padding: 24px 26px 22px;
+ display: flex;
+ flex-direction: column;
+ gap: 18px;
+ position: relative;
+ overflow: hidden;
+}
+
+/* Top row: style label + slide count */
+.carousel-header-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+
+.style-label-group {
+ display: flex;
+ flex-direction: column;
+ gap: 6px;
+}
+
+.style-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 4px 10px 3px;
+ border-radius: var(--radius-pill);
+ border: 1px solid var(--line);
+ background: linear-gradient(to right, rgba(255,255,255,0.04), rgba(255,255,255,0.0));
+ font-family: var(--font-sans);
+ font-size: 11px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.style-chip-accent {
+ width: 16px;
+ height: 8px;
+ border-radius: 999px;
+ background: linear-gradient(90deg, var(--accent-deep), var(--accent));
+}
+
+.style-name {
+ font-family: var(--font-display);
+ font-size: 30px;
+ line-height: 1.1;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--text);
+}
+
+.style-subtitle {
+ font-family: var(--font-sans);
+ font-size: 13px;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.slide-counter {
+ font-family: var(--font-sans);
+ font-size: 12px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+ border-radius: var(--radius-pill);
+ border: 1px solid var(--line);
+ padding: 6px 13px 5px;
+}
+
+/* Divider */
+.card-divider {
+ height: 1px;
+ width: 100%;
+ background-image: linear-gradient(to right, rgba(249, 244, 232, 0), rgba(249, 244, 232, 0.5), rgba(249, 244, 232, 0));
+ opacity: 0.6;
+}
+
+/* Carousel content */
+.carousel-inner {
+ display: flex;
+ flex-direction: column;
+ gap: 18px;
+}
+
+.carousel-content-row {
+ display: grid;
+ grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.4fr);
+ gap: 22px;
+}
+
+/* Slide image pane */
+.slide-visual {
+ border-radius: 22px;
+ background: radial-gradient(circle at top left, #20202a 0, #101018 45%, #050507 100%);
+ padding: 18px 16px 16px;
+ border: 1px solid var(--line-strong);
+ position: relative;
+ overflow: hidden;
+}
+
+/* Pattern swatch & vignette wrapper */
+.pattern-vignette {
+ display: grid;
+ grid-template-columns: 1.05fr 1.2fr;
+ gap: 14px;
+ align-items: stretch;
+}
+
+/* Swatch */
+.pattern-swatch {
+ border-radius: 18px;
+ overflow: hidden;
+ border: 1px solid rgba(249, 244, 232, 0.24);
+ position: relative;
+ isolation: isolate;
+ min-height: 130px;
+}
+
+/* Vignette */
+.room-vignette {
+ border-radius: 18px;
+ overflow: hidden;
+ border: 1px solid rgba(249, 244, 232, 0.16);
+ position: relative;
+ background: radial-gradient(circle at 0% 0%, #2d2b32 0, #15131a 42%, #020206 100%);
+}
+
+/* Vignette “floor” + “wall” structure */
+.vignette-inner {
+ position: absolute;
+ inset: 0;
+ display: grid;
+ grid-template-rows: 62% 38%;
+}
+
+.vignette-wall {
+ position: relative;
+ overflow: hidden;
+}
+
+.vignette-floor {
+ position: relative;
+ background-image:
+ linear-gradient(175deg, rgba(0,0,0,0.4) 0, rgba(0,0,0,0.7) 45%, rgba(0,0,0,0.95) 100%),
+ repeating-linear-gradient(105deg, rgba(130,110,90,0.2) 0, rgba(130,110,90,0.2) 6px, rgba(40,32,26,0.7) 6px, rgba(40,32,26,0.7) 12px);
+}
+
+/* Shared vignette furniture base */
+.vignette-furniture {
+ position: absolute;
+ inset: 0;
+}
+
+/* Base seat block */
+.v-seat {
+ position: absolute;
+ bottom: 12%;
+ left: 8%;
+ width: 54%;
+ height: 22%;
+ border-radius: 16px;
+ background: linear-gradient(135deg, #26252c, #14131a);
+ box-shadow: 0 14px 24px rgba(0,0,0,0.7);
+ border: 1px solid rgba(255,255,255,0.08);
+}
+
+/* Backrest variations per slide created via modifiers */
+
+/* Side table */
+.v-table {
+ position: absolute;
+ bottom: 14%;
+ right: 10%;
+ width: 16%;
+ height: 26%;
+ background: linear-gradient(to bottom, #2e2c33, #17151c);
+ border-radius: 12px;
+ border: 1px solid rgba(255,255,255,0.1);
+ box-shadow: 0 12px 18px rgba(0,0,0,0.7);
+}
+
+/* Lamp stem */
+.v-lamp-stem {
+ position: absolute;
+ bottom: 40%;
+ right: 17%;
+ width: 2px;
+ height: 20%;
+ background: linear-gradient(to bottom, rgba(249,244,232,0.9), rgba(249,244,232,0.4));
+}
+
+/* Lamp shade */
+.v-lamp-shade {
+ position: absolute;
+ bottom: 62%;
+ right: 12%;
+ width: 22%;
+ height: 18%;
+ border-radius: 50% 50% 45% 45%;
+ background: radial-gradient(circle at 30% 0%, #fffbe1 0, #f3d38a 35%, #7d6a45 100%);
+ box-shadow: 0 0 18px rgba(201,169,97,0.75);
+}
+
+/* Artwork frame */
+.v-frame {
+ position: absolute;
+ top: 14%;
+ left: 14%;
+ width: 38%;
+ height: 40%;
+ border-radius: 12px;
+ border: 1px solid rgba(249,244,232,0.6);
+ box-shadow: 0 8px 18px rgba(0,0,0,0.6);
+ overflow: hidden;
+}
+
+/* Text pane */
+.slide-text {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ gap: 18px;
+}
+
+.slide-kicker {
+ font-family: var(--font-sans);
+ font-size: 11px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.slide-title {
+ font-family: var(--font-display);
+ font-size: 32px;
+ line-height: 1.05;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ margin-bottom: 6px;
+}
+
+.slide-note {
+ font-family: var(--font-sans);
+ font-size: 15px;
+ color: rgba(245, 242, 234, 0.9);
+ max-width: 34rem;
+}
+
+.slide-caption {
+ font-family: var(--font-sans);
+ font-size: 12px;
+ color: var(--muted);
+}
+
+/* CTA slide overrides */
+.slide--cta .slide-visual {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 24px 22px;
+}
+
+.cta-emblem {
+ width: 100%;
+ height: 100%;
+ border-radius: 20px;
+ border: 1px solid var(--line-strong);
+ background-image:
+ radial-gradient(circle at top left, rgba(201,169,97,0.16) 0, transparent 48%),
+ radial-gradient(circle at bottom right, rgba(201,169,97,0.2) 0, transparent 50%),
+ repeating-linear-gradient(135deg, rgba(249,244,232,0.08) 0, rgba(249,244,232,0.08) 2px, rgba(0,0,0,0) 2px, rgba(0,0,0,0) 8px);
+ position: relative;
+ overflow: hidden;
+}
+
+/* concentric rings */
+.cta-ring {
+ position: absolute;
+ border-radius: 999px;
+ border: 1px solid rgba(201,169,97,0.35);
+ inset: 14%;
+}
+
+.cta-ring:nth-child(2) { inset: 26%; opacity: 0.6; }
+.cta-ring:nth-child(3) { inset: 38%; opacity: 0.4; }
+
+/* central monogram */
+.cta-monogram {
+ position: absolute;
+ inset: 44%;
+ border-radius: 999px;
+ background: radial-gradient(circle at 30% 10%, #fff9dc 0, var(--accent) 45%, var(--accent-deep) 100%);
+ box-shadow: 0 0 30px rgba(201,169,97,0.7);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.cta-monogram-letter {
+ font-family: var(--font-display);
+ font-size: 24px;
+ letter-spacing: 0.22em;
+ text-transform: uppercase;
+ color: #151313;
+}
+
+/* CTA text */
+.cta-heading {
+ font-family: var(--font-display);
+ font-size: 30px;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ margin-bottom: 6px;
+}
+
+.cta-body {
+ font-size: 15px;
+ color: rgba(245,242,234,0.9);
+ max-width: 30rem;
+ margin-bottom: 12px;
+}
+
+.cta-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px 14px;
+ font-size: 11px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.cta-pill {
+ padding: 5px 10px 4px;
+ border-radius: var(--radius-pill);
+ border: 1px solid var(--line);
+}
+
+/* Bottom controls */
+.carousel-footer-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 16px;
+}
+
+.carousel-dots {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 999px;
+ border: 1px solid rgba(249, 244, 232, 0.35);
+ background: transparent;
+ transition: background-color 260ms var(--ease-swift-out), transform 260ms var(--ease-swift-out), border-color 260ms var(--ease-swift-out), box-shadow 260ms var(--ease-swift-out);
+}
+
+.dot.active {
+ background: radial-gradient(circle at 30% 20%, #fff9dc 0, var(--accent) 40%, var(--accent-deep) 100%);
+ box-shadow: 0 0 0 1px rgba(249, 244, 232, 0.35), 0 0 14px rgba(201, 169, 97, 0.7);
+ transform: scale(1.32);
+ border-color: transparent;
+}
+
+/* arrows */
+.carousel-arrows {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.arrow-btn {
+ border-radius: 999px;
+ border: 1px solid var(--line);
+ background: rgba(10,10,12,0.55);
+ color: var(--muted);
+ width: 34px;
+ height: 34px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ cursor: pointer;
+ padding: 0;
+ transition: background-color 220ms var(--ease-swift-out), border-color 220ms var(--ease-swift-out), color 220ms var(--ease-swift-out), transform 220ms var(--ease-swift-out), box-shadow 220ms var(--ease-swift-out);
+}
+
+.arrow-btn svg {
+ width: 16px;
+ height: 16px;
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 1.3;
+}
+
+.arrow-btn:focus-visible {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+}
+
+.arrow-btn:hover {
+ background: radial-gradient(circle at top left, rgba(201,169,97,0.18) 0, rgba(11,11,13,0.9) 55%);
+ border-color: rgba(249, 244, 232, 0.5);
+ color: var(--text);
+ box-shadow: 0 0 0 1px rgba(201,169,97,0.25);
+ transform: translateY(-0.5px);
+}
+
+/* slide index label */
+.carousel-index {
+ font-size: 11px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+/* Slides */
+.slide {
+ opacity: 0;
+ transform: translateX(16px);
+ pointer-events: none;
+ position: absolute;
+ inset: 0;
+ padding-right: 2px;
+ padding-bottom: 2px;
+ transition:
+ opacity 420ms var(--ease-hero),
+ transform 420ms var(--ease-hero);
+}
+
+.slide.active {
+ opacity: 1;
+ transform: translateX(0);
+ pointer-events: auto;
+ position: relative;
+}
+
+/* Slide-specific pattern swatches & vignette details */
+
+/* Cover slide pattern: stepped deco fan */
+.swatch--cover {
+ background-image:
+ radial-gradient(circle at 0 0, rgba(249,244,232,0.2) 0, transparent 46%),
+ repeating-linear-gradient(135deg, rgba(249,244,232,0.04) 0, rgba(249,244,232,0.04) 1px, rgba(0,0,0,0) 1px, rgba(0,0,0,0) 7px),
+ repeating-linear-gradient(45deg, rgba(201,169,97,0.22) 0, rgba(201,169,97,0.22) 2px, rgba(13,13,15,1) 2px, rgba(13,13,15,1) 10px);
+}
+
+/* Slide 1 swatch: geometric brass inlay grid */
+.swatch--geo-grid {
+ background-image:
+ linear-gradient(135deg, rgba(201,169,97,0.22), rgba(125,106,69,0.05)),
+ repeating-linear-gradient(90deg, transparent 0, transparent 19px, rgba(201,169,97,0.36) 19px, rgba(201,169,97,0.36) 20px),
+ repeating-linear-gradient(180deg, transparent 0, transparent 19px, rgba(201,169,97,0.36) 19px, rgba(201,169,97,0.36) 20px);
+}
+
+/* Slide 2 swatch: fan motif */
+.swatch--fan {
+ background-image:
+ radial-gradient(circle at 50% 0%, rgba(201,169,97,0.45) 0, rgba(201,169,97,0) 55%),
+ repeating-radial-gradient(circle at 50% 120%, rgba(249,244,232,0.18) 0, rgba(249,244,232,0.18) 1px, rgba(13,13,15,1) 1px, rgba(13,13,15,1) 9px);
+}
+
+/* Slide 3 swatch: slender vertical pinstripes */
+.swatch--pinstripe {
+ background-image:
+ linear-gradient(180deg, rgba(0,0,0,0.65), rgba(0,0,0,0.95)),
+ repeating-linear-gradient(90deg, rgba(249,244,232,0.16) 0, rgba(249,244,232,0.16) 1px, rgba(7,7,9,1) 1px, rgba(7,7,9,1) 8px);
+}
+
+/* Cover vignette backrest: low profile */
+.v-seat-back--cover {
+ position: absolute;
+ left: 10%;
+ bottom: 32%;
+ width: 48%;
+ height: 20%;
+ border-radius: 18px 18px 10px 10px;
+ background-image:
+ linear-gradient(120deg, #373642, #1c1a23);
+ border: 1px solid rgba(255,255,255,0.09);
+}
+
+/* Slide 1 vignette: faceted wall paneling */
+.v-wall-geo {
+ position: absolute;
+ inset: 0;
+ background-image:
+ linear-gradient(135deg, rgba(201,169,97,0.2) 0, rgba(201,169,97,0) 55%),
+ repeating-linear-gradient(135deg, rgba(249,244,232,0.06) 0, rgba(249,244,232,0.06) 1px, rgba(5,5,7,0.8) 1px, rgba(5,5,7,0.8) 12px);
+ opacity: 0.9;
+}
+
+/* Slide 2 vignette: scalloped fans on wall */
+.v-wall-fan {
+ position: absolute;
+ inset: 0;
+ background-image:
+ repeating-radial-gradient(circle at 50% 120%, rgba(249,244,232,0.12) 0, rgba(249,244,232,0.12) 1px, rgba(7,7,9,0.9) 1px, rgba(7,7,9,0.9) 10px);
+}
+
+/* Slide 3 vignette: pinstriped wall with spotlight */
+.v-wall-pin {
+ position: absolute;
+ inset: 0;
+ background-image:
+ radial-gradient(circle at 50% 0%, rgba(255,255,255,0.06) 0, rgba(0,0,0,0) 50%),
+ repeating-linear-gradient(90deg, rgba(249,244,232,0.16) 0, rgba(249,244,232,0.16) 1px, rgba(7,7,9,1) 1px, rgba(7,7,9,1) 10px);
+}
+
+/* Slide2 backrest: curved shell */
+.v-seat-back--shell {
+ position: absolute;
+ left: 6%;
+ bottom: 34%;
+ width: 58%;
+ height: 32%;
+ border-radius: 60px 60px 30px 30px;
+ background-image:
+ radial-gradient(circle at 20% 0%, rgba(255,255,255,0.16) 0, rgba(255,255,255,0) 50%),
+ linear-gradient(135deg, #3b3742, #1a1822);
+ border: 1px solid rgba(255,255,255,0.12);
+}
+
+/* Slide3 backrest: tall channel-tufted */
+.v-seat-back--channel {
+ position: absolute;
+ left: 9%;
+ bottom: 35%;
+ width: 54%;
+ height: 40%;
+ border-radius: 18px 18px 12px 12px;
+ background-image:
+ repeating-linear-gradient(90deg, #302d35 0, #302d35 8px, #241f29 8px, #241f29 18px);
+ border: 1px solid rgba(255,255,255,0.09);
+}
+
+/* Art pieces per slide */
+
+/* Cover artwork: simple deco arch */
+.art--arch {
+ background-image:
+ radial-gradient(circle at 50% 120%, rgba(13,13,15,1) 0, rgba(13,13,15,1) 40%, rgba(249,244,232,0.14) 42%, rgba(249,244,232,0.14) 48%, rgba(13,13,15,1) 50%, rgba(13,13,15,1) 100%),
+ linear-gradient(180deg, rgba(201,169,97,0.32), rgba(77,60,32,0.9));
+}
+
+/* Slide1 artwork: intersecting line work */
+.art--lines {
+ background-image:
+ linear-gradient(135deg, rgba(201,169,97,0.35) 0, rgba(201,169,97,0.05) 60%),
+ repeating-linear-gradient(45deg, rgba(13,13,15,1) 0, rgba(13,13,15,1) 8px, rgba(249,244,232,0.16) 8px, rgba(249,244,232,0.16) 9px);
+}
+
+/* Slide2 artwork: stylized fan */
+.art--fan {
+ background-image:
+ radial-gradient(circle at 50% 110%, rgba(201,169,97,0.65) 0, rgba(201,169,97,0.0) 60%),
+ radial-gradient(circle at 0 0, rgba(249,244,232,0.15) 0, rgba(13,13,15,1) 60%);
+}
+
+/* Slide3 artwork: minimal stripe composition */
+.art--stripe {
+ background-image:
+ linear-gradient(90deg,
+ rgba(249,244,232,0.05) 0,
+ rgba(249,244,232,0.05) 26%,
+ rgba(201,169,97,0.6) 26%,
+ rgba(201,169,97,0.6) 32%,
+ rgba(13,13,15,1) 32%,
+ rgba(13,13,15,1) 100%);
+}
+
+/* Responsive adjustments */
+@media (max-width: 900px) {
+ .carousel-card {
+ padding: 18px 16px 18px;
+ border-radius: 22px;
+ }
+ .carousel-content-row {
+ grid-template-columns: 1fr;
+ }
+ .slide-visual {
+ order: -1;
+ }
+}
+
+@media (max-width: 640px) {
+ .app-header {
+ padding: 14px 16px 12px;
+ height: auto;
+ }
+ :root {
+ --header-height: 92px;
+ }
+ .wordmark {
+ font-size: 36px;
+ letter-spacing: 0.16em;
+ }
+ .style-name {
+ font-size: 24px;
+ }
+ .slide-title {
+ font-size: 26px;
+ }
+ .pattern-vignette {
+ grid-template-columns: 1.1fr 1.5fr;
+ }
+ .carousel-footer-row {
+ flex-direction: column;
+ align-items: flex-start;
+ }
+}
+
+/* Reduce motion preference */
+@media (prefers-reduced-motion: reduce) {
+ * {
+ scroll-behavior: auto !important;
+ animation: none !important;
+ transition: none !important;
+ }
+}
+</style>
+</head>
+<body>
+<div class="app-shell">
+ <header class="app-header">
+ <div class="wordmark-lockup">
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ <div class="wordmark-sub">CURATED WALL PATTERNS FOR INTERIOR PURISTS</div>
+ </div>
+ <div class="header-meta">
+ <div class="meta-pill">
+ <span class="meta-dot" aria-hidden="true"></span>
+ <span>Lookbook · Art Deco Noir</span>
+ </div>
+ <div class="meta-pill">
+ <span>Swipe</span>
+ </div>
+ </div>
+ </header>
+
+ <main class="main">
+ <section class="carousel-shell" aria-label="Art Deco Noir wallcovering carousel">
+ <div class="carousel-card">
+ <div class="carousel-header-row">
+ <div class="style-label-group">
+ <div class="style-chip">
+ <span class="style-chip-accent" aria-hidden="true"></span>
+ <span>Style edit</span>
+ </div>
+ <div class="style-name" contenteditable="true" spellcheck="false">
+ Art Deco Noir
+ </div>
+ <div class="style-subtitle">
+ Wallcoverings for cinematic living rooms
+ </div>
+ </div>
+ <div class="slide-counter" id="slideCounter" aria-live="polite">
+ Slide 1 · 5
+ </div>
+ </div>
+
+ <div class="card-divider" aria-hidden="true"></div>
+
+ <div class="carousel-inner">
+ <!-- Slide 1: Cover -->
+ <article class="slide active" data-index="0" aria-roledescription="slide" aria-label="Cover: Art Deco Noir palette">
+ <div class="carousel-content-row">
+ <div class="slide-visual">
+ <div class="pattern-vignette">
+ <div class="pattern-swatch swatch--cover" aria-hidden="true"></div>
+ <div class="room-vignette" aria-hidden="true">
+ <div class="vignette-inner">
+ <div class="vignette-wall">
+ <div class="v-wall-geo"></div>
+ <div class="v-frame art--arch"></div>
+ </div>
+ <div class="vignette-floor"></div>
+ </div>
+ <div class="vignette-furniture">
+ <div class="v-seat"></div>
+ <div class="v-seat-back--cover"></div>
+ <div class="v-table"></div>
+ <div class="v-lamp-stem"></div>
+ <div class="v-lamp-shade"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="slide-text">
+ <div>
+ <div class="slide-kicker">Lookbook cover</div>
+ <h2 class="slide-title">Sculpted light over deep nocturnes</h2>
+ <p class="slide-note">
+ A restrained palette of ink black, warm ivory, and brushed gold sets the tone for an Art Deco living room that feels like a private cinema.
+ </p>
+ </div>
+ <p class="slide-caption">
+ Edit the style name above and tune this palette for your next launch — every swatch below is drawn with pure CSS, ready to adapt.
+ </p>
+ </div>
+ </div>
+ </article>
+
+ <!-- Slide 2: Geometric brass grid -->
+ <article class="slide" data-index="1" aria-roledescription="slide" aria-label="Geometric brass grid wall">
+ <div class="carousel-content-row">
+ <div class="slide-visual">
+ <div class="pattern-vignette">
+ <div class="pattern-swatch swatch--geo-grid" aria-hidden="true"></div>
+ <div class="room-vignette" aria-hidden="true">
+ <div class="vignette-inner">
+ <div class="vignette-wall">
+ <div class="v-wall-geo"></div>
+ <div class="v-frame art--lines"></div>
+ </div>
+ <div class="vignette-floor"></div>
+ </div>
+ <div class="vignette-furniture">
+ <div class="v-seat"></div>
+ <div class="v-seat-back--channel"></div>
+ <div class="v-table"></div>
+ <div class="v-lamp-stem"></div>
+ <div class="v-lamp-shade"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="slide-text">
+ <div>
+ <div class="slide-kicker">Pattern one · Geometric brass grid</div>
+ <h2 class="slide-title">Frame the room with quiet geometry</h2>
+ <p class="slide-note">
+ Use a slim brass inlay grid on the main wall only, then keep furnishings low and monochrome so the pattern reads like built-in architecture.
+ </p>
+ </div>
+ <p class="slide-caption">
+ Deep charcoal grounds the grid; echo the metal in table edges and lamp stems for a subtle, continuous line around the room.
+ </p>
+ </div>
+ </div>
+ </article>
+
+ <!-- Slide 3: Fan motif -->
+ <article class="slide" data-index="2" aria-roledescription="slide" aria-label="Scalloped fan wall">
+ <div class="carousel-content-row">
+ <div class="slide-visual">
+ <div class="pattern-vignette">
+ <div class="pattern-swatch swatch--fan" aria-hidden="true"></div>
+ <div class="room-vignette" aria-hidden="true">
+ <div class="vignette-inner">
+ <div class="vignette-wall">
+ <div class="v-wall-fan"></div>
+ <div class="v-frame art--fan"></div>
+ </div>
+ <div class="vignette-floor"></div>
+ </div>
+ <div class="vignette-furniture">
+ <div class="v-seat"></div>
+ <div class="v-seat-back--shell"></div>
+ <div class="v-table"></div>
+ <div class="v-lamp-stem"></div>
+ <div class="v-lamp-shade"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="slide-text">
+ <div>
+ <div class="slide-kicker">Pattern two · Fan motif</div>
+ <h2 class="slide-title">Let the fans glow, not shout</h2>
+ <p class="slide-note">
+ Pair scalloped fans with rounded seating and a single halo lamp so light brushes the arcs and the pattern feels luminous rather than busy.
+ </p>
+ </div>
+ <p class="slide-caption">
+ Keep fabrics matte and textured — bouclé, wool, or mohair — to contrast the silky sheen of the fan print.
+ </p>
+ </div>
+ </div>
+ </article>
+
+ <!-- Slide 4: Pinstripe -->
+ <article class="slide" data-index="3" aria-roledescription="slide" aria-label="Vertical pinstripe wall">
+ <div class="carousel-content-row">
+ <div class="slide-visual">
+ <div class="pattern-vignette">
+ <div class="pattern-swatch swatch--pinstripe" aria-hidden="true"></div>
+ <div class="room-vignette" aria-hidden="true">
+ <div class="vignette-inner">
+ <div class="vignette-wall">
+ <div class="v-wall-pin"></div>
+ <div class="v-frame art--stripe"></div>
+ </div>
+ <div class="vignette-floor"></div>
+ </div>
+ <div class="vignette-furniture">
+ <div class="v-seat"></div>
+ <div class="v-seat-back--channel"></div>
+ <div class="v-table"></div>
+ <div class="v-lamp-stem"></div>
+ <div class="v-lamp-shade"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="slide-text">
+ <div>
+ <div class="slide-kicker">Pattern three · Vertical pinstripe</div>
+ <h2 class="slide-title">Pull the ceiling higher with stripes</h2>
+ <p class="slide-note">
+ Run ultra-fine ivory pinstripes floor to ceiling, then choose low-slung seating so the wall reads taller and the room feels quietly grand.
+ </p>
+ </div>
+ <p class="slide-caption">
+ Anchor the look with a single dark, glossy table or plinth to mirror the line of the stripes without adding visual noise.
+ </p>
+ </div>
+ </div>
+ </article>
+
+ <!-- Slide 5: CTA -->
+ <article class="slide slide--cta" data-index="4" aria-roledescription="slide" aria-label="Call to action">
+ <div class="carousel-content-row">
+ <div class="slide-visual">
+ <div class="cta-emblem" aria-hidden="true">
+ <div class="cta-ring"></div>
+ <div class="cta-ring"></div>
+ <div class="cta-ring"></div>
+ <div class="cta-monogram">
+ <span class="cta-monogram-letter">DW</span>
+ </div>
+ </div>
+ </div>
+ <div class="slide-text">
+ <div>
+ <div class="slide-kicker">Final touch</div>
+ <h2 class="cta-heading">Specify your next statement wall</h2>
+ <p class="cta-body">
+ Save this carousel as a palette sketch: edit the style name, tune the gold, and swap patterns to prototype your own couture wallcovering story.
+ </p>
+ </div>
+ <div class="cta-meta">
+ <span class="cta-pill">Hold to zoom details</span>
+ <span class="cta-pill">Share with your client</span>
+ <span class="cta-pill">Tag @designerwallcoverings</span>
+ </div>
+ </div>
+ </div>
+ </article>
+ </div>
+
+ <div class="carousel-footer-row">
+ <div class="carousel-dots" role="tablist" aria-label="Slide navigation">
+ <button class="dot active" data-index="0" role="tab" aria-selected="true" aria-label="Go to cover slide"></button>
+ <button class="dot" data-index="1" role="tab" aria-selected="false" aria-label="Go to geometric brass grid slide"></button>
+ <button class="dot" data-index="2" role="tab" aria-selected="false" aria-label="Go to fan motif slide"></button>
+ <button class="dot" data-index="3" role="tab" aria-selected="false" aria-label="Go to vertical pinstripe slide"></button>
+ <button class="dot" data-index="4" role="tab" aria-selected="false" aria-label="Go to call to action slide"></button>
+ </div>
+ <div class="carousel-arrows">
+ <div class="carousel-index" id="slideIndexText">01 · 05</div>
+ <button class="arrow-btn" id="prevBtn" type="button" aria-label="Previous slide">
+ <svg viewBox="0 0 24 24" aria-hidden="true">
+ <path d="M14.5 6.5L9 12l5.5 5.5" />
+ </svg>
+ </button>
+ <button class="arrow-btn" id="nextBtn" type="button" aria-label="Next slide">
+ <svg viewBox="0 0 24 24" aria-hidden="true">
+ <path d="M9.5 6.5L15 12l-5.5 5.5" />
+ </svg>
+ </button>
+ </div>
+ </div>
+ </div>
+ </section>
+ </main>
+</div>
+
+<script>
+(function () {
+ const slides = Array.from(document.querySelectorAll('.slide'));
+ const dots = Array.from(document.querySelectorAll('.dot'));
+ const counter = document.getElementById('slideCounter');
+ const indexText = document.getElementById('slideIndexText');
+ const prev = document.getElementById('prevBtn');
+ const next = document.getElementById('nextBtn');
+ const total = slides.length;
+ let current = 0;
+
+ function setSlide(index) {
+ if (index === current || index < 0 || index >= total) return;
+ slides[current].classList.remove('active');
+ dots[current].classList.remove('active');
+ slides[index].classList.add('active');
+ dots[index].classList.add('active');
+ current = index;
+ const displayIndex = (current + 1).toString().padStart(2, '0');
+ const displayTotal = total.toString().padStart(2, '0');
+ counter.textContent = 'Slide ' + (current + 1) + ' · ' + total;
+ indexText.textContent = displayIndex + ' · ' + displayTotal;
+ dots.forEach((dot, i) => {
+ dot.setAttribute('aria-selected', i === current ? 'true' : 'false');
+ });
+ }
+
+ prev.addEventListener('click', function () {
+ const target = current === 0 ? total - 1 : current - 1;
+ setSlide(target);
+ });
+
+ next.addEventListener('click', function () {
+ const target = current === total - 1 ? 0 : current + 1;
+ setSlide(target);
+ });
+
+ dots.forEach(dot => {
+ dot.addEventListener('click', () => {
+ const index = parseInt(dot.getAttribute('data-index'), 10);
+ setSlide(index);
+ });
+ });
+
+ // Keyboard navigation
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'ArrowRight') {
+ next.click();
+ } else if (e.key === 'ArrowLeft') {
+ prev.click();
+ }
+ });
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/gpt.png b/data/artifacts/70eea6613a73/gpt.png
new file mode 100644
index 0000000..d77da36
Binary files /dev/null and b/data/artifacts/70eea6613a73/gpt.png differ
diff --git a/data/artifacts/70eea6613a73/grok.html b/data/artifacts/70eea6613a73/grok.html
new file mode 100644
index 0000000..c1f8a02
--- /dev/null
+++ b/data/artifacts/70eea6613a73/grok.html
@@ -0,0 +1,937 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Grandmillennial — Designer Wallcoverings Lookbook</title>
+<style>
+:root {
+ --bg: #f7f3eb;
+ --surface: #fffdf8;
+ --ink: #1c1a17;
+ --muted: #6e675c;
+ --accent: #9a3b4a;
+ --accent-soft: #c4a dig;
+ --gold: #b8956c;
+ --line: rgba(28, 26, 23, 0.12);
+ --shadow: 0 18px 48px rgba(28, 26, 23, 0.08);
+ --shadow-soft: 0 6px 20px rgba(28, 26, 23, 0.06);
+ --ease: cubic-bezier(.22, .9, .24, 1);
+ --ease-scene: cubic-bezier(.77, 0, .18, 1);
+ --ease-out: cubic-bezier(.22, 1, .36, 1);
+ --serif: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, 'Times New Roman', serif;
+ --sans: 'Avenir Next', 'Century Gothic', Futura, 'Segoe UI', sans-serif;
+ --bar-h: 72px;
+ --radius: 2px;
+}
+
+*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
+
+html, body {
+ height: 100%;
+ background: var(--bg);
+ color: var(--ink);
+ font-family: var(--sans);
+ font-size: 16px;
+ line-height: 1.55;
+ -webkit-font-smoothing: antialiased;
+ overflow: hidden;
+}
+
+/* —— Fixed brand bar —— */
+.brand-bar {
+ position: fixed;
+ top: 0; left: 0; right: 0;
+ height: var(--bar-h);
+ z-index: 100;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 0 28px;
+ background: var(--bg);
+ border-bottom: 1px solid var(--line);
+}
+
+.wordmark {
+ font-family: var(--serif);
+ font-size: 42px;
+ font-weight: 400;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ line-height: 1.05;
+ white-space: nowrap;
+}
+
+.bar-meta {
+ font-family: var(--sans);
+ font-size: 10px;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+/* —— Stage —— */
+.stage {
+ position: fixed;
+ inset: var(--bar-h) 0 0 0;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 28px 20px 36px;
+}
+
+.phone {
+ width: min(400px, 100%);
+ height: min(720px, calc(100vh - var(--bar-h) - 64px));
+ background: var(--surface);
+ border: 1px solid var(--line);
+ box-shadow: var(--shadow);
+ border-radius: 4px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ position: relative;
+}
+
+/* —— Carousel —— */
+.carousel {
+ flex: 1;
+ position: relative;
+ overflow: hidden;
+ touch-action: pan-y;
+}
+
+.track {
+ display: flex;
+ height: 100%;
+ transition: transform 0.7s var(--ease-scene);
+ will-change: transform;
+}
+
+.slide {
+ flex: 0 0 100%;
+ width: 100%;
+ height: 100%;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ padding: 28px 28px 20px;
+ opacity: 0.35;
+ transition: opacity 0.55s var(--ease);
+}
+
+.slide.is-active { opacity: 1; }
+
+/* Cover */
+.slide-cover {
+ justify-content: flex-end;
+ padding-bottom: 48px;
+ background:
+ linear-gradient(180deg, transparent 30%, rgba(247,243,235,0.92) 70%, var(--bg) 100%),
+ repeating-linear-gradient(
+ 0deg,
+ transparent,
+ transparent 11px,
+ rgba(154, 59, 74, 0.045) 11px,
+ rgba(154, 59, 74, 0.045) 12px
+ ),
+ repeating-linear-gradient(
+ 90deg,
+ transparent,
+ transparent 11px,
+ rgba(184, 149, 108, 0.05) 11px,
+ rgba(184, 149, 108, 0.05) 12px
+ );
+}
+
+.cover-ornament {
+ position: absolute;
+ inset: 36px 28px auto;
+ height: 52%;
+ border: 1px solid var(--line);
+ display: grid;
+ place-items: center;
+ overflow: hidden;
+}
+
+.cover-ornament svg { width: 78%; height: 78%; }
+
+.eyebrow {
+ font-size: 11px;
+ letter-spacing: 0.22em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 14px;
+}
+
+.style-name {
+ font-family: var(--serif);
+ font-size: 50px;
+ font-weight: 400;
+ line-height: 1.05;
+ letter-spacing: -0.02em;
+ color: var(--ink);
+ margin-bottom: 10px;
+}
+
+.style-name[contenteditable="true"] {
+ outline: none;
+ border-bottom: 1px solid transparent;
+ transition: border-color 0.3s var(--ease);
+ cursor: text;
+}
+.style-name[contenteditable="true"]:hover,
+.style-name[contenteditable="true"]:focus {
+ border-bottom-color: var(--gold);
+}
+
+.cover-line {
+ width: 48px;
+ height: 1px;
+ background: var(--accent);
+ margin: 16px 0;
+}
+
+.cover-dek {
+ font-size: 14px;
+ color: var(--muted);
+ max-width: 28ch;
+ line-height: 1.6;
+}
+
+/* Pair slides */
+.slide-pair {
+ gap: 18px;
+}
+
+.pair-top {
+ display: grid;
+ grid-template-columns: 1fr 1.15fr;
+ gap: 14px;
+ flex: 1;
+ min-height: 0;
+}
+
+.swatch {
+ border: 1px solid var(--line);
+ border-radius: var(--radius);
+ position: relative;
+ overflow: hidden;
+ box-shadow: var(--shadow-soft);
+ min-height: 180px;
+}
+
+.vignette {
+ border: 1px solid var(--line);
+ border-radius: var(--radius);
+ position: relative;
+ overflow: hidden;
+ background: #e8e0d4;
+ box-shadow: var(--shadow-soft);
+ min-height: 180px;
+}
+
+.pair-note {
+ border-top: 1px solid var(--line);
+ padding-top: 16px;
+ display: flex;
+ gap: 14px;
+ align-items: flex-start;
+}
+
+.note-index {
+ font-family: var(--serif);
+ font-size: 28px;
+ color: var(--accent);
+ line-height: 1;
+ min-width: 28px;
+}
+
+.note-text {
+ font-size: 14px;
+ color: var(--ink);
+ line-height: 1.55;
+ max-width: 34ch;
+}
+
+.note-label {
+ display: block;
+ font-size: 10px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 6px;
+}
+
+/* CTA */
+.slide-cta {
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ gap: 18px;
+ background:
+ radial-gradient(ellipse at 50% 0%, rgba(154,59,74,0.06), transparent 55%);
+}
+
+.cta-mark {
+ width: 56px;
+ height: 1px;
+ background: var(--gold);
+}
+
+.cta-title {
+ font-family: var(--serif);
+ font-size: 38px;
+ line-height: 1.1;
+ letter-spacing: -0.02em;
+}
+
+.cta-body {
+ font-size: 14px;
+ color: var(--muted);
+ max-width: 28ch;
+ line-height: 1.65;
+}
+
+.palette-row {
+ display: flex;
+ gap: 10px;
+ margin-top: 8px;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.swatch-dot {
+ width: 28px;
+ height: 28px;
+ border-radius: 50%;
+ border: 1px solid var(--line);
+ cursor: pointer;
+ transition: transform 0.35s var(--ease), box-shadow 0.35s var(--ease);
+ position: relative;
+}
+.swatch-dot:hover { transform: scale(1.12); }
+.swatch-dot.is-active {
+ box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--ink);
+}
+
+.cta-btn {
+ margin-top: 10px;
+ appearance: none;
+ border: 1px solid var(--ink);
+ background: var(--ink);
+ color: var(--bg);
+ font-family: var(--sans);
+ font-size: 11px;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ padding: 14px 28px;
+ cursor: pointer;
+ transition: background 0.35s var(--ease), color 0.35s var(--ease), transform 0.35s var(--ease);
+}
+.cta-btn:hover {
+ background: transparent;
+ color: var(--ink);
+}
+.cta-btn:active { transform: scale(0.98); }
+
+/* —— Dots + controls —— */
+.chrome {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 14px 22px 18px;
+ border-top: 1px solid var(--line);
+ background: var(--surface);
+}
+
+.dots {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+}
+
+.dot {
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: var(--line);
+ border: none;
+ padding: 0;
+ cursor: pointer;
+ transition: background 0.35s var(--ease), transform 0.35s var(--ease);
+}
+.dot[aria-current="true"] {
+ background: var(--ink);
+ transform: scale(1.25);
+}
+
+.nav-btns {
+ display: flex;
+ gap: 6px;
+}
+
+.nav-btn {
+ appearance: none;
+ background: transparent;
+ border: 1px solid var(--line);
+ color: var(--ink);
+ font-family: var(--sans);
+ font-size: 10px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ padding: 8px 12px;
+ cursor: pointer;
+ transition: border-color 0.3s var(--ease), background 0.3s var(--ease);
+}
+.nav-btn:hover {
+ border-color: var(--ink);
+ background: rgba(28,26,23,0.03);
+}
+.nav-btn:disabled {
+ opacity: 0.35;
+ cursor: default;
+}
+
+/* —— Room vignettes (pure CSS) —— */
+.room {
+ position: absolute;
+ inset: 0;
+}
+
+/* shared furniture pieces */
+.wall {
+ position: absolute;
+ inset: 0 0 38% 0;
+}
+.floor {
+ position: absolute;
+ left: 0; right: 0; bottom: 0;
+ height: 38%;
+ background:
+ linear-gradient(180deg, rgba(28,26,23,0.06), transparent 40%),
+ repeating-linear-gradient(
+ 90deg,
+ #d9cfc0 0 28px,
+ #d2c6b4 28px 29px
+ );
+}
+.baseboard {
+ position: absolute;
+ left: 0; right: 0;
+ bottom: 38%;
+ height: 4px;
+ background: #f3ebe0;
+ border-top: 1px solid rgba(28,26,23,0.08);
+ border-bottom: 1px solid rgba(28,26,23,0.1);
+}
+.sofa {
+ position: absolute;
+ left: 12%;
+ right: 12%;
+ bottom: 22%;
+ height: 22%;
+ background: #6b4f55;
+ border-radius: 6px 6px 2px 2px;
+ box-shadow: 0 4px 12px rgba(28,26,23,0.12);
+}
+.sofa::before {
+ content: '';
+ position: absolute;
+ left: 6%; right: 6%;
+ top: -28%;
+ height: 38%;
+ background: #7a5a60;
+ border-radius: 4px 4px 0 0;
+}
+.sofa::after {
+ content: '';
+ position: absolute;
+ left: 10%;
+ top: 18%;
+ width: 22%;
+ height: 42%;
+ background: #c4a dig;
+ background: #c9b29a;
+ border-radius: 3px;
+ box-shadow: 26px 0 0 #b8956c, 52px 4px 0 #9a3b4a;
+}
+.table {
+ position: absolute;
+ left: 32%;
+ right: 32%;
+ bottom: 16%;
+ height: 8%;
+ background: #3a322c;
+ border-radius: 1px;
+}
+.table::before {
+ content: '';
+ position: absolute;
+ left: 8%; right: 8%;
+ top: -55%;
+ height: 55%;
+ background: radial-gradient(ellipse at 50% 80%, #efe6d8, #e0d4c2);
+ border: 1px solid rgba(28,26,23,0.08);
+ border-radius: 50%;
+}
+.lamp {
+ position: absolute;
+ width: 10%;
+ right: 14%;
+ bottom: 38%;
+ height: 28%;
+}
+.lamp-shade {
+ position: absolute;
+ top: 0; left: 0; right: 0;
+ height: 38%;
+ background: #f0e6d4;
+ clip-path: polygon(8% 100%, 92% 100%, 100% 0, 0 0);
+ box-shadow: 0 0 24px rgba(240, 230, 212, 0.55);
+}
+.lamp-stem {
+ position: absolute;
+ left: 46%;
+ width: 8%;
+ top: 38%;
+ bottom: 0;
+ background: var(--gold);
+}
+.frame {
+ position: absolute;
+ border: 3px solid var(--gold);
+ background: #f7f1e6;
+ box-shadow: inset 0 0 0 1px rgba(28,26,23,0.06);
+}
+.plant {
+ position: absolute;
+ left: 10%;
+ bottom: 38%;
+ width: 12%;
+ height: 18%;
+}
+.plant-pot {
+ position: absolute;
+ bottom: 0; left: 20%; right: 20%;
+ height: 35%;
+ background: #8a6a4a;
+ clip-path: polygon(10% 0, 90% 0, 100% 100%, 0 100%);
+}
+.plant-leaf {
+ position: absolute;
+ background: #4a6b52;
+ border-radius: 50% 50% 50% 0;
+}
+
+/* Room 1 — parlor */
+.room-1 .wall {
+ background:
+ repeating-linear-gradient(
+ 45deg,
+ #e9dfd0 0 10px,
+ #e4d8c6 10px 20px
+ );
+}
+.room-1 .frame { top: 14%; left: 18%; width: 28%; height: 32%; }
+.room-1 .frame-b { top: 18%; left: 52%; width: 22%; height: 26%; border-color: #8a6a4a; }
+
+/* Room 2 — library nook */
+.room-2 .wall {
+ background:
+ repeating-linear-gradient(
+ 0deg,
+ #d9cfc3 0 14px,
+ #cfc3b4 14px 15px
+ );
+}
+.room-2 .sofa { background: #3d4a56; }
+.room-2 .sofa::before { background: #4a5866; }
+.room-2 .bookshelf {
+ position: absolute;
+ left: 8%; top: 10%;
+ width: 36%; height: 48%;
+ background:
+ repeating-linear-gradient(
+ 90deg,
+ #5c3d2e 0 8px,
+ #6b4a38 8px 10px,
+ #2c241e 10px 18px,
+ #8b3a3a 18px 22px,
+ #1c1a17 22px 26px,
+ #b8956c 26px 30px
+ ),
+ linear-gradient(#3a2a22, #3a2a22);
+ border: 2px solid #2a201a;
+ box-shadow: inset 0 0 0 3px #4a3428;
+}
+.room-2 .sofa { left: 48%; right: 8%; }
+
+/* Room 3 — breakfast bay */
+.room-3 .wall {
+ background:
+ radial-gradient(circle at 20% 30%, rgba(154,59,74,0.15) 0 6%, transparent 6.5%),
+ radial-gradient(circle at 50% 60%, rgba(154,59,74,0.12) 0 5%, transparent 5.5%),
+ radial-gradient(circle at 75% 25%, rgba(154,59,74,0.14) 0 7%, transparent 7.5%),
+ radial-gradient(circle at 40% 80%, rgba(184,149,108,0.18) 0 5%, transparent 5.5%),
+ #efe6d6;
+}
+.room-3 .window {
+ position: absolute;
+ top: 12%; left: 22%; right: 22%;
+ height: 42%;
+ background: linear-gradient(180deg, #c5d4c8, #a8bfb0);
+ border: 4px solid #f5efe4;
+ box-shadow: 0 0 0 1px rgba(28,26,23,0.1), inset 0 0 0 2px #e8dfd0;
+}
+.room-3 .window::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background:
+ linear-gradient(var(--gold), var(--gold)) center/100% 2px no-repeat,
+ linear-gradient(var(--gold), var(--gold)) center/2px 100% no-repeat;
+}
+.room-3 .sofa {
+ left: 18%; right: 18%;
+ bottom: 18%;
+ height: 16%;
+ background: #d8c8a8;
+ border-radius: 2px;
+}
+.room-3 .sofa::before { display: none; }
+.room-3 .sofa::after { display: none; }
+.room-3 .chair-l, .room-3 .chair-r {
+ position: absolute;
+ bottom: 20%;
+ width: 14%;
+ height: 18%;
+ background: #6b4f55;
+ border-radius: 3px 3px 0 0;
+}
+.room-3 .chair-l { left: 10%; }
+.room-3 .chair-r { right: 10%; }
+
+/* —— Pattern swatches (distinct motifs) —— */
+/* 1. Chinoiserie vine */
+.pat-chinoiserie {
+ background-color: #f3ebe0;
+ background-image:
+ radial-gradient(ellipse 18px 28px at 30% 35%, transparent 60%, rgba(154,59,74,0.55) 61% 68%, transparent 69%),
+ radial-gradient(ellipse 14px 22px at 68% 62%, transparent 60%, rgba(74,107,82,0.5) 61% 70%, transparent 71%),
+ radial-gradient(circle at 50% 48%, rgba(184,149,108,0.45) 0 3px, transparent 3.5px),
+ radial-gradient(circle at 22% 70%, rgba(154,59,74,0.35) 0 2px, transparent 2.5px),
+ radial-gradient(circle at 78% 28%, rgba(74,107,82,0.4) 0 2.5px, transparent 3px),
+ linear-gradient(125deg, transparent 48%, rgba(74,107,82,0.25) 49% 51%, transparent 52%),
+ linear-gradient(55deg, transparent 46%, rgba(154,59,74,0.2) 47% 49%, transparent 50%);
+}
+
+/* 2. Damask diamond */
+.pat-damask {
+ background-color: #2c333c;
+ background-image:
+ radial-gradient(ellipse 40% 30% at 50% 50%, rgba(184,149,108,0.55) 0 8%, transparent 9%),
+ radial-gradient(ellipse 18% 40% at 50% 50%, rgba(184,149,108,0.4) 0 10%, transparent 11%),
+ linear-gradient(45deg, transparent 46%, rgba(184,149,108,0.22) 47% 53%, transparent 54%),
+ linear-gradient(-45deg, transparent 46%, rgba(184,149,108,0.22) 47% 53%, transparent 54%);
+ background-size: 48px 48px, 48px 48px, 48px 48px, 48px 48px;
+}
+
+/* 3. Botanical stripe */
+.pat-botanical {
+ background-color: #f6f0e6;
+ background-image:
+ radial-gradient(circle at 50% 20%, #9a3b4a 0 2px, transparent 2.5px),
+ radial-gradient(circle at 50% 50%, #4a6b52 0 3px, transparent 3.5px),
+ radial-gradient(circle at 50% 80%, #b8956c 0 2px, transparent 2.5px),
+ linear-gradient(90deg,
+ transparent 0 18%,
+ rgba(154,59,74,0.15) 18% 20%,
+ transparent 20% 48%,
+ rgba(74,107,82,0.18) 48% 52%,
+ transparent 52% 80%,
+ rgba(184,149,108,0.2) 80% 82%,
+ transparent 82%
+ );
+ background-size: 36px 60px, 36px 60px, 36px 60px, 36px 100%;
+}
+
+/* overlay toast */
+.toast {
+ position: absolute;
+ left: 50%;
+ bottom: 88px;
+ transform: translateX(-50%) translateY(12px);
+ background: var(--ink);
+ color: var(--bg);
+ font-size: 11px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ padding: 12px 20px;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
+ z-index: 20;
+ white-space: nowrap;
+}
+.toast.show {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+}
+
+/* editable palette hint */
+.edit-hint {
+ font-size: 10px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-top: 4px;
+}
+
+@media (max-width: 480px) {
+ .wordmark { font-size: 28px; letter-spacing: 0.14em; }
+ .brand-bar { padding: 0 16px; height: 60px; }
+ :root { --bar-h: 60px; }
+ .style-name { font-size: 40px; }
+ .pair-top { grid-template-columns: 1fr; }
+}
+</style>
+</head>
+<body>
+
+<header class="brand-bar">
+ <div class="wordmark">Designer Wallcoverings</div>
+ <div class="bar-meta">Lookbook · 01</div>
+</header>
+
+<main class="stage">
+ <div class="phone" id="phone">
+ <div class="carousel" id="carousel">
+ <div class="track" id="track">
+
+ <!-- COVER -->
+ <section class="slide slide-cover is-active" data-i="0">
+ <div class="cover-ornament" aria-hidden="true">
+ <svg viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
+ <rect x="20" y="20" width="160" height="160" stroke="#1c1a17" stroke-opacity="0.15" stroke-width="0.75"/>
+ <path d="M100 36 C78 60, 58 78, 58 104 C58 128, 76 146, 100 146 C124 146, 142 128, 142 104 C142 78, 122 60, 100 36Z" stroke="#9a3b4a" stroke-width="1.25" fill="none"/>
+ <path d="M100 52 C86 70, 72 84, 72 104 C72 120, 84 132, 100 132 C116 132, 128 120, 128 104 C128 84, 114 70, 100 52Z" stroke="#b8956c" stroke-width="0.75" fill="none"/>
+ <circle cx="100" cy="104" r="4" fill="#9a3b4a"/>
+ <path d="M100 146 V168 M88 156 H112" stroke="#1c1a17" stroke-opacity="0.35" stroke-width="1"/>
+ <path d="M40 100 H62 M138 100 H160" stroke="#b8956c" stroke-width="0.75" stroke-opacity="0.7"/>
+ <path d="M48 80 Q58 100 48 120 M152 80 Q142 100 152 120" stroke="#4a6b52" stroke-width="1" fill="none" opacity="0.7"/>
+ </svg>
+ </div>
+ <p class="eyebrow">Style Study · Vol. IV</p>
+ <h1 class="style-name" id="styleName" contenteditable="true" spellcheck="false">Grandmillennial</h1>
+ <div class="cover-line"></div>
+ <p class="cover-dek">Heirloom patterns, collected color, and rooms that feel inherited — not staged.</p>
+ </section>
+
+ <!-- SLIDE 1 -->
+ <section class="slide slide-pair" data-i="1">
+ <div class="pair-top">
+ <div class="swatch pat-chinoiserie" title="Chinoiserie vine"></div>
+ <div class="vignette">
+ <div class="room room-1">
+ <div class="wall"></div>
+ <div class="frame"></div>
+ <div class="frame frame-b"></div>
+ <div class="baseboard"></div>
+ <div class="floor"></div>
+ <div class="lamp"><div class="lamp-shade"></div><div class="lamp-stem"></div></div>
+ <div class="sofa"></div>
+ <div class="table"></div>
+ </div>
+ </div>
+ </div>
+ <div class="pair-note">
+ <span class="note-index">01</span>
+ <div>
+ <span class="note-label">Chinoiserie vine</span>
+ <p class="note-text">Paper one accent wall in trailing florals; ground it with oxblood velvet and a gilt frame pair.</p>
+ </div>
+ </div>
+ </section>
+
+ <!-- SLIDE 2 -->
+ <section class="slide slide-pair" data-i="2">
+ <div class="pair-top">
+ <div class="swatch pat-damask" title="Midnight damask"></div>
+ <div class="vignette">
+ <div class="room room-2">
+ <div class="wall"></div>
+ <div class="bookshelf"></div>
+ <div class="baseboard"></div>
+ <div class="floor"></div>
+ <div class="sofa"></div>
+ <div class="table"></div>
+ </div>
+ </div>
+ </div>
+ <div class="pair-note">
+ <span class="note-index">02</span>
+ <div>
+ <span class="note-label">Midnight damask</span>
+ <p class="note-text">Wrap a library nook in ink-dark damask; let brass hardware and leather spines catch the light.</p>
+ </div>
+ </div>
+ </section>
+
+ <!-- SLIDE 3 -->
+ <section class="slide slide-pair" data-i="3">
+ <div class="pair-top">
+ <div class="swatch pat-botanical" title="Botanical stripe"></div>
+ <div class="vignette">
+ <div class="room room-3">
+ <div class="wall"></div>
+ <div class="window"></div>
+ <div class="baseboard"></div>
+ <div class="floor"></div>
+ <div class="chair-l"></div>
+ <div class="chair-r"></div>
+ <div class="sofa"></div>
+ </div>
+ </div>
+ </div>
+ <div class="pair-note">
+ <span class="note-index">03</span>
+ <div>
+ <span class="note-label">Botanical stripe</span>
+ <p class="note-text">Soft vertical rhythm for a breakfast bay — pair with cane chairs and a single rose-madder runner.</p>
+ </div>
+ </div>
+ </section>
+
+ <!-- CTA -->
+ <section class="slide slide-cta" data-i="4">
+ <div class="cta-mark"></div>
+ <h2 class="cta-title">Bring it home</h2>
+ <p class="cta-body">Request sample cuttings in your edited palette. Style name is live — click the cover title to rename.</p>
+ <p class="edit-hint">Tap a chip to recolor accent</p>
+ <div class="palette-row" id="paletteRow" aria-label="Accent palette">
+ <button class="swatch-dot is-active" data-accent="#9a3b4a" data-gold="#b8956c" style="background:#9a3b4a" title="Rose madder"></button>
+ <button class="swatch-dot" data-accent="#2f4a3c" data-gold="#c4a574" style="background:#2f4a3c" title="Deep sage"></button>
+ <button class="swatch-dot" data-accent="#3d4a56" data-gold="#c9a961" style="background:#3d4a56" title="Slate"></button>
+ <button class="swatch-dot" data-accent="#6b3f2a" data-gold="#d4b896" style="background:#6b3f2a" title="Cognac"></button>
+ <button class="swatch-dot" data-accent="#1c1a17" data-gold="#b8956c" style="background:#1c1a17" title="Near black"></button>
+ </div>
+ <button class="cta-btn" id="ctaBtn" type="button">Request samples</button>
+ </section>
+
+ </div>
+ </div>
+
+ <div class="toast" id="toast" role="status">Samples noted — we'll be in touch</div>
+
+ <div class="chrome">
+ <div class="dots" id="dots" role="tablist" aria-label="Slides"></div>
+ <div class="nav-btns">
+ <button class="nav-btn" id="prev" type="button">Prev</button>
+ <button class="nav-btn" id="next" type="button">Next</button>
+ </div>
+ </div>
+ </div>
+</main>
+
+<script>
+(function () {
+ const track = document.getElementById('track');
+ const slides = Array.from(document.querySelectorAll('.slide'));
+ const dotsWrap = document.getElementById('dots');
+ const prev = document.getElementById('prev');
+ const next = document.getElementById('next');
+ const carousel = document.getElementById('carousel');
+ const toast = document.getElementById('toast');
+ const ctaBtn = document.getElementById('ctaBtn');
+ const root = document.documentElement;
+ let i = 0;
+ const n = slides.length;
+
+ // dots
+ slides.forEach((_, idx) => {
+ const b = document.createElement('button');
+ b.className = 'dot';
+ b.type = 'button';
+ b.setAttribute('role', 'tab');
+ b.setAttribute('aria-label', 'Slide ' + (idx + 1));
+ b.addEventListener('click', () => go(idx));
+ dotsWrap.appendChild(b);
+ });
+ const dots = Array.from(dotsWrap.children);
+
+ function go(to) {
+ i = Math.max(0, Math.min(n - 1, to));
+ track.style.transform = 'translateX(' + (-i * 100) + '%)';
+ slides.forEach((s, k) => s.classList.toggle('is-active', k === i));
+ dots.forEach((d, k) => d.setAttribute('aria-current', k === i ? 'true' : 'false'));
+ prev.disabled = i === 0;
+ next.disabled = i === n - 1;
+ }
+
+ prev.addEventListener('click', () => go(i - 1));
+ next.addEventListener('click', () => go(i + 1));
+
+ // swipe
+ let x0 = null, dx = 0, dragging = false;
+ const threshold = 48;
+
+ function onStart(x) {
+ x0 = x;
+ dragging = true;
+ track.style.transition = 'none';
+ }
+ function onMove(x) {
+ if (!dragging || x0 === null) return;
+ dx = x - x0;
+ const pct = (dx / carousel.offsetWidth) * 100;
+ track.style.transform = 'translateX(calc(' + (-i * 100) + '% + ' + pct + '%))';
+ }
+ function onEnd() {
+ if (!dragging) return;
+ track.style.transition = '';
+ if (dx > threshold) go(i - 1);
+ else if (dx < -threshold) go(i + 1);
+ else go(i);
+ x0 = null; dx = 0; dragging = false;
+ }
+
+ carousel.addEventListener('touchstart', e => onStart(e.touches[0].clientX), { passive: true });
+ carousel.addEventListener('touchmove', e => onMove(e.touches[0].clientX), { passive: true });
+ carousel.addEventListener('touchend', onEnd);
+ carousel.addEventListener('mousedown', e => { e.preventDefault(); onStart(e.clientX); });
+ window.addEventListener('mousemove', e => onMove(e.clientX));
+ window.addEventListener('mouseup', onEnd);
+
+ // keyboard
+ window.addEventListener('keydown', e => {
+ if (e.key === 'ArrowRight') go(i + 1);
+ if (e.key === 'ArrowLeft') go(i - 1);
+ });
+
+ // palette chips
+ document.getElementById('paletteRow').addEventListener('click', e => {
+ const btn = e.target.closest('.swatch-dot');
+ if (!btn) return;
+ document.querySelectorAll('.swatch-dot').forEach(d => d.classList.remove('is-active'));
+ btn.classList.add('is-active');
+ root.style.setProperty('--accent', btn.dataset.accent);
+ root.style.setProperty('--gold', btn.dataset.gold);
+ });
+
+ // CTA toast
+ let toastTimer;
+ ctaBtn.addEventListener('click', () => {
+ const name = (document.getElementById('styleName').textContent || 'Grandmillennial').trim();
+ toast.textContent = name + ' · samples requested';
+ toast.classList.add('show');
+ clearTimeout(toastTimer);
+ toastTimer = setTimeout(() => toast.classList.remove('show'), 2600);
+ });
+
+ go(0);
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/grok.png b/data/artifacts/70eea6613a73/grok.png
new file mode 100644
index 0000000..e527fdb
Binary files /dev/null and b/data/artifacts/70eea6613a73/grok.png differ
diff --git a/data/artifacts/70eea6613a73/hermes3-8b.html b/data/artifacts/70eea6613a73/hermes3-8b.html
new file mode 100644
index 0000000..ecf68a3
--- /dev/null
+++ b/data/artifacts/70eea6613a73/hermes3-8b.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Grandmillennial Lookbook</title>
+<style>
+:root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #1c1a17;
+ --muted: #9b948a;
+ --accent-base: #7d6a45;
+ --accent-hover: #c9a961;
+ --line: rgba(0, 0, 0, .12);
+ --shadow-light: rgba(255, 255, 255, .15);
+ --ease-in-out-quart: cubic-bezier(.165, .84, .44, 1);
+ font-family: -apple-system, "Segoe UI", Helvetica Neue, Arial, sans-serif;
+}
+body {
+ background-color: var(--bg);
+ color: var(--text);
+ margin: 0;
+ padding: 64px;
+ font-size: 16px;
+}
+h1 {
+ display: block;
+ font-family: 'Didot', "Bodoni MT", "Playfair Display", Georgia, serif;
+ color: var(--bg);
+ background-color: var(--text);
+ text-align: center;
+ letter-spacing: .15em;
+ padding: 32px 0;
+}
+header {
+ display: flex;
+ align-items: center;
+ font-family: 'Didot', "Bodoni MT", "Playfair Display", Georgia, serif;
+ color: var(--bg);
+ background-color: var(--text);
+ letter-spacing: .18em;
+ padding: 0 32px;
+}
+.wordmark {
+ font-size: 50px;
+ flex-grow: 1;
+}
+nav {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-left: 24px;
+ color: var(--surface);
+ background-color: var(--muted);
+}
+a, button {
+ font-family: -apple-system, "Segoe UI", Helvetica Neue, Arial, sans-serif;
+ text-transform: uppercase;
+ letter-spacing: .15em;
+ padding: 8px 16px;
+ border-radius: 14px;
+ margin-left: 12px;
+ background-color: var(--surface);
+ color: var(--muted);
+ transition: background-color .3s, color .3s;
+}
+a:hover, button:hover {
+ background-color: var(--accent-hover);
+ color: var(--bg);
+}
+section {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 96px 0;
+}
+.card {
+ flex-basis: calc(33% - 24px);
+ margin-right: 24px;
+ border-radius: 14px;
+ overflow: hidden;
+ box-shadow: 0 8px 24px var(--line), 0 16px 48px rgba(var(--text), .18);
+ transition: transform .7s var(--ease-in-out-quart), box-shadow .3s, opacity .6s;
+}
+.card img {
+ width: 100%;
+ display: block;
+ transition: opacity .4s;
+}
+.card:hover {
+ transform: translateY(-8px);
+ box-shadow: 0 16px 48px rgba(var(--text), .18);
+ opacity: .9;
+}
+.note {
+ position: relative;
+ z-index: 1;
+ background-color: var(--surface);
+ color: var(--muted);
+ padding: 24px;
+ box-shadow: 0 0 24px var(--accent-base) var(--shadow-light);
+}
+.note::before {
+ content: '';
+ position: absolute;
+ top: -8px; left: 0;
+ width: 100%;
+ height: 14px;
+ background-color: var(--muted);
+ box-shadow: 0 8px 24px var(--line);
+}
+.cta {
+ text-align: center;
+ margin-top: 64px;
+}
+.cta a {
+ font-size: 38px;
+ display: block;
+ width: 100%;
+ background-color: var(--accent-base);
+ color: var(--surface);
+ padding: 24px 0;
+ border-radius: 14px;
+}
+@media (max-width: 768px) {
+ h1, header, .card, .cta a {
+ font-size: calc(12px + (20 - 12) * ((100vw - 320px) / 384))
+ }
+}
+</style>
+<body>
+<header class="wordmark">DESIGNER WALLCOVERINGS</header>
+<nav><a href="#">Home</a> | <button>Shop</button></nav>
+<h1>Grandmillennial Lookbook</h1>
+<section>
+ <div class="card">
+ <img src="#grandmillennial" alt="">
+ <div class="note">CLASSIC PATTERNS<br>FOR TIMELESS SPACES</div>
+ </div>
+ <div class="card">
+ <img src="#vibrant-vignette" alt="">
+ <div class="note">ELEGANT COLORS<br>MIXED WITH MODERN FUNK</div>
+ </div>
+ <div class="card">
+ <img src="#cozy-combo" alt="">
+ <div class="note">COMFORTING TEXTURES<br>AND DELICATE DETAILS</div>
+ </div>
+</section>
+<div class="cta"><a href="#">EXPLORE MORE LOOKBOOKS</a></div>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/hermes3-8b.png b/data/artifacts/70eea6613a73/hermes3-8b.png
new file mode 100644
index 0000000..50f019b
Binary files /dev/null and b/data/artifacts/70eea6613a73/hermes3-8b.png differ
diff --git a/data/artifacts/70eea6613a73/hf-qwen-coder-32b.html b/data/artifacts/70eea6613a73/hf-qwen-coder-32b.html
new file mode 100644
index 0000000..3e3f457
--- /dev/null
+++ b/data/artifacts/70eea6613a73/hf-qwen-coder-32b.html
@@ -0,0 +1,204 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Grandmillennial Lookbook</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #1c1a17;
+ --muted: #9b948a;
+ --accent: #b0472e;
+ --line: #dcdcdc;
+ --shadow: rgba(0, 0, 0, .12);
+ --hover-shadow: rgba(0, 0, 0, .18);
+ --glow: rgba(176, 71, 46, .35);
+ --ease: cubic-bezier(.22, 1, .36, 1);
+ }
+ body {
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ background-color: var(--bg);
+ color: var(--text);
+ margin: 0;
+ padding: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ }
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ background-color: var(--bg);
+ padding: 24px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, .06);
+ z-index: 10;
+ }
+ header h1 {
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 50px;
+ letter-spacing: .18em;
+ text-transform: uppercase;
+ margin: 0;
+ color: var(--text);
+ }
+ .carousel {
+ position: relative;
+ width: 90%;
+ max-width: 1200px;
+ overflow: hidden;
+ border-radius: 14px;
+ box-shadow: var(--shadow);
+ }
+ .carousel-inner {
+ display: flex;
+ transition: transform .7s var(--ease);
+ }
+ .slide {
+ min-width: 100%;
+ padding: 96px 24px;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background-color: var(--surface);
+ text-align: center;
+ }
+ .slide h2 {
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 38px;
+ margin-bottom: 48px;
+ }
+ .slide p {
+ font-size: 16px;
+ color: var(--muted);
+ margin-bottom: 48px;
+ }
+ .pattern-swatch {
+ width: 200px;
+ height: 200px;
+ background-image: linear-gradient(45deg, #b0472e, #2f4c39);
+ border-radius: 14px;
+ box-shadow: var(--shadow);
+ margin-bottom: 48px;
+ }
+ .room-vignette {
+ width: 100%;
+ max-width: 600px;
+ height: 400px;
+ background-color: var(--muted);
+ border-radius: 14px;
+ box-shadow: var(--shadow);
+ margin-bottom: 24px;
+ }
+ .room-vignette::before {
+ content: '';
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ background-image: linear-gradient(90deg, rgba(255, 255, 255, .1), rgba(255, 255, 255, .3));
+ }
+ .dots {
+ display: flex;
+ justify-content: center;
+ margin-top: 48px;
+ }
+ .dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background-color: var(--muted);
+ margin: 0 8px;
+ cursor: pointer;
+ transition: background-color .3s ease-in-out;
+ }
+ .dot.active {
+ background-color: var(--accent);
+ }
+ </style>
+</head>
+<body>
+ <header>
+ <h1>DESIGNER WALLCOVERINGS</h1>
+ </header>
+ <div class="carousel">
+ <div class="carousel-inner" id="carouselInner">
+ <div class="slide">
+ <h2>GRANDMILLENNIAL</h2>
+ <p>A design style that blends timeless elegance with modern sophistication, perfect for those who appreciate the charm of classic aesthetics.</p>
+ </div>
+ <div class="slide">
+ <div class="pattern-swatch"></div>
+ <div class="room-vignette" style="background-image: linear-gradient(135deg, #f7efe6, #fff9f1);"></div>
+ <p>Subtle textures and warm hues create a cozy yet chic ambiance.</p>
+ </div>
+ <div class="slide">
+ <div class="pattern-swatch" style="background-image: linear-gradient(45deg, #c65f38, #e0a458);"></div>
+ <div class="room-vignette" style="background-image: linear-gradient(90deg, #fff9f1, #f7efe6);"></div>
+ <p>Vivid colors and rich patterns add a touch of opulence to your space.</p>
+ </div>
+ <div class="slide">
+ <div class="pattern-swatch" style="background-image: linear-gradient(135deg, #b0472e, #2f4c39);"></div>
+ <div class="room-vignette" style="background-image: linear-gradient(45deg, #fff9f1, #f7efe6);"></div>
+ <p>Neutral tones and earthy elements bring a sense of calm and balance.</p>
+ </div>
+ <div class="slide">
+ <h2>ELEVATE YOUR SPACE</h2>
+ <p>Discover more luxurious wallcoverings that reflect your personal style.</p>
+ </div>
+ </div>
+ <div class="dots" id="dotsContainer"></div>
+ </div>
+ <script>
+ const slides = document.querySelectorAll('.slide');
+ const dotsContainer = document.getElementById('dotsContainer');
+ let currentSlideIndex = 0;
+
+ function createDots() {
+ slides.forEach((_, index) => {
+ const dot = document.createElement('div');
+ dot.classList.add('dot');
+ dot.addEventListener('click', () => goToSlide(index));
+ dotsContainer.appendChild(dot);
+ });
+ updateActiveDot();
+ }
+
+ function updateActiveDot() {
+ const dots = document.querySelectorAll('.dot');
+ dots.forEach((dot, index) => {
+ if (index === currentSlideIndex) {
+ dot.classList.add('active');
+ } else {
+ dot.classList.remove('active');
+ }
+ });
+ }
+
+ function goToSlide(index) {
+ currentSlideIndex = index;
+ const offset = -currentSlideIndex * 100 + '%';
+ document.querySelector('.carousel-inner').style.transform = `translateX(${offset})`;
+ updateActiveDot();
+ }
+
+ function nextSlide() {
+ if (currentSlideIndex < slides.length - 1) {
+ currentSlideIndex++;
+ } else {
+ currentSlideIndex = 0;
+ }
+ goToSlide(currentSlideIndex);
+ }
+
+ createDots();
+
+ setInterval(nextSlide, 5000);
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/hf-qwen-coder-32b.png b/data/artifacts/70eea6613a73/hf-qwen-coder-32b.png
new file mode 100644
index 0000000..bcfc686
Binary files /dev/null and b/data/artifacts/70eea6613a73/hf-qwen-coder-32b.png differ
diff --git a/data/artifacts/70eea6613a73/kimi.html b/data/artifacts/70eea6613a73/kimi.html
new file mode 100644
index 0000000..902456f
--- /dev/null
+++ b/data/artifacts/70eea6613a73/kimi.html
@@ -0,0 +1,1041 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Grandmillennial Lookbook | Designer Wallcoverings</title>
+<style>
+/* DESIGN TOKENS */
+:root {
+ /* Grandmillennial Luxury Palette */
+ --bg: #f7f5f0;
+ --surface: #ffffff;
+ --ink: #1c1a17;
+ --muted: #8b8178;
+ --accent: #2d5a4a; /* Botanical green */
+ --accent-warm: #c9a86c; /* Antique gold */
+ --line: #d4cfc4;
+ --shadow: rgba(28, 26, 23, 0.08);
+ --shadow-deep: rgba(28, 26, 23, 0.15);
+
+ /* Typography */
+ --font-display: "Didot", "Bodoni MT", "Playfair Display", Georgia, serif;
+ --font-body: -apple-system, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
+
+ /* Motion */
+ --ease-swift: cubic-bezier(.22,.9,.24,1);
+ --ease-power: cubic-bezier(.77,0,.18,1);
+ --ease-quint: cubic-bezier(.22,1,.36,1);
+
+ /* Spacing */
+ --space-xs: 8px;
+ --space-sm: 16px;
+ --space-md: 24px;
+ --space-lg: 40px;
+ --space-xl: 64px;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html {
+ font-size: 16px;
+}
+
+body {
+ font-family: var(--font-body);
+ background: var(--bg);
+ color: var(--ink);
+ line-height: 1.6;
+ overflow-x: hidden;
+}
+
+/* HEADER / WORDMARK */
+header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 100;
+ background: var(--surface);
+ border-bottom: 1px solid var(--line);
+ padding: var(--space-sm) var(--space-md);
+ display: flex;
+ align-items: center;
+ height: 72px;
+}
+
+.wordmark {
+ font-family: var(--font-display);
+ font-size: 42px;
+ font-weight: 400;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ line-height: 1.1;
+}
+
+/* CAROUSEL CONTAINER */
+.carousel-container {
+ position: relative;
+ width: 100%;
+ max-width: 480px;
+ margin: 0 auto;
+ padding-top: 72px;
+ height: 100vh;
+ display: flex;
+ flex-direction: column;
+ background: var(--bg);
+}
+
+.carousel-track {
+ position: relative;
+ flex: 1;
+ overflow: hidden;
+}
+
+.carousel-slides {
+ display: flex;
+ height: 100%;
+ transition: transform 500ms var(--ease-swift);
+}
+
+.slide {
+ min-width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ padding: var(--space-md);
+ gap: var(--space-md);
+}
+
+/* DOTS NAVIGATION */
+.carousel-dots {
+ display: flex;
+ justify-content: center;
+ gap: var(--space-sm);
+ padding: var(--space-md);
+ background: var(--surface);
+ border-top: 1px solid var(--line);
+}
+
+.dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--line);
+ border: none;
+ cursor: pointer;
+ transition: all 300ms var(--ease-swift);
+}
+
+.dot.active {
+ background: var(--accent);
+ transform: scale(1.2);
+}
+
+/* SWIPE HINT */
+.swipe-hint {
+ position: absolute;
+ bottom: 80px;
+ left: 50%;
+ transform: translateX(-50%);
+ font-family: var(--font-body);
+ font-size: 11px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--muted);
+ opacity: 0.6;
+ pointer-events: none;
+}
+
+/* COVER SLIDE */
+.slide-cover {
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background: var(--surface);
+ position: relative;
+}
+
+.slide-cover::before {
+ content: '';
+ position: absolute;
+ inset: var(--space-md);
+ border: 1px solid var(--line);
+ pointer-events: none;
+}
+
+.cover-content h1 {
+ font-family: var(--font-display);
+ font-size: 50px;
+ font-weight: 400;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--ink);
+ margin-bottom: var(--space-sm);
+ line-height: 1.1;
+}
+
+.cover-content .subtitle {
+ font-family: var(--font-body);
+ font-size: 14px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: var(--space-lg);
+}
+
+.cover-accent {
+ width: 60px;
+ height: 2px;
+ background: var(--accent);
+ margin: 0 auto var(--space-lg);
+}
+
+.cover-year {
+ font-family: var(--font-display);
+ font-size: 14px;
+ letter-spacing: 0.2em;
+ color: var(--muted);
+ font-style: italic;
+}
+
+/* PATTERN SWATCH + VIGNETTE PAIR */
+.pattern-vignette-pair {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: var(--space-md);
+}
+
+.pattern-swatch {
+ height: 35%;
+ border-radius: 4px;
+ position: relative;
+ overflow: hidden;
+ box-shadow: 0 4px 20px var(--shadow);
+}
+
+.room-vignette {
+ flex: 1;
+ border-radius: 4px;
+ position: relative;
+ overflow: hidden;
+ box-shadow: 0 4px 20px var(--shadow);
+ background: linear-gradient(135deg, #f0ebe3 0%, #e8e2d8 100%);
+}
+
+.styling-note {
+ font-family: var(--font-body);
+ font-size: 13px;
+ letter-spacing: 0.05em;
+ color: var(--muted);
+ text-align: center;
+ font-style: italic;
+ padding: var(--space-sm) 0;
+ border-top: 1px solid var(--line);
+}
+
+/* GRANDMILLENNIAL PATTERNS */
+
+/* Pattern 1: Chintz Floral */
+.pattern-chintz {
+ background:
+ radial-gradient(circle at 30% 30%, rgba(194, 140, 140, 0.4) 0%, transparent 50%),
+ radial-gradient(circle at 70% 60%, rgba(140, 170, 130, 0.3) 0%, transparent 45%),
+ radial-gradient(circle at 40% 80%, rgba(200, 160, 120, 0.35) 0%, transparent 40%),
+ radial-gradient(circle at 80% 20%, rgba(180, 140, 160, 0.3) 0%, transparent 50%),
+ radial-gradient(circle at 20% 70%, rgba(140, 160, 140, 0.35) 0%, transparent 45%),
+ radial-gradient(circle at 60% 40%, rgba(190, 150, 140, 0.25) 0%, transparent 40%),
+ linear-gradient(45deg, #f5f0e8 0%, #ebe4d8 100%);
+ position: relative;
+}
+
+.pattern-chintz::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image:
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 120 120'%3E%3Cg fill='none' stroke='%232d5a4a' stroke-width='0.5' opacity='0.3'%3E%3Cpath d='M20 60c0-20 20-35 40-35s40 15 40 35-20 35-40 35-40-15-40-35z'/%3E%3Cpath d='M60 20c20 0 35 20 35 40s-15 40-35 40-35-15-35-40 15-40 35-40z'/%3E%3Ccircle cx='60' cy='60' r='8' fill='%23c9a86c' opacity='0.4'/%3E%3C/g%3E%3C/svg%3E");
+ opacity: 0.6;
+}
+
+/* Pattern 2: Chinese Chippendale Lattice */
+.pattern-lattice {
+ background:
+ repeating-linear-gradient(
+ 45deg,
+ transparent,
+ transparent 10px,
+ rgba(45, 90, 74, 0.1) 10px,
+ rgba(45, 90, 74, 0.1) 11px
+ ),
+ repeating-linear-gradient(
+ -45deg,
+ transparent,
+ transparent 10px,
+ rgba(45, 90, 74, 0.1) 10px,
+ rgba(45, 90, 74, 0.1) 11px
+ ),
+ #f7f5f0;
+ position: relative;
+}
+
+.pattern-lattice::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image:
+ url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 80 80'%3E%3Cpath d='M0 0h80v80H0z' fill='none'/%3E%3Cpath d='M0 40 L40 0 L80 40 L40 80 Z' fill='none' stroke='%232d5a4a' stroke-width='1.5' opacity='0.25'/%3E%3Ccircle cx='40' cy='40' r='12' fill='none' stroke='%23c9a86c' stroke-width='1' opacity='0.4'/%3E%3C/svg%3E");
+ opacity: 0.8;
+}
+
+/* Pattern 3: Ticking Stripe */
+.pattern-ticking {
+ background:
+ repeating-linear-gradient(
+ 90deg,
+ #f7f5f0,
+ #f7f5f0 8px,
+ #2d5a4a 8px,
+ #2d5a4a 10px,
+ #f7f5f0 10px,
+ #f7f5f0 18px,
+ #1c1a17 18px,
+ #1c1a17 19px,
+ #f7f5f0 19px,
+ #f7f5f0 40px
+ );
+ position: relative;
+}
+
+/* ROOM VIGNETTES (CSS-DRAWN) */
+
+/* Vignette 1: Chintz Living Room */
+.vignette-chintz {
+ position: relative;
+ background: linear-gradient(180deg, #e8e2d8 0%, #d8d0c4 100%);
+}
+
+.vignette-chintz .wall {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 65%;
+ background:
+ radial-gradient(circle at 20% 40%, rgba(194, 140, 140, 0.2) 0%, transparent 30%),
+ radial-gradient(circle at 80% 30%, rgba(140, 170, 130, 0.15) 0%, transparent 25%),
+ radial-gradient(circle at 50% 60%, rgba(200, 160, 120, 0.2) 0%, transparent 35%),
+ #f0ebe3;
+}
+
+.vignette-chintz .floor {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 35%;
+ background:
+ repeating-linear-gradient(
+ 0deg,
+ #c4b8a8,
+ #c4b8a8 2px,
+ #b8aa98 2px,
+ #b8aa98 20px
+ );
+}
+
+.vignette-chintz .sofa {
+ position: absolute;
+ bottom: 25%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 140px;
+ height: 80px;
+ background: #8b4513;
+ border-radius: 8px 8px 0 0;
+ box-shadow: 0 -4px 0 rgba(0,0,0,0.1) inset;
+}
+
+.vignette-chintz .sofa::before {
+ content: '';
+ position: absolute;
+ top: -20px;
+ left: 10px;
+ right: 10px;
+ height: 30px;
+ background: #a0522d;
+ border-radius: 10px 10px 0 0;
+}
+
+.vignette-chintz .lamp {
+ position: absolute;
+ bottom: 30%;
+ right: 15%;
+ width: 40px;
+ height: 100px;
+}
+
+.vignette-chintz .lamp-shade {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 50px;
+ height: 35px;
+ background: #f5f2ea;
+ border-radius: 50% 50% 10% 10%;
+ box-shadow: 0 2px 8px var(--shadow);
+}
+
+.vignette-chintz .lamp-base {
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 8px;
+ height: 65px;
+ background: var(--accent-warm);
+}
+
+.vignette-chintz .plant {
+ position: absolute;
+ bottom: 30%;
+ left: 10%;
+ width: 50px;
+ height: 80px;
+}
+
+.vignette-chintz .plant-pot {
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 30px;
+ height: 25px;
+ background: #8b7355;
+ border-radius: 0 0 5px 5px;
+}
+
+.vignette-chintz .plant-leaves {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 40px;
+ height: 55px;
+ background:
+ radial-gradient(ellipse at 30% 20%, #4a7c59 0%, transparent 50%),
+ radial-gradient(ellipse at 70% 40%, #5a8c69 0%, transparent 50%),
+ radial-gradient(ellipse at 50% 80%, #3a6c49 0%, transparent 50%);
+ border-radius: 50%;
+}
+
+/* Vignette 2: Lattice Dining Room */
+.vignette-lattice {
+ position: relative;
+ background: linear-gradient(180deg, #e8e2d8 0%, #d8d0c4 100%);
+}
+
+.vignette-lattice .wall {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 70%;
+ background:
+ repeating-linear-gradient(
+ 45deg,
+ transparent,
+ transparent 15px,
+ rgba(45, 90, 74, 0.08) 15px,
+ rgba(45, 90, 74, 0.08) 16px
+ ),
+ repeating-linear-gradient(
+ -45deg,
+ transparent,
+ transparent 15px,
+ rgba(45, 90, 74, 0.08) 15px,
+ rgba(45, 90, 74, 0.08) 16px
+ ),
+ #f5f0e8;
+}
+
+.vignette-lattice .floor {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 30%;
+ background: #b8a898;
+}
+
+.vignette-lattice .table {
+ position: absolute;
+ bottom: 25%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 120px;
+ height: 70px;
+ background: #6b4423;
+ border-radius: 60px 60px 0 0;
+ box-shadow: 0 8px 20px var(--shadow-deep);
+}
+
+.vignette-lattice .table::before {
+ content: '';
+ position: absolute;
+ top: -10px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 100px;
+ height: 20px;
+ background: #7d5432;
+ border-radius: 50%;
+}
+
+.vignette-lattice .chair {
+ position: absolute;
+ bottom: 28%;
+ width: 35px;
+ height: 60px;
+ background: #8b4513;
+ border-radius: 5px 5px 0 0;
+}
+
+.vignette-lattice .chair:nth-child(3) { left: 15%; }
+.vignette-lattice .chair:nth-child(4) { right: 15%; }
+
+.vignette-lattice .chair::before {
+ content: '';
+ position: absolute;
+ top: -15px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 30px;
+ height: 20px;
+ background: #a0522d;
+ border-radius: 5px 5px 0 0;
+}
+
+.vignette-lattice .chandelier {
+ position: absolute;
+ top: 10%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 60px;
+ height: 80px;
+}
+
+.vignette-lattice .chandelier-chain {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 2px;
+ height: 30px;
+ background: var(--accent-warm);
+}
+
+.vignette-lattice .chandelier-body {
+ position: absolute;
+ top: 30px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 40px;
+ height: 40px;
+ background:
+ radial-gradient(circle at 30% 30%, var(--accent-warm) 0%, transparent 30%),
+ radial-gradient(circle at 70% 30%, var(--accent-warm) 0%, transparent 30%),
+ radial-gradient(circle at 50% 70%, var(--accent-warm) 0%, transparent 30%);
+ opacity: 0.8;
+}
+
+/* Vignette 3: Stripe Bedroom */
+.vignette-stripe {
+ position: relative;
+ background: linear-gradient(180deg, #e8e2d8 0%, #d8d0c4 100%);
+}
+
+.vignette-stripe .wall {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 60%;
+ background:
+ repeating-linear-gradient(
+ 90deg,
+ #f7f5f0,
+ #f7f5f0 15px,
+ #2d5a4a 15px,
+ #2d5a4a 17px,
+ #f7f5f0 17px,
+ #f7f5f0 35px,
+ #1c1a17 35px,
+ #1c1a17 36px,
+ #f7f5f0 36px,
+ #f7f5f0 70px
+ ),
+ #f5f0e8;
+ opacity: 0.9;
+}
+
+.vignette-stripe .floor {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 40%;
+ background:
+ linear-gradient(180deg, #c4b8a8 0%, #b8aa98 100%);
+}
+
+.vignette-stripe .bed {
+ position: absolute;
+ bottom: 30%;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 160px;
+ height: 90px;
+ background: #fff;
+ border-radius: 5px;
+ box-shadow: 0 4px 15px var(--shadow-deep);
+}
+
+.vignette-stripe .bed-headboard {
+ position: absolute;
+ top: -40px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 140px;
+ height: 50px;
+ background:
+ linear-gradient(90deg,
+ #8b4513 0%,
+ #a0522d 20%,
+ #8b4513 40%,
+ #a0522d 60%,
+ #8b4513 80%,
+ #a0522d 100%
+ );
+ border-radius: 10px 10px 0 0;
+}
+
+.vignette-stripe .pillow {
+ position: absolute;
+ top: 10px;
+ width: 45px;
+ height: 30px;
+ background: #f5f2ea;
+ border-radius: 8px;
+ box-shadow: 0 2px 5px var(--shadow);
+}
+
+.vignette-stripe .pillow:nth-child(2) { left: 20px; }
+.vignette-stripe .pillow:nth-child(3) { right: 20px; }
+
+.vignette-stripe .blanket {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 50px;
+ background:
+ repeating-linear-gradient(
+ 0deg,
+ #2d5a4a,
+ #2d5a4a 8px,
+ #f7f5f0 8px,
+ #f7f5f0 16px
+ );
+ border-radius: 0 0 5px 5px;
+}
+
+.vignette-stripe .side-table {
+ position: absolute;
+ bottom: 32%;
+ right: 8%;
+ width: 35px;
+ height: 45px;
+ background: #6b4423;
+ border-radius: 3px;
+}
+
+.vignette-stripe .lamp-small {
+ position: absolute;
+ bottom: 55%;
+ right: 10%;
+ width: 25px;
+ height: 50px;
+}
+
+.vignette-stripe .lamp-small-shade {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 30px;
+ height: 20px;
+ background: #f5f2ea;
+ border-radius: 40% 40% 10% 10%;
+}
+
+.vignette-stripe .lamp-small-base {
+ position: absolute;
+ bottom: 0;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 4px;
+ height: 30px;
+ background: var(--accent-warm);
+}
+
+/* CTA SLIDE */
+.slide-cta {
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ background: var(--surface);
+ position: relative;
+}
+
+.slide-cta::before {
+ content: '';
+ position: absolute;
+ inset: var(--space-md);
+ border: 1px solid var(--line);
+ pointer-events: none;
+}
+
+.cta-content {
+ padding: var(--space-xl);
+}
+
+.cta-content h2 {
+ font-family: var(--font-display);
+ font-size: 38px;
+ font-weight: 400;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: var(--ink);
+ margin-bottom: var(--space-sm);
+ line-height: 1.1;
+}
+
+.cta-content p {
+ font-family: var(--font-body);
+ font-size: 14px;
+ color: var(--muted);
+ margin-bottom: var(--space-lg);
+ letter-spacing: 0.02em;
+}
+
+.cta-button {
+ display: inline-block;
+ padding: var(--space-sm) var(--space-lg);
+ background: var(--ink);
+ color: var(--surface);
+ font-family: var(--font-body);
+ font-size: 11px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ text-decoration: none;
+ border-radius: 2px;
+ transition: all 300ms var(--ease-swift);
+ border: 1px solid var(--ink);
+}
+
+.cta-button:hover {
+ background: transparent;
+ color: var(--ink);
+}
+
+.cta-accent {
+ width: 40px;
+ height: 1px;
+ background: var(--accent);
+ margin: var(--space-lg) auto;
+}
+
+/* EDITABLE STYLE NAME */
+.editable-title {
+ cursor: text;
+ border-bottom: 1px solid transparent;
+ transition: border-color 200ms;
+}
+
+.editable-title:hover {
+ border-bottom-color: var(--line);
+}
+
+.editable-title:focus {
+ outline: none;
+ border-bottom-color: var(--accent);
+}
+
+/* SLIDE TRANSITION ANIMATIONS */
+.slide-enter {
+ opacity: 0;
+ transform: translateX(30px);
+}
+
+.slide-enter-active {
+ opacity: 1;
+ transform: translateX(0);
+ transition: all 600ms var(--ease-quint);
+}
+
+/* PATTERN LABELS (Minimal, elegant) */
+.pattern-label {
+ position: absolute;
+ bottom: var(--space-sm);
+ left: var(--space-sm);
+ font-family: var(--font-body);
+ font-size: 10px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--ink);
+ background: rgba(247, 245, 240, 0.9);
+ padding: 4px 8px;
+ border-radius: 2px;
+}
+
+/* RESPONSIVE */
+@media (max-width: 480px) {
+ .wordmark {
+ font-size: 36px;
+ }
+
+ .cover-content h1 {
+ font-size: 42px;
+ }
+
+ .cta-content h2 {
+ font-size: 32px;
+ }
+}
+
+@media (max-width: 380px) {
+ .wordmark {
+ font-size: 32px;
+ }
+
+ .cover-content h1 {
+ font-size: 36px;
+ }
+}
+</style>
+</head>
+<body>
+
+<header>
+ <div class="wordmark">Designer Wallcoverings</div>
+</header>
+
+<div class="carousel-container">
+ <div class="carousel-track">
+ <div class="carousel-slides" id="track">
+
+ <!-- Slide 1: Cover -->
+ <div class="slide slide-cover">
+ <div class="cover-content">
+ <div class="cover-accent"></div>
+ <h1 class="editable-title" contenteditable="true">Grandmillennial</h1>
+ <p class="subtitle">The New Traditional</p>
+ <p class="cover-year">Est. MMXXV</p>
+ </div>
+ </div>
+
+ <!-- Slide 2: Chintz -->
+ <div class="slide">
+ <div class="pattern-vignette-pair">
+ <div class="pattern-swatch pattern-chintz">
+ <span class="pattern-label">English Chintz</span>
+ </div>
+ <div class="room-vignette vignette-chintz">
+ <div class="wall"></div>
+ <div class="floor"></div>
+ <div class="plant">
+ <div class="plant-leaves"></div>
+ <div class="plant-pot"></div>
+ </div>
+ <div class="sofa"></div>
+ <div class="lamp">
+ <div class="lamp-base"></div>
+ <div class="lamp-shade"></div>
+ </div>
+ </div>
+ </div>
+ <p class="styling-note">"Layer florals on cream grounds with honey-toned woods"</p>
+ </div>
+
+ <!-- Slide 3: Lattice -->
+ <div class="slide">
+ <div class="pattern-vignette-pair">
+ <div class="pattern-swatch pattern-lattice">
+ <span class="pattern-label">Chippendale Lattice</span>
+ </div>
+ <div class="room-vignette vignette-lattice">
+ <div class="wall"></div>
+ <div class="floor"></div>
+ <div class="chair"></div>
+ <div class="table"></div>
+ <div class="chair"></div>
+ <div class="chandelier">
+ <div class="chandelier-chain"></div>
+ <div class="chandelier-body"></div>
+ </div>
+ </div>
+ </div>
+ <p class="styling-note">"Fretwork patterns bring architectural elegance to dining spaces"</p>
+ </div>
+
+ <!-- Slide 4: Ticking -->
+ <div class="slide">
+ <div class="pattern-vignette-pair">
+ <div class="pattern-swatch pattern-ticking">
+ <span class="pattern-label">Botanical Ticking</span>
+ </div>
+ <div class="room-vignette vignette-stripe">
+ <div class="wall"></div>
+ <div class="floor"></div>
+ <div class="bed">
+ <div class="bed-headboard"></div>
+ <div class="pillow"></div>
+ <div class="pillow"></div>
+ <div class="blanket"></div>
+ </div>
+ <div class="side-table"></div>
+ <div class="lamp-small">
+ <div class="lamp-small-base"></div>
+ <div class="lamp-small-shade"></div>
+ </div>
+ </div>
+ </div>
+ <p class="styling-note">"Classic stripes in forest green feel fresh, not farmhouse"</p>
+ </div>
+
+ <!-- Slide 5: CTA -->
+ <div class="slide slide-cta">
+ <div class="cta-content">
+ <h2>Curate Your<br>Collection</h2>
+ <div class="cta-accent"></div>
+ <p>Discover 200+ heritage patterns<br>reimagined for today</p>
+ <a href="#" class="cta-button" onclick="event.preventDefault(); alert('Visit designerwallcoverings.com');">Explore Lookbook</a>
+ </div>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="swipe-hint">Swipe to explore</div>
+
+ <div class="carousel-dots" id="dots">
+ <button class="dot active" data-index="0"></button>
+ <button class="dot" data-index="1"></button>
+ <button class="dot" data-index="2"></button>
+ <button class="dot" data-index="3"></button>
+ <button class="dot" data-index="4"></button>
+ </div>
+</div>
+
+<script>
+(function() {
+ const track = document.getElementById('track');
+ const dots = document.querySelectorAll('.dot');
+ const slides = document.querySelectorAll('.slide');
+ let currentIndex = 0;
+ let startX = 0;
+ let isDragging = false;
+
+ function goToSlide(index) {
+ if (index < 0) index = 0;
+ if (index >= slides.length) index = slides.length - 1;
+ currentIndex = index;
+
+ track.style.transform = `translateX(-${currentIndex * 100}%)`;
+
+ dots.forEach((dot, i) => {
+ dot.classList.toggle('active', i === currentIndex);
+ });
+ }
+
+ // Dot navigation
+ dots.forEach((dot, i) => {
+ dot.addEventListener('click', () => goToSlide(i));
+ });
+
+ // Touch swipe
+ const container = document.querySelector('.carousel-track');
+
+ container.addEventListener('touchstart', (e) => {
+ startX = e.touches[0].clientX;
+ isDragging = true;
+ });
+
+ container.addEventListener('touchmove', (e) => {
+ if (!isDragging) return;
+ });
+
+ container.addEventListener('touchend', (e) => {
+ if (!isDragging) return;
+ isDragging = false;
+
+ const endX = e.changedTouches[0].clientX;
+ const diff = startX - endX;
+
+ if (Math.abs(diff) > 50) {
+ if (diff > 0) {
+ goToSlide(currentIndex + 1);
+ } else {
+ goToSlide(currentIndex - 1);
+ }
+ }
+ });
+
+ // Mouse drag for desktop
+ container.addEventListener('mousedown', (e) => {
+ startX = e.clientX;
+ isDragging = true;
+ });
+
+ container.addEventListener('mousemove', (e) => {
+ if (!isDragging) return;
+ });
+
+ container.addEventListener('mouseup', (e) => {
+ if (!isDragging) return;
+ isDragging = false;
+
+ const endX = e.clientX;
+ const diff = startX - endX;
+
+ if (Math.abs(diff) > 50) {
+ if (diff > 0) {
+ goToSlide(currentIndex + 1);
+ } else {
+ goToSlide(currentIndex - 1);
+ }
+ }
+ });
+
+ container.addEventListener('mouseleave', () => {
+ isDragging = false;
+ });
+
+ // Keyboard navigation
+ document.addEventListener('keydown', (e) => {
+ if (e.key === 'ArrowRight') goToSlide(currentIndex + 1);
+ if (e.key === 'ArrowLeft') goToSlide(currentIndex - 1);
+ });
+})();
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/kimi.png b/data/artifacts/70eea6613a73/kimi.png
new file mode 100644
index 0000000..51f7eba
Binary files /dev/null and b/data/artifacts/70eea6613a73/kimi.png differ
diff --git a/data/artifacts/70eea6613a73/qwen25-7b.html b/data/artifacts/70eea6613a73/qwen25-7b.html
new file mode 100644
index 0000000..6a57d82
--- /dev/null
+++ b/data/artifacts/70eea6613a73/qwen25-7b.html
@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Grandmillennial Lookbook</title>
+ <style>
+ :root {
+ --bg: #f7efe6;
+ --surface: #fff9f1;
+ --text: #3a2c22;
+ --muted: #a08c7a;
+ --accent: #c65f38;
+ --line: 1px solid var(--text);
+ --shadow: 0 8px 24px rgba(0, 0, 0, .12), hover 0 16px 48px rgba(0, 0, 0, .18);
+ --ease: cubic-bezier(.22,1,.36,1) both;
+ }
+
+ body {
+ margin: 0;
+ padding: 0;
+ background-color: var(--bg);
+ color: var(--text);
+ font-family: 'Didot', 'Bodoni MT', Georgia, serif;
+ overflow-x: hidden;
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ background-color: var(--surface);
+ padding: 24px;
+ color: var(--text);
+ font-size: 48px;
+ text-transform: uppercase;
+ letter-spacing: .15em;
+ }
+
+ .carousel {
+ display: flex;
+ overflow-x: auto;
+ gap: 32px;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .slide {
+ width: 300px;
+ max-height: 480px;
+ background-color: var(--surface);
+ border-radius: 14px;
+ overflow: hidden;
+ flex-shrink: 0;
+ }
+
+ .swatch, .vignette {
+ display: inline-block;
+ width: 150px;
+ height: 300px;
+ margin: auto;
+ background-size: cover;
+ }
+
+ .swatch {
+ box-shadow: var(--shadow);
+ transition: transform .7s var(--ease), box-shadow .7s var(--ease);
+ }
+
+ .vignette {
+ opacity: 1;
+ filter: drop-shadow(0px 8px 24px rgba(0, 0, 0, 0.3));
+ }
+
+ .swatch:hover {
+ transform: translateY(-16px);
+ }
+
+ .title {
+ text-align: center;
+ font-size: 24px;
+ margin-top: 24px;
+ }
+
+ footer {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ background-color: var(--surface);
+ padding: 24px;
+ text-align: center;
+ font-family: 'Didot', 'Bodoni MT', Georgia, serif;
+ }
+
+ .cta {
+ display: inline-block;
+ padding: 16px 32px;
+ margin-top: 24px;
+ background-color: var(--accent);
+ color: #fff;
+ text-decoration: none;
+ font-size: 18px;
+ letter-spacing: .15em;
+ }
+
+ @keyframes fadeUp {
+ from { opacity: 0; transform: translateY(28px); }
+ to { opacity: 1; transform: translateY(0); }
+ }
+
+ section {
+ animation: ambient-bg 18s linear infinite alternate;
+ }
+
+ .fade-up {
+ animation-name: fadeUp;
+ }
+
+ @keyframes ambient-bg {
+ from { background-position: 0%; }
+ to { background-position: -1200%; }
+ }
+ </style>
+</head>
+<body>
+
+<header class="header">
+ <span>DESIGNER WALLCOVERINGS</span>
+</header>
+
+<div class="carousel">
+ <div class="slide fade-up">
+ <div class="swatch" style="background: linear-gradient(to bottom, var(--accent) 0%, rgba(255, 86, 56, 0.7) 100%);"></div>
+ <div class="vignette" style="background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="150" height="300"><rect width="150" height="300" fill="#fff9f1"/></svg>');"></div>
+ <div class="title">Warm Living</div>
+ </div>
+
+ <div class="slide fade-up">
+ <div class="swatch" style="background: linear-gradient(to bottom, var(--accent) 0%, rgba(255, 86, 56, 0.7) 100%);"></div>
+ <div class="vignette" style="background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="150" height="300"><rect width="150" height="300" fill="#fff9f1"/></svg>');"></div>
+ <div class="title">Cozy Corner</div>
+ </div>
+
+ <div class="slide fade-up">
+ <div class="swatch" style="background: linear-gradient(to bottom, var(--accent) 0%, rgba(255, 86, 56, 0.7) 100%);"></div>
+ <div class="vignette" style="background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="150" height="300"><rect width="150" height="300" fill="#fff9f1"/></svg>');"></div>
+ <div class="title">Rustic Retreat</div>
+ </div>
+
+ <footer class="cta">
+ Explore More
+ </footer>
+</div>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/qwen25-7b.png b/data/artifacts/70eea6613a73/qwen25-7b.png
new file mode 100644
index 0000000..5ee874b
Binary files /dev/null and b/data/artifacts/70eea6613a73/qwen25-7b.png differ
diff --git a/data/artifacts/70eea6613a73/qwen3-14b.html b/data/artifacts/70eea6613a73/qwen3-14b.html
new file mode 100644
index 0000000..c5a3c41
--- /dev/null
+++ b/data/artifacts/70eea6613a73/qwen3-14b.html
@@ -0,0 +1,272 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>Design Lookbook</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #1c1a17;
+ --muted: #9b948a;
+ --accent: #b0472e;
+ --line: #e8e5e0;
+ --shadow: 0 0 24px rgba(0, 0, 0, 0.1);
+ --ease: cubic-bezier(0.22, 1, 0.36, 1);
+ }
+
+ * {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ }
+
+ body {
+ background: var(--bg);
+ color: var(--text);
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ line-height: 1.6;
+ overflow-x: hidden;
+ }
+
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ background: var(--surface);
+ padding: 16px 32px;
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 40px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--text);
+ z-index: 1000;
+ }
+
+ .carousel {
+ position: relative;
+ width: 100%;
+ height: 100vh;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: var(--bg);
+ padding-top: 96px;
+ }
+
+ .slide {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ opacity: 0;
+ transform: translateY(28px);
+ transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
+ pointer-events: none;
+ background: var(--surface);
+ box-shadow: var(--shadow);
+ border-radius: 14px;
+ padding: 32px;
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ text-align: center;
+ }
+
+ .slide.active {
+ opacity: 1;
+ transform: translateY(0);
+ pointer-events: auto;
+ }
+
+ .slide h1 {
+ font-size: 48px;
+ margin-bottom: 24px;
+ font-family: 'Playfair Display', Georgia, serif;
+ color: var(--text);
+ }
+
+ .slide .pattern {
+ width: 200px;
+ height: 200px;
+ margin-bottom: 24px;
+ background: repeating-conic-gradient(
+ var(--accent) 0% 25%,
+ var(--muted) 25% 50%,
+ var(--surface) 50% 75%,
+ var(--text) 75% 100%
+ );
+ border: 1px solid var(--line);
+ border-radius: 14px;
+ box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);
+ }
+
+ .slide .room {
+ width: 300px;
+ height: 200px;
+ background: linear-gradient(135deg, var(--surface), var(--bg));
+ border: 1px solid var(--line);
+ border-radius: 14px;
+ box-shadow: 0 0 16px rgba(0, 0, 0, 0.08);
+ margin-bottom: 24px;
+ }
+
+ .slide .note {
+ font-size: 16px;
+ color: var(--muted);
+ margin-bottom: 48px;
+ }
+
+ .slide .cta {
+ font-size: 24px;
+ font-weight: bold;
+ color: var(--accent);
+ cursor: pointer;
+ }
+
+ .dots {
+ position: absolute;
+ bottom: 48px;
+ left: 50%;
+ transform: translateX(-50%);
+ display: flex;
+ gap: 16px;
+ }
+
+ .dot {
+ width: 12px;
+ height: 12px;
+ background: var(--muted);
+ border-radius: 50%;
+ transition: background 0.3s var(--ease);
+ }
+
+ .dot.active {
+ background: var(--accent);
+ }
+
+ @keyframes fadeUp {
+ from {
+ opacity: 0;
+ transform: translateY(28px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ @keyframes drift {
+ 0% { background-position: 0% 50%; }
+ 100% { background-position: 100% 50%; }
+ }
+
+ body {
+ background: linear-gradient(135deg, var(--bg), var(--surface)) fixed;
+ animation: drift 18s linear infinite;
+ }
+ </style>
+</head>
+<body>
+ <header>DESIGNER WALLCOVERINGS</header>
+ <div class="carousel" id="carousel">
+ <div class="slide active" data-index="0">
+ <h1>GRANDMILL ennEIAL</h1>
+ </div>
+ <div class="slide" data-index="1">
+ <h1>Pattern Swatch</h1>
+ <div class="pattern"></div>
+ <div class="room"></div>
+ <div class="note">Soft textures meet refined geometry.</div>
+ </div>
+ <div class="slide" data-index="2">
+ <h1>Pattern Swatch</h1>
+ <div class="pattern" style="background: repeating-linear-gradient(45deg, var(--accent) 0%, var(--muted) 50%, var(--accent) 100%);"></div>
+ <div class="room" style="background: linear-gradient(135deg, var(--surface), var(--bg));"></div>
+ <div class="note">Subtle floral accents in rich tones.</div>
+ </div>
+ <div class="slide" data-index="3">
+ <h1>Pattern Swatch</h1>
+ <div class="pattern" style="background: repeating-radial-gradient(circle at 30% 30%, var(--accent) 0%, var(--muted) 40%, var(--surface) 60%);"></div>
+ <div class="room" style="background: linear-gradient(135deg, var(--bg), var(--surface));"></div>
+ <div class="note">Opulent damask meets traditional craftsmanship.</div>
+ </div>
+ <div class="slide" data-index="4">
+ <h1>Explore More</h1>
+ <div class="cta">Discover the Collection</div>
+ </div>
+ </div>
+ <div class="dots" id="dots">
+ <div class="dot active"></div>
+ <div class="dot"></div>
+ <div class="dot"></div>
+ <div class="dot"></div>
+ <div class="dot"></div>
+ </div>
+ <script>
+ const carousel = document.getElementById('carousel');
+ const slides = document.querySelectorAll('.slide');
+ const dots = document.querySelectorAll('.dot');
+ let currentIndex = 0;
+
+ function showSlide(index) {
+ slides.forEach((slide, i) => {
+ slide.classList.remove('active');
+ if (i === index) {
+ slide.classList.add('active');
+ }
+ });
+ dots.forEach((dot, i) => {
+ dot.classList.toggle('active', i === index);
+ });
+ }
+
+ function nextSlide() {
+ currentIndex = (currentIndex + 1) % slides.length;
+ showSlide(currentIndex);
+ }
+
+ function prevSlide() {
+ currentIndex = (currentIndex - 1 + slides.length) % slides.length;
+ showSlide(currentIndex);
+ }
+
+ // Auto-advance every 6 seconds
+ setInterval(nextSlide, 6000);
+
+ // Swipe detection
+ let startX = 0;
+ let endX = 0;
+
+ carousel.addEventListener('touchstart', e => {
+ startX = e.touches[0].clientX;
+ });
+
+ carousel.addEventListener('touchmove', e => {
+ endX = e.touches[0].clientX;
+ });
+
+ carousel.addEventListener('touchend', () => {
+ if (startX - endX > 50) {
+ nextSlide();
+ } else if (startX - endX < -50) {
+ prevSlide();
+ }
+ });
+
+ // Dot click
+ dots.forEach((dot, index) => {
+ dot.addEventListener('click', () => {
+ currentIndex = index;
+ showSlide(index);
+ });
+ });
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/70eea6613a73/qwen3-14b.png b/data/artifacts/70eea6613a73/qwen3-14b.png
new file mode 100644
index 0000000..9adccae
Binary files /dev/null and b/data/artifacts/70eea6613a73/qwen3-14b.png differ
diff --git a/data/challenges.json b/data/challenges.json
index a384238..265dcf4 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -2080,7 +2080,14 @@
"started_at": "2026-07-23T13:54:49.362Z",
"finished_at": "2026-07-23T13:55:44.602Z",
"bytes": 3531,
- "thumb": true
+ "thumb": true,
+ "aiScore": 6.8,
+ "aiReason": "The game fulfills the challenge but lacks some visual polish and detail.",
+ "aiScores": {
+ "qwen2.5vl:7b": 7,
+ "minicpm-v:latest": 6.5
+ },
+ "aiSpread": 0.5
},
{
"model": "gemma3-12b",
@@ -29124,95 +29131,129 @@
"runs": [
{
"model": "qwen3-14b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.710Z"
+ "seconds": 52,
+ "cost": 0,
+ "started_at": "2026-07-25T14:59:57.530Z",
+ "finished_at": "2026-07-25T15:00:49.611Z",
+ "queued_at": "2026-07-25T14:59:53.710Z",
+ "bytes": 6880,
+ "thumb": true
},
{
"model": "gemma3-12b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.722Z"
+ "seconds": 58,
+ "cost": 0,
+ "started_at": "2026-07-25T15:00:49.621Z",
+ "finished_at": "2026-07-25T15:01:47.970Z",
+ "queued_at": "2026-07-25T14:59:53.722Z",
+ "bytes": 7179,
+ "thumb": true
},
{
"model": "hermes3-8b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.730Z"
+ "seconds": 18,
+ "cost": 0,
+ "started_at": "2026-07-25T15:01:47.984Z",
+ "finished_at": "2026-07-25T15:02:05.935Z",
+ "queued_at": "2026-07-25T14:59:53.730Z",
+ "bytes": 3593,
+ "thumb": true
},
{
"model": "qwen25-7b",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 35,
+ "cost": 0,
"started_at": "2026-07-25T14:59:53.761Z",
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.735Z"
+ "finished_at": "2026-07-25T15:00:28.547Z",
+ "queued_at": "2026-07-25T14:59:53.735Z",
+ "bytes": 4850,
+ "thumb": true
},
{
"model": "hf-qwen-coder-32b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.739Z"
+ "seconds": 84,
+ "cost": 0,
+ "started_at": "2026-07-25T15:02:05.950Z",
+ "finished_at": "2026-07-25T15:03:30.087Z",
+ "queued_at": "2026-07-25T14:59:53.739Z",
+ "bytes": 6937,
+ "thumb": true
},
{
"model": "claude-code",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 95,
+ "cost": 0,
"started_at": "2026-07-25T14:59:53.767Z",
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.743Z"
+ "finished_at": "2026-07-25T15:01:29.157Z",
+ "queued_at": "2026-07-25T14:59:53.743Z",
+ "bytes": 18609,
+ "thumb": true
},
{
"model": "kimi",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 161,
+ "cost": 0.0231,
"started_at": "2026-07-25T14:59:53.772Z",
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.747Z"
+ "finished_at": "2026-07-25T15:02:35.084Z",
+ "queued_at": "2026-07-25T14:59:53.747Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 23067,
+ "thumb": true
},
{
"model": "gpt",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 74,
+ "cost": 0.1439,
"started_at": "2026-07-25T14:59:53.778Z",
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.752Z"
+ "finished_at": "2026-07-25T15:01:08.049Z",
+ "queued_at": "2026-07-25T14:59:53.752Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 32557,
+ "thumb": true
},
{
"model": "grok",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 120,
+ "cost": 0.1476,
"started_at": "2026-07-25T14:59:53.783Z",
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.757Z"
+ "finished_at": "2026-07-25T15:01:53.328Z",
+ "queued_at": "2026-07-25T14:59:53.757Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 25347,
+ "thumb": true
}
- ]
+ ],
+ "judging": true
},
{
"id": "57af693363f2",
@@ -29225,21 +29266,23 @@
"runs": [
{
"model": "qwen3-14b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.816Z"
+ "seconds": 66,
+ "cost": 0,
+ "started_at": "2026-07-25T15:03:30.102Z",
+ "finished_at": "2026-07-25T15:04:36.402Z",
+ "queued_at": "2026-07-25T14:59:53.816Z",
+ "bytes": 9561,
+ "thumb": true
},
{
"model": "gemma3-12b",
- "status": "queued",
+ "status": "running",
"error": null,
"seconds": null,
"cost": null,
- "started_at": null,
+ "started_at": "2026-07-25T15:04:36.413Z",
"finished_at": null,
"queued_at": "2026-07-25T14:59:53.821Z"
},
@@ -29255,13 +29298,15 @@
},
{
"model": "qwen25-7b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.829Z"
+ "seconds": 30,
+ "cost": 0,
+ "started_at": "2026-07-25T15:00:28.551Z",
+ "finished_at": "2026-07-25T15:00:58.475Z",
+ "queued_at": "2026-07-25T14:59:53.829Z",
+ "bytes": 4043,
+ "thumb": true
},
{
"model": "hf-qwen-coder-32b",
@@ -29275,43 +29320,60 @@
},
{
"model": "claude-code",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.837Z"
+ "seconds": 118,
+ "cost": 0,
+ "started_at": "2026-07-25T15:01:29.165Z",
+ "finished_at": "2026-07-25T15:03:26.781Z",
+ "queued_at": "2026-07-25T14:59:53.837Z",
+ "bytes": 22630,
+ "thumb": true
},
{
"model": "kimi",
- "status": "queued",
+ "status": "running",
"error": null,
"seconds": null,
"cost": null,
- "started_at": null,
+ "started_at": "2026-07-25T15:02:35.105Z",
"finished_at": null,
"queued_at": "2026-07-25T14:59:53.841Z"
},
{
"model": "gpt",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.846Z"
+ "seconds": 80,
+ "cost": 0.1477,
+ "started_at": "2026-07-25T15:01:08.060Z",
+ "finished_at": "2026-07-25T15:02:27.660Z",
+ "queued_at": "2026-07-25T14:59:53.846Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 35327,
+ "thumb": true
},
{
"model": "grok",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T14:59:53.850Z"
+ "seconds": 156,
+ "cost": 0.1919,
+ "started_at": "2026-07-25T15:01:53.333Z",
+ "finished_at": "2026-07-25T15:04:28.932Z",
+ "queued_at": "2026-07-25T14:59:53.850Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 32876,
+ "thumb": true
}
]
}
diff --git a/data/costlog.jsonl b/data/costlog.jsonl
index 715a2ea..5ff4453 100644
--- a/data/costlog.jsonl
+++ b/data/costlog.jsonl
@@ -402,3 +402,8 @@
{"ts":"2026-07-25T14:49:57.395Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":3486,"output_tokens":11052,"cost_usd":0.160829}
{"ts":"2026-07-25T14:50:21.494Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena-tools","input_tokens":3638,"output_tokens":7749,"cost_usd":0.021555}
{"ts":"2026-07-25T14:50:46.352Z","provider":"xai","model":"grok-4.5","task":"model-arena-tools","input_tokens":4256,"output_tokens":11214,"cost_usd":0.180978}
+{"ts":"2026-07-25T15:01:08.046Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":3301,"output_tokens":9868,"cost_usd":0.143929}
+{"ts":"2026-07-25T15:01:53.327Z","provider":"xai","model":"grok-4.5","task":"model-arena-tools","input_tokens":4057,"output_tokens":9030,"cost_usd":0.147621}
+{"ts":"2026-07-25T15:02:27.658Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":3289,"output_tokens":10136,"cost_usd":0.14766}
+{"ts":"2026-07-25T15:02:35.080Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena-tools","input_tokens":3623,"output_tokens":8358,"cost_usd":0.023069}
+{"ts":"2026-07-25T15:04:28.927Z","provider":"xai","model":"grok-4.5","task":"model-arena-tools","input_tokens":4257,"output_tokens":11941,"cost_usd":0.191886}
← 2a4b2e1 night-loop: cycle 07:59 — judged=d7636ea87ec3 · fired 2 →; F
·
back to Model Arena
·
night-loop: cycle 08:12 — judged=93a51ee67f87 · fired 1 →; F 844afc1 →