← back to Model Arena
data/artifacts/0219528ac7d7/claude-code.html
536 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Which Design Era? — Designer Wallcoverings</title>
<style>
:root{
--bg:#faf8f4;
--surface:#ffffff;
--ink:#1c1a17;
--text:#1c1a17;
--muted:#9b948a;
--accent:#a9863f; /* soft antique gold */
--accent-deep:#7d6a45;
--line:rgba(28,26,23,.12);
--shadow:0 8px 24px rgba(28,26,23,.10);
--shadow-hi:0 16px 48px rgba(28,26,23,.16);
--ease:cubic-bezier(.22,1,.36,1);
--serif:'Didot','Bodoni MT','Playfair Display','Cormorant Garamond',Georgia,'Times New Roman',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;
min-height:100%;
display:flex;
flex-direction:column;
}
/* ---------- Fixed top bar / wordmark ---------- */
header.topbar{
position:sticky;top:0;z-index:50;
background:rgba(250,248,244,.92);
backdrop-filter:blur(8px);
border-bottom:1px solid var(--line);
display:flex;align-items:center;justify-content:space-between;
padding:18px 28px;
}
.wordmark{
font-family:var(--serif);
color:var(--ink);
font-size:clamp(20px,3.6vw,30px);
font-weight:600;
line-height:1.02;
text-transform:uppercase;
letter-spacing:.18em;
white-space:normal;
max-width:300px;
}
.wordmark small{
display:block;
font-family:var(--sans);
font-size:10px;
letter-spacing:.34em;
color:var(--muted);
font-weight:600;
margin-top:6px;
}
.scorebar{
display:flex;gap:22px;align-items:center;
font-family:var(--sans);
text-transform:uppercase;letter-spacing:.15em;
font-size:11px;color:var(--muted);
}
.scorebar b{
display:block;
font-family:var(--serif);
font-size:26px;letter-spacing:.02em;
color:var(--ink);font-weight:600;margin-top:2px;
}
/* ---------- Layout ---------- */
main{
flex:1;
width:100%;max-width:1040px;margin:0 auto;
padding:40px 28px 80px;
display:flex;flex-direction:column;align-items:center;
}
.kicker{
font-size:12px;letter-spacing:.22em;text-transform:uppercase;
color:var(--accent-deep);margin-bottom:14px;font-weight:600;
}
h1.prompt{
font-family:var(--serif);
font-weight:500;
font-size:clamp(26px,4.4vw,40px);
text-align:center;line-height:1.12;
margin-bottom:6px;color:var(--ink);
}
.subprompt{color:var(--muted);font-size:14px;margin-bottom:34px;text-align:center}
/* ---------- Vignette frame ---------- */
.stage{
width:100%;max-width:760px;
aspect-ratio:16/10;
border-radius:14px;
overflow:hidden;
position:relative;
box-shadow:var(--shadow-hi);
border:1px solid var(--line);
background:#eee;
animation:fadeUp .7s var(--ease) both;
}
.vignette{position:absolute;inset:0}
.plaque{
position:absolute;left:20px;bottom:18px;
background:rgba(255,255,255,.86);
backdrop-filter:blur(4px);
border:1px solid var(--line);
padding:8px 14px;border-radius:8px;
font-size:10px;letter-spacing:.2em;text-transform:uppercase;
color:var(--accent-deep);font-weight:700;
box-shadow:var(--shadow);
}
@keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
/* ---------- Guess buttons ---------- */
.options{
margin-top:34px;width:100%;max-width:760px;
display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:16px;
}
.opt{
font-family:var(--sans);
background:var(--surface);
border:1px solid var(--line);
border-radius:12px;
padding:20px 16px;
cursor:pointer;
text-align:center;
text-transform:uppercase;letter-spacing:.14em;
font-size:12px;font-weight:600;color:var(--ink);
box-shadow:var(--shadow);
transition:transform .2s var(--ease),box-shadow .2s var(--ease),border-color .2s var(--ease);
}
.opt:hover:not(:disabled){transform:translateY(-3px);box-shadow:var(--shadow-hi);border-color:var(--accent)}
.opt:disabled{cursor:default}
.opt.correct{border-color:var(--accent);background:#fbf6ea;box-shadow:0 0 24px rgba(169,134,63,.32)}
.opt.wrong{border-color:#b0472e;background:#fbefe c;opacity:.9}
.opt.wrong{background:#fbefec;border-color:#b0472e}
.opt.dim{opacity:.4}
/* ---------- Reveal card ---------- */
.reveal{
margin-top:30px;width:100%;max-width:760px;
background:var(--surface);
border:1px solid var(--line);
border-radius:14px;
padding:28px 30px;
box-shadow:var(--shadow);
display:none;
animation:fadeUp .5s var(--ease) both;
}
.reveal.show{display:block}
.reveal .verdict{
font-family:var(--sans);font-size:12px;letter-spacing:.18em;text-transform:uppercase;
font-weight:700;margin-bottom:10px;
}
.reveal .verdict.hit{color:var(--accent-deep)}
.reveal .verdict.miss{color:#b0472e}
.reveal h2{
font-family:var(--serif);font-weight:500;font-size:28px;color:var(--ink);margin-bottom:12px;
}
.reveal p{color:#4a453e;font-size:15px;line-height:1.65;max-width:60ch}
.reveal .next{
margin-top:22px;
display:inline-block;
font-family:var(--sans);
background:var(--ink);color:var(--bg);
border:none;border-radius:10px;
padding:14px 30px;cursor:pointer;
text-transform:uppercase;letter-spacing:.16em;font-size:12px;font-weight:600;
transition:background .2s var(--ease),transform .2s var(--ease);
}
.reveal .next:hover{background:var(--accent-deep);transform:translateY(-2px)}
.progress{
margin-top:30px;display:flex;gap:8px;
}
.pip{width:26px;height:3px;border-radius:2px;background:var(--line);transition:background .3s var(--ease)}
.pip.done{background:var(--accent)}
.pip.now{background:var(--ink)}
/* ---------- Overlay ---------- */
.overlay{
position:fixed;inset:0;z-index:100;
background:rgba(28,26,23,.55);
backdrop-filter:blur(6px);
display:none;align-items:center;justify-content:center;padding:24px;
}
.overlay.show{display:flex;animation:fadeIn .35s var(--ease) both}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.modal{
background:var(--surface);
border:1px solid var(--line);
border-radius:16px;
max-width:460px;width:100%;
padding:48px 40px;text-align:center;
box-shadow:var(--shadow-hi);
animation:fadeUp .5s var(--ease) both;
}
.modal .kicker{margin-bottom:18px}
.modal h2{font-family:var(--serif);font-weight:500;font-size:40px;color:var(--ink);line-height:1.05}
.modal .bigscore{
font-family:var(--serif);font-size:66px;color:var(--accent-deep);margin:18px 0 6px;font-weight:600;
}
.modal .best{
font-family:var(--sans);font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--muted);margin-bottom:8px;
}
.modal .msg{color:#4a453e;font-size:15px;line-height:1.6;margin:8px 0 30px}
.modal button{
font-family:var(--sans);
background:var(--ink);color:var(--bg);border:none;border-radius:10px;
padding:15px 40px;cursor:pointer;
text-transform:uppercase;letter-spacing:.16em;font-size:12px;font-weight:600;
transition:background .2s var(--ease),transform .2s var(--ease);
}
.modal button:hover{background:var(--accent-deep);transform:translateY(-2px)}
.modal .newbest{
display:inline-block;margin-top:12px;
font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--accent);font-weight:700;
}
footer{
text-align:center;padding:26px;font-size:10px;letter-spacing:.24em;text-transform:uppercase;
color:var(--muted);border-top:1px solid var(--line);
}
</style>
</head>
<body>
<header class="topbar">
<div class="wordmark">Designer Wallcoverings<small>The Design Era Salon</small></div>
<div class="scorebar">
<div>Round<b id="roundNum">1<span style="font-size:15px;color:var(--muted)">/8</span></b></div>
<div>Score<b id="scoreNum">0</b></div>
<div>Best<b id="bestNum">—</b></div>
</div>
</header>
<main>
<div class="kicker">Guess the Interior</div>
<h1 class="prompt">Which design era is this room?</h1>
<p class="subprompt">Study the palette, pattern & silhouette — then name the style.</p>
<div class="stage" id="stage" aria-label="An interior vignette to identify">
<div class="vignette" id="vignette"></div>
<div class="plaque">A Vignette · No. <span id="plaqueNum">1</span></div>
</div>
<div class="options" id="options"></div>
<div class="reveal" id="reveal">
<div class="verdict" id="verdict"></div>
<h2 id="revealTitle"></h2>
<p id="revealFact"></p>
<button class="next" id="nextBtn">Next Vignette →</button>
</div>
<div class="progress" id="progress"></div>
</main>
<footer>Designer Wallcoverings — A Salon of Style</footer>
<!-- Game over overlay -->
<div class="overlay" id="overlay">
<div class="modal">
<div class="kicker">The Verdict</div>
<h2 id="modalTitle">Well Composed</h2>
<div class="bigscore" id="modalScore">0</div>
<div class="best">of 8 rooms named correctly</div>
<div id="newBestWrap"></div>
<p class="msg" id="modalMsg"></p>
<button id="restartBtn">Play Again</button>
</div>
</div>
<script>
(function(){
"use strict";
// ---------- Era definitions with CSS-drawn vignettes ----------
const ERAS = {
victorian: {
name: "Victorian",
fact: "Victorian interiors (1837–1901) prized abundance: deep jewel tones, layered damask wallpapers, dark carved mahogany and rooms dressed almost floor-to-ceiling in pattern. William Morris' arabesques defined the age.",
draw: victorian
},
deco: {
name: "Art Deco",
fact: "Art Deco (1920s–30s) celebrated the machine age with bold symmetry, sunburst fans, lacquered black and glinting gold. Stepped geometry, chevrons and chrome made luxury feel modern and streamlined.",
draw: deco
},
midcentury: {
name: "Mid-Century Modern",
fact: "Mid-Century Modern (1945–1965) stripped rooms to clean lines, tapered wooden legs and warm atomic hues — mustard, teal and orange — with organic 'boomerang' motifs and a love of unadorned function.",
draw: midcentury
},
grandmillennial: {
name: "Grandmillennial",
fact: "Grandmillennial style revives 'granny chic' — chintz florals, scalloped edges, blue-and-white porcelain and skirted furniture — reinterpreting traditional patterns with a fresh, joyful, layered hand.",
draw: grandmillennial
}
};
const KEYS = Object.keys(ERAS);
// ---------- Vignette renderers (return CSS on a wrapper div) ----------
function baseRoom(el, wallCSS, floor, accent){
el.innerHTML =
'<div style="position:absolute;inset:0;'+wallCSS+'"></div>'+
// floor
'<div style="position:absolute;left:0;right:0;bottom:0;height:26%;background:'+floor+';border-top:2px solid rgba(0,0,0,.18)"></div>';
return el.firstChild;
}
function victorian(el){
// deep burgundy damask wall, dark floor, ornate framed art + sofa silhouette
const damask =
'background-color:#4a1522;'+
'background-image:'+
'radial-gradient(circle at 20px 30px, rgba(180,140,70,.28) 0 6px, transparent 7px),'+
'radial-gradient(circle at 60px 90px, rgba(180,140,70,.28) 0 6px, transparent 7px),'+
'radial-gradient(ellipse 14px 26px at 20px 60px, rgba(150,40,60,.55) 0 100%, transparent),'+
'radial-gradient(ellipse 14px 26px at 60px 120px, rgba(150,40,60,.55) 0 100%, transparent),'+
'linear-gradient(#4a1522,#3a1019);'+
'background-size:80px 120px,80px 120px,80px 120px,80px 120px,100% 100%;';
baseRoom(el, damask, 'linear-gradient(#3c2a1e,#2c1d14)', '#b48c46');
el.insertAdjacentHTML('beforeend',
// gilded oval frame
'<div style="position:absolute;left:50%;top:14%;transform:translateX(-50%);width:26%;height:40%;border-radius:50%;'+
'background:radial-gradient(circle at 40% 35%,#6a2233,#3a0f1b);border:8px solid #b48c46;box-shadow:0 0 0 2px #7d5a2a,inset 0 0 20px rgba(0,0,0,.6)"></div>'+
// tufted sofa
'<div style="position:absolute;left:14%;bottom:20%;width:72%;height:26%;background:linear-gradient(#6d1f2f,#57121f);'+
'border-radius:16px 16px 8px 8px;box-shadow:inset 0 -8px 14px rgba(0,0,0,.4),0 8px 16px rgba(0,0,0,.4);'+
'border-top:3px solid #8a3a4a"></div>'+
'<div style="position:absolute;left:16%;bottom:20%;width:68%;height:12%;background:repeating-linear-gradient(90deg,#7d2434 0 3px,transparent 3px 46px)"></div>'
);
}
function deco(el){
// black & gold sunburst, symmetrical
baseRoom(el,'background:linear-gradient(#161311,#221c16);','linear-gradient(#0e0c0a,#1a1512)','#c9a24a');
el.insertAdjacentHTML('beforeend',
// radiating gold fan
'<div style="position:absolute;left:50%;top:6%;transform:translateX(-50%);width:44%;height:64%;'+
'background:conic-gradient(from 200deg at 50% 100%,'+
'#c9a24a 0 4deg,transparent 4deg 14deg,#a9843a 14deg 18deg,transparent 18deg 28deg,'+
'#c9a24a 28deg 32deg,transparent 32deg 42deg,#a9843a 42deg 46deg,transparent 46deg 56deg,'+
'#c9a24a 56deg 60deg,transparent 60deg 70deg,#a9843a 70deg 74deg,transparent 74deg 84deg,#c9a24a 84deg 88deg,transparent 88deg 140deg);'+
'border-radius:0 0 6px 6px;opacity:.9"></div>'+
// stepped console
'<div style="position:absolute;left:50%;bottom:20%;transform:translateX(-50%);width:40%;height:22%;background:linear-gradient(#2b2320,#171310);'+
'border-top:4px solid #c9a24a;box-shadow:0 8px 18px rgba(0,0,0,.5)"></div>'+
'<div style="position:absolute;left:50%;bottom:20%;transform:translateX(-50%);width:20%;height:30%;background:#0f0c0a;border-left:2px solid #c9a24a;border-right:2px solid #c9a24a"></div>'+
// chevron border
'<div style="position:absolute;left:0;right:0;top:0;height:8%;background:repeating-linear-gradient(135deg,#c9a24a 0 8px,#161311 8px 16px)"></div>'
);
}
function midcentury(el){
// warm cream wall w/ atomic ovals, teal + orange, tapered legs
const wall='background:linear-gradient(#efe3ce,#e6d7bd);';
baseRoom(el,wall,'linear-gradient(#c58a4d,#a9713a)','#d97b34');
el.insertAdjacentHTML('beforeend',
// atomic starbursts
'<div style="position:absolute;left:18%;top:14%;width:70px;height:70px;'+
'background:conic-gradient(from 0deg,#e07b34 0 10deg,transparent 10deg 45deg,#2f7f78 45deg 55deg,transparent 55deg 90deg,#e07b34 90deg 100deg,transparent 100deg 135deg,#2f7f78 135deg 145deg,transparent 145deg 180deg,#e07b34 180deg 190deg,transparent 190deg 225deg,#2f7f78 225deg 235deg,transparent 235deg 270deg,#e07b34 270deg 280deg,transparent 280deg 315deg,#2f7f78 315deg 325deg,transparent 325deg 360deg);border-radius:50%"></div>'+
// boomerang ovals
'<div style="position:absolute;right:16%;top:20%;width:120px;height:44px;border:5px solid #2f7f78;border-radius:50%;transform:rotate(-18deg)"></div>'+
'<div style="position:absolute;right:24%;top:32%;width:80px;height:30px;border:5px solid #d97b34;border-radius:50%;transform:rotate(-18deg)"></div>'+
// low couch teal
'<div style="position:absolute;left:20%;bottom:22%;width:60%;height:16%;background:linear-gradient(#2f7f78,#256560);border-radius:6px;box-shadow:0 6px 12px rgba(0,0,0,.25)"></div>'+
'<div style="position:absolute;left:22%;bottom:14%;width:8px;height:9%;background:#5c3a1e;transform:rotate(8deg)"></div>'+
'<div style="position:absolute;right:22%;bottom:14%;width:8px;height:9%;background:#5c3a1e;transform:rotate(-8deg)"></div>'
);
}
function grandmillennial(el){
// blue & white chintz floral, scalloped, skirted table + ginger jar
const chintz=
'background-color:#f4f8fb;'+
'background-image:'+
'radial-gradient(circle at 25px 25px,#9cc0dd 0 7px,transparent 8px),'+
'radial-gradient(circle at 25px 25px,#4a76a8 0 3px,transparent 4px),'+
'radial-gradient(circle at 75px 75px,#9cc0dd 0 7px,transparent 8px),'+
'radial-gradient(circle at 75px 75px,#4a76a8 0 3px,transparent 4px),'+
'linear-gradient(#f4f8fb,#eaf1f7);'+
'background-size:100px 100px,100px 100px,100px 100px,100px 100px,100% 100%;';
baseRoom(el,chintz,'linear-gradient(#dfe7ec,#cdd8df)','#4a76a8');
el.insertAdjacentHTML('beforeend',
// scalloped valance
'<div style="position:absolute;left:0;right:0;top:0;height:9%;background:'+
'radial-gradient(circle at 20px 0,#4a76a8 0 18px,transparent 19px) 0 0/40px 20px repeat-x,#6f9ac4"></div>'+
// ginger jar
'<div style="position:absolute;left:50%;top:26%;transform:translateX(-50%);width:16%;height:30%;'+
'background:radial-gradient(circle at 40% 30%,#fff,#dbe8f2);border-radius:50% 50% 46% 46%;border:2px solid #4a76a8;box-shadow:inset -6px 0 10px rgba(74,118,168,.3)"></div>'+
'<div style="position:absolute;left:50%;top:24%;transform:translateX(-50%);width:6%;height:5%;background:#4a76a8;border-radius:4px"></div>'+
// skirted table
'<div style="position:absolute;left:33%;bottom:16%;width:34%;height:20%;background:linear-gradient(#fbe4ec,#f2c9d8);'+
'border-radius:8px 8px 0 0;box-shadow:0 6px 14px rgba(0,0,0,.15)"></div>'+
'<div style="position:absolute;left:33%;bottom:16%;width:34%;height:6%;background:repeating-linear-gradient(90deg,#e2a3ba 0 6px,#f2c9d8 6px 14px)"></div>'
);
}
// ---------- Game state ----------
const TOTAL = 8;
let round, score, sequence, answered, best;
const $ = id => document.getElementById(id);
const optionsEl=$('options'), revealEl=$('reveal'), progressEl=$('progress');
best = parseInt(localStorage.getItem('dw_era_best')||'',10);
if(!isNaN(best)) $('bestNum').textContent = best;
function buildProgress(){
progressEl.innerHTML='';
for(let i=0;i<TOTAL;i++){
const p=document.createElement('div');p.className='pip';p.dataset.i=i;progressEl.appendChild(p);
}
}
function updateProgress(){
[...progressEl.children].forEach((p,i)=>{
p.className='pip'+(i<round?' done':i===round?' now':'');
});
}
function shuffled(arr){
const a=arr.slice();
for(let i=a.length-1;i>0;i--){const j=Math.floor(Math.random()*(i+1));[a[i],a[j]]=[a[j],a[i]];}
return a;
}
function startGame(){
round=0;score=0;answered=false;
// sequence: at least each era once when possible, then random, shuffled
let seq=[];
while(seq.length<TOTAL){ seq=seq.concat(shuffled(KEYS)); }
sequence=shuffled(seq).slice(0,TOTAL);
$('scoreNum').textContent=0;
buildProgress();
$('overlay').classList.remove('show');
loadRound();
}
function loadRound(){
answered=false;
const eraKey=sequence[round];
$('roundNum').innerHTML=(round+1)+'<span style="font-size:15px;color:var(--muted)">/'+TOTAL+'</span>';
$('plaqueNum').textContent=round+1;
updateProgress();
// draw vignette
const v=$('vignette');
v.innerHTML='';
v.style.cssText='position:absolute;inset:0';
ERAS[eraKey].draw(v);
// re-trigger entrance
const stage=$('stage');stage.style.animation='none';void stage.offsetWidth;stage.style.animation='';
// build options
optionsEl.innerHTML='';
shuffled(KEYS).forEach(k=>{
const b=document.createElement('button');
b.className='opt';b.textContent=ERAS[k].name;b.dataset.key=k;
b.addEventListener('click',()=>choose(k,b));
optionsEl.appendChild(b);
});
revealEl.classList.remove('show');
}
function choose(guess,btn){
if(answered) return;
answered=true;
const correctKey=sequence[round];
const correct = guess===correctKey;
if(correct){ score++; $('scoreNum').textContent=score; }
[...optionsEl.children].forEach(b=>{
b.disabled=true;
const k=b.dataset.key;
if(k===correctKey) b.classList.add('correct');
else if(k===guess) b.classList.add('wrong');
else b.classList.add('dim');
});
const era=ERAS[correctKey];
const vEl=$('verdict');
if(correct){ vEl.textContent='Correct — Beautifully Read'; vEl.className='verdict hit'; }
else { vEl.textContent='Not Quite — It Was…'; vEl.className='verdict miss'; }
$('revealTitle').textContent=era.name;
$('revealFact').textContent=era.fact;
$('nextBtn').textContent = (round+1<TOTAL) ? 'Next Vignette →' : 'See Your Result →';
revealEl.classList.add('show');
revealEl.scrollIntoView({behavior:'smooth',block:'nearest'});
}
$('nextBtn').addEventListener('click',()=>{
round++;
if(round<TOTAL){ loadRound(); window.scrollTo({top:0,behavior:'smooth'}); }
else finish();
});
function finish(){
$('modalScore').textContent=score;
let title,msg;
if(score===TOTAL){ title='Connoisseur'; msg='A flawless eye. Every era named without a false step — the salon is yours.'; }
else if(score>=6){ title='Well-Studied'; msg='A refined sensibility for period and pattern. A stray guess or two, but a discerning eye.'; }
else if(score>=4){ title='Coming Along'; msg='A promising instinct for style. Another turn through the rooms will sharpen it.'; }
else { title='A Fresh Start'; msg='Every collector begins somewhere. Study the palettes and motifs, then take another turn.'; }
$('modalTitle').textContent=title;
$('modalMsg').textContent=msg;
const nb=$('newBestWrap');nb.innerHTML='';
if(isNaN(best)||score>best){
best=score;localStorage.setItem('dw_era_best',String(best));
$('bestNum').textContent=best;
nb.innerHTML='<span class="newbest">★ New Personal Best</span>';
} else {
nb.innerHTML='<span class="best" style="color:var(--muted)">Best so far: '+best+'</span>';
}
$('overlay').classList.add('show');
}
$('restartBtn').addEventListener('click',startGame);
startGame();
})();
</script>
</body>
</html>