← back to Model Arena
auto-save: 2026-07-25T05:33:58 (27 files) — data/challenges.json data/costlog.jsonl data/artifacts/6e1b0984b54e/gemma3-12b.html data/artifacts/6e1b0984b54e/gemma3-12b.png data/artifacts/6e1b0984b54e/grok.png
069b96f2b98a6fe756e383435f4b786e64cd67a0 · 2026-07-25 05:34:05 -0700 · Steve Abrams
Files touched
A data/artifacts/6e1b0984b54e/gemma3-12b.htmlA data/artifacts/6e1b0984b54e/gemma3-12b.pngA data/artifacts/6e1b0984b54e/grok.pngA data/artifacts/6e1b0984b54e/hermes3-8b.htmlA data/artifacts/6e1b0984b54e/hermes3-8b.pngA data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.htmlA data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.pngA data/artifacts/6e1b0984b54e/kimi.htmlA data/artifacts/6e1b0984b54e/kimi.pngA data/artifacts/bf0bdeb4c423/claude-code.htmlA data/artifacts/bf0bdeb4c423/claude-code.pngA data/artifacts/bf0bdeb4c423/gemma3-12b.htmlA data/artifacts/bf0bdeb4c423/gemma3-12b.pngA data/artifacts/bf0bdeb4c423/gpt.htmlA data/artifacts/bf0bdeb4c423/gpt.pngA data/artifacts/bf0bdeb4c423/grok.htmlA data/artifacts/bf0bdeb4c423/grok.pngA data/artifacts/bf0bdeb4c423/hermes3-8b.htmlA data/artifacts/bf0bdeb4c423/hermes3-8b.pngA data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.htmlA data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.pngA data/artifacts/bf0bdeb4c423/kimi.htmlA data/artifacts/bf0bdeb4c423/kimi.pngA data/artifacts/bf0bdeb4c423/qwen3-14b.htmlA data/artifacts/bf0bdeb4c423/qwen3-14b.pngM data/challenges.jsonM data/costlog.jsonl
Diff
commit 069b96f2b98a6fe756e383435f4b786e64cd67a0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Jul 25 05:34:05 2026 -0700
auto-save: 2026-07-25T05:33:58 (27 files) — data/challenges.json data/costlog.jsonl data/artifacts/6e1b0984b54e/gemma3-12b.html data/artifacts/6e1b0984b54e/gemma3-12b.png data/artifacts/6e1b0984b54e/grok.png
---
data/artifacts/6e1b0984b54e/gemma3-12b.html | 251 ++++
data/artifacts/6e1b0984b54e/gemma3-12b.png | Bin 0 -> 33974 bytes
data/artifacts/6e1b0984b54e/grok.png | Bin 0 -> 26954 bytes
data/artifacts/6e1b0984b54e/hermes3-8b.html | 172 +++
data/artifacts/6e1b0984b54e/hermes3-8b.png | Bin 0 -> 39154 bytes
data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.html | 172 +++
data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.png | Bin 0 -> 21447 bytes
data/artifacts/6e1b0984b54e/kimi.html | 674 ++++++++++
data/artifacts/6e1b0984b54e/kimi.png | Bin 0 -> 170937 bytes
data/artifacts/bf0bdeb4c423/claude-code.html | 858 +++++++++++++
data/artifacts/bf0bdeb4c423/claude-code.png | Bin 0 -> 31660 bytes
data/artifacts/bf0bdeb4c423/gemma3-12b.html | 306 +++++
data/artifacts/bf0bdeb4c423/gemma3-12b.png | Bin 0 -> 72279 bytes
data/artifacts/bf0bdeb4c423/gpt.html | 1219 ++++++++++++++++++
data/artifacts/bf0bdeb4c423/gpt.png | Bin 0 -> 139666 bytes
data/artifacts/bf0bdeb4c423/grok.html | 1336 ++++++++++++++++++++
data/artifacts/bf0bdeb4c423/grok.png | Bin 0 -> 43628 bytes
data/artifacts/bf0bdeb4c423/hermes3-8b.html | 236 ++++
data/artifacts/bf0bdeb4c423/hermes3-8b.png | Bin 0 -> 28611 bytes
data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.html | 252 ++++
data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.png | Bin 0 -> 22594 bytes
data/artifacts/bf0bdeb4c423/kimi.html | 680 ++++++++++
data/artifacts/bf0bdeb4c423/kimi.png | Bin 0 -> 22828 bytes
data/artifacts/bf0bdeb4c423/qwen3-14b.html | 334 +++++
data/artifacts/bf0bdeb4c423/qwen3-14b.png | Bin 0 -> 19046 bytes
data/challenges.json | 308 +++--
data/costlog.jsonl | 4 +
27 files changed, 6715 insertions(+), 87 deletions(-)
diff --git a/data/artifacts/6e1b0984b54e/gemma3-12b.html b/data/artifacts/6e1b0984b54e/gemma3-12b.html
new file mode 100644
index 0000000..59cd200
--- /dev/null
+++ b/data/artifacts/6e1b0984b54e/gemma3-12b.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Designer Wallcoverings - Seasonal Color Story</title>
+ <style>
+ :root {
+ --bg: #f7efe6;
+ --surface: #fff9f1;
+ --text: #3a2c22;
+ --muted: #a08c7a;
+ --accent: #c65f38;
+ --line: rgba(58, 44, 34, .1);
+ --shadow: rgba(0, 0, 0, .12);
+ --ease: cubic-bezier(.22, 1, .36, 1);
+ }
+
+ body {
+ font-family: system-ui, sans-serif;
+ background-color: var(--bg);
+ color: var(--text);
+ margin: 0;
+ overflow-x: hidden; /* Prevent horizontal scroll */
+ }
+
+ .container {
+ padding: 96px;
+ max-width: 1080px;
+ margin: 0 auto;
+ }
+
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ background-color: var(--bg);
+ padding: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: left; /* Left align */
+ }
+
+ header h1 {
+ font-family: 'Didot', serif;
+ font-size: calc(67px * .75); /* Adjust for fixed header */
+ letter-spacing: .18em;
+ margin: 0;
+ line-height: 1.2;
+ white-space: nowrap;
+ }
+
+ /* Carousel Styles */
+ .carousel {
+ position: relative;
+ width: 100%;
+ overflow: hidden;
+ }
+
+ .slide {
+ flex: 0 0 100%; /* Each slide takes full width */
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ padding: 48px;
+ background-color: var(--surface);
+ border-radius: 14px;
+ box-shadow: 0 8px 24px var(--shadow);
+ transition: transform .3s ease-in-out; /* Add transition */
+ }
+
+ .slide:hover {
+ transform: scale(1.02);
+ }
+
+
+ .carousel-dots {
+ position: absolute;
+ bottom: 24px;
+ left: 50%;
+ transform: translateX(-50%);
+ display: flex;
+ gap: 8px;
+ }
+
+ .dot {
+ width: 12px;
+ height: 12px;
+ background-color: var(--muted);
+ border-radius: 50%;
+ cursor: pointer;
+ }
+
+ .dot.active {
+ background-color: var(--accent);
+ }
+
+
+ /* Color Swatch Styles */
+ .swatch {
+ width: 260px;
+ height: 260px;
+ border: 1px solid var(--line);
+ border-radius: 14px;
+ background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, .3) 80%, var(--accent) 100%);
+ box-shadow: 0 8px 24px var(--shadow);
+ }
+
+ .room-tip {
+ margin-top: 24px;
+ font-size: 16px;
+ }
+
+
+ /* CTA Styles */
+ .cta {
+ background-color: var(--accent);
+ color: white;
+ padding: 16px 32px;
+ border-radius: 14px;
+ text-decoration: none;
+ display: inline-block;
+ transition: background-color .3s ease;
+ }
+
+ .cta:hover {
+ background-color: #c65f38; /* slightly darker */
+ }
+
+
+ /* Mobile responsiveness */
+ @media (max-width: 768px) {
+ header h1 {
+ font-size: calc(67px * .5); /* Further reduce for smaller screens */
+ }
+
+ .container {
+ padding: 32px; /* Reduce padding on smaller screens */
+ }
+ }
+
+
+
+ </style>
+</head>
+<body>
+
+ <header>
+ <h1>DESIGNER WALLCOVERINGS</h1>
+ </header>
+
+
+ <div class="container">
+ <div class="carousel" id="carousel">
+ <div class="slide" data-index="0">
+ <h1>Terracotta & Sage</h1>
+ </div>
+
+ <div class="slide" data-index="1">
+ <div class="swatch"></div>
+ <h2>Oatmeal</h2>
+ <p class="room-tip">Perfect for cozy bedrooms and sunlit dining areas.</p>
+ </div>
+
+ <div class="slide" data-index="2">
+ <div class="swatch"></div>
+ <h2>Celadon</h2>
+ <p class="room-tip">Bring a touch of tranquility to bathrooms and powder rooms.</p>
+ </div>
+
+ <div class="slide" data-index="3">
+ <div class="swatch"></div>
+ <h2>Terracotta</h2>
+ <p class="room-tip">Create warmth and character in living rooms and hallways.</p>
+ </div>
+
+ <div class="slide" data-index="4">
+ <h2>Explore the Collection</h2>
+ <a href="#" class="cta">View All Wallcoverings</a>
+ </div>
+ </div>
+
+ <div class="carousel-dots" id="dots">
+ <span class="dot active" data-index="0"></span>
+ <span class="dot" data-index="1"></span>
+ <span class="dot" data-index="2"></span>
+ <span class="dot" data-index="3"></span>
+ <span class="dot" data-index="4"></span>
+ </div>
+
+ </div>
+
+
+ <script>
+ const carousel = document.getElementById('carousel');
+ const dotsContainer = document.getElementById('dots');
+ let currentSlide = 0;
+ const slides = document.querySelectorAll('.slide');
+ const numSlides = slides.length;
+
+ // Initialize dots
+ for (let i = 0; i < numSlides; i++) {
+ const dot = document.createElement('span');
+ dot.classList.add('dot');
+ dot.dataset.index = i;
+ dotsContainer.appendChild(dot);
+ }
+
+ // Activate the first dot
+ dotsContainer.querySelector('.dot').classList.add('active');
+
+
+ function showSlide(index) {
+ slides.forEach((slide, i) => {
+ if (i === index) {
+ slide.style.transform = `translateX(-${index * 100}%)`;
+ } else {
+ slide.style.transform = `translateX(${- (i * 100)}%)`;
+ }
+ });
+
+ // Update active dot
+ dotsContainer.querySelector('.dot.active').classList.remove('active');
+ dotsContainer.children[index].classList.add('active');
+
+ }
+
+
+ function nextSlide() {
+ currentSlide = (currentSlide + 1) % numSlides;
+ showSlide(currentSlide);
+ }
+
+ // Event listeners for dots
+ dotsContainer.addEventListener('click', (event) => {
+ if (event.target.classList.contains('dot')) {
+ const index = parseInt(event.target.dataset.index);
+ currentSlide = index;
+ showSlide(currentSlide);
+ }
+ });
+
+
+ // Automatic slide transition (optional) - Remove if not needed for strict requirements
+ setInterval(nextSlide, 5000);
+
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/6e1b0984b54e/gemma3-12b.png b/data/artifacts/6e1b0984b54e/gemma3-12b.png
new file mode 100644
index 0000000..cc2babe
Binary files /dev/null and b/data/artifacts/6e1b0984b54e/gemma3-12b.png differ
diff --git a/data/artifacts/6e1b0984b54e/grok.png b/data/artifacts/6e1b0984b54e/grok.png
new file mode 100644
index 0000000..48b43a3
Binary files /dev/null and b/data/artifacts/6e1b0984b54e/grok.png differ
diff --git a/data/artifacts/6e1b0984b54e/hermes3-8b.html b/data/artifacts/6e1b0984b54e/hermes3-8b.html
new file mode 100644
index 0000000..ddc05c3
--- /dev/null
+++ b/data/artifacts/6e1b0984b54e/hermes3-8b.html
@@ -0,0 +1,172 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Design Wallcoverings</title>
+<style>
+:root {
+ --bg-color: #f7efe6;
+ --surface-color: #fff9f1;
+ --text-color: #3a2c22;
+ --muted-color: #a08c7a;
+ --accent-main: #c65f38;
+ --accent-secondary: #e0a458;
+ --line-color: rgba(255, 95, 56, .25);
+ --shadow-color: rgba(0, 0, 0, .12);
+ --ease-in-out-quart: cubic-bezier(.22, 1, .36, 1);
+}
+body {
+ background-color: var(--bg-color);
+ color: var(--text-color);
+ font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+ margin: 0;
+ padding: 32px;
+}
+.muted {
+ color: var(--muted-color);
+}
+.accent {
+ color: var(--accent-main);
+}
+h1 {
+ font-size: 50px;
+ letter-spacing: .18em;
+ text-align: left;
+}
+header {
+ background-color: var(--surface-color);
+ padding: 16px;
+}
+.wordmark {
+ display: block;
+ font-family: 'Cormorant Garamond', serif;
+ font-size: 32px;
+ letter-spacing: .18em;
+ margin: 0;
+}
+.cta {
+ background-color: var(--surface-color);
+ border-radius: 14px;
+ box-shadow: 0 8px 24px var(--shadow-color);
+ display: flex;
+ gap: 16px;
+ justify-content: center;
+ padding: 32px;
+}
+.cta-logo {
+ background-color: var(--accent-main);
+ border-radius: 50%;
+ width: 64px;
+ height: 64px;
+}
+.cta-text {
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ font-size: 24px;
+ text-transform: uppercase;
+}
+.card {
+ background-color: var(--surface-color);
+ border-radius: 14px;
+ box-shadow: 0 8px 24px rgba(0, 0, 0, .12);
+ padding: 32px;
+ position: relative;
+ transition: transform .7s var(--ease-in-out-quart), box-shadow .7s var(--ease-in-out-quart);
+}
+.card::before {
+ background-color: var(--accent-main);
+ content: '';
+ position: absolute;
+ top: -14px;
+ left: 0;
+ width: calc(100% - 32px);
+ height: 14px;
+}
+.card:hover {
+ box-shadow: 0 16px 48px rgba(0, 0, 0, .18);
+ transform: translateY(-4px);
+}
+.swatch {
+ background-color: var(--accent-main);
+ border-radius: 12px;
+ height: 120px;
+ margin-bottom: 24px;
+ position: relative;
+}
+.swatch::before {
+ content: '';
+ display: block;
+ position: absolute;
+ top: -14px;
+ left: calc((100% - 168px) / 2);
+ width: 168px;
+ height: 14px;
+ background-color: var(--surface-color);
+}
+h3 {
+ font-size: 28px;
+ margin: 0;
+}
+p {
+ font-size: 16px;
+ margin: 24px 0;
+}
+.cta-button {
+ background-color: var(--accent-main);
+ border-radius: 14px;
+ color: var(--surface-color);
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ font-size: 16px;
+ text-transform: uppercase;
+ display: block;
+ width: 100%;
+ padding: 12px 0;
+}
+/* Keyframes */
+@keyframes fadeUp {
+ from {
+ opacity: 0;
+ transform: translateY(28px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+</style>
+</head>
+<body>
+<header class="bg-surface-color padding-16">
+<div class="wordmark bg-bg-color padding-8 margin-0 font-size-32">DESIGNER WALLCOVERINGS</div>
+</header>
+<section class="padding-96">
+<h1 class="text-color">Terracotta & Sage</h1>
+<div class="bg-surface-color border-radius-14 shadow card padding-32 margin-bottom-32">
+ <h3 class="text-color margin-0">Oatmeal</h3>
+ <p class="muted margin-0">Design by: Eliza Crumpet</p>
+ <p class="margin-24">Bring warm, neutral vibes to any space with this light oatmeal swatch. Perfect for a calming bedroom or cozy living room.</p>
+ <div class="swatch bg-accent-main padding-0 margin-0">
+ <div class="bg-surface-color border-radius-12 shadow-sm swatch-inner padding-0 margin-0"></div>
+ </div>
+</div>
+<div class="bg-surface-color border-radius-14 shadow card padding-32 margin-bottom-32">
+ <h3 class="text-color margin-0">Celadon</h3>
+ <p class="muted margin-0">Design by: Pierre DuChamp</p>
+ <p class="margin-24">Add a touch of elegance with this sage green hue. Ideal for offices, dining rooms or any space that needs to feel balanced and sophisticated.</p>
+ <div class="swatch bg-accent-main padding-0 margin-0">
+ <div class="bg-surface-color border-radius-12 shadow-sm swatch-inner padding-0 margin-0"></div>
+ </div>
+</div>
+<div class="bg-surface-color border-radius-14 shadow card padding-32 margin-bottom-32">
+ <h3 class="text-color margin-0">Terracotta</h3>
+ <p class="muted margin-0">Design by: Francesca Spaghetti</p>
+ <p class="margin-24">Inject energy and warmth into your space with this rich terracotta tone. Perfect for entryways, kitchens or any area that needs a pop of color.</p>
+ <div class="swatch bg-accent-main padding-0 margin-0">
+ <div class="bg-surface-color border-radius-12 shadow-sm swatch-inner padding-0 margin-0"></div>
+ </div>
+</section>
+<div class="cta bg-surface-color padding-32 flex justify-center items-center">
+ <div class="cta-logo bg-accent-main border-radius-50% width-64 height-64"></div>
+ <div class="cta-text text-uppercase font-size-24 margin-0">Discover More</div>
+ <button class="bg-accent-main text-color border-radius-14 padding-12 display-block width-100">Shop Now</button>
+</div>
\ No newline at end of file
diff --git a/data/artifacts/6e1b0984b54e/hermes3-8b.png b/data/artifacts/6e1b0984b54e/hermes3-8b.png
new file mode 100644
index 0000000..ba01267
Binary files /dev/null and b/data/artifacts/6e1b0984b54e/hermes3-8b.png differ
diff --git a/data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.html b/data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.html
new file mode 100644
index 0000000..20963c9
--- /dev/null
+++ b/data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.html
@@ -0,0 +1,172 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Designer Wallcoverings</title>
+ <style>
+ :root {
+ --bg: #f7efe6;
+ --surface: #fff9f1;
+ --ink: #3a2c22;
+ --muted: #a08c7a;
+ --accent: #c65f38;
+ --line: #e0a458;
+ --shadow: rgba(0, 0, 0, .12);
+ --hover-shadow: rgba(0, 0, 0, .18);
+ --glow: rgba(198, 95, 56, .35);
+ --ease: cubic-bezier(.22,1,.36,1);
+ }
+ body {
+ margin: 0;
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ background-color: var(--bg);
+ color: var(--ink);
+ line-height: 1.5;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100vh;
+ overflow: hidden;
+ }
+ header {
+ position: fixed;
+ top: 24px;
+ left: 24px;
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 38px;
+ letter-spacing: .18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ background-color: transparent;
+ z-index: 10;
+ }
+ .carousel {
+ width: 1080px;
+ height: 1080px;
+ position: relative;
+ overflow: hidden;
+ perspective: 1000px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ .slide-track {
+ display: flex;
+ transition: transform .7s var(--ease);
+ width: calc(5400px);
+ }
+ .slide {
+ min-width: 1080px;
+ height: 1080px;
+ box-shadow: 0 8px 24px var(--shadow);
+ border-radius: 16px;
+ background-color: var(--surface);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ }
+ .slide h2 {
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 48px;
+ letter-spacing: .15em;
+ text-transform: uppercase;
+ margin-bottom: 32px;
+ color: var(--ink);
+ }
+ .swatch {
+ width: 200px;
+ height: 200px;
+ background-color: currentColor;
+ border-radius: 8px;
+ box-shadow: 0 4px 16px rgba(0, 0, 0, .1);
+ margin-bottom: 32px;
+ }
+ .tip {
+ font-size: 16px;
+ color: var(--muted);
+ text-align: center;
+ max-width: 500px;
+ }
+ .dots {
+ position: absolute;
+ bottom: 48px;
+ display: flex;
+ justify-content: center;
+ gap: 12px;
+ }
+ .dot {
+ width: 16px;
+ height: 16px;
+ background-color: var(--muted);
+ border-radius: 50%;
+ transition: background-color .3s ease;
+ cursor: pointer;
+ }
+ .dot.active {
+ background-color: var(--accent);
+ }
+ </style>
+</head>
+<body>
+ <header>DESIGNER WALLCOVERINGS</header>
+ <div class="carousel">
+ <div class="slide-track" id="slideTrack">
+ <div class="slide" style="background-color: #fff9f1;">
+ <h2>TERRACOTTA & SAGE</h2>
+ </div>
+ <div class="slide" style="color: #f5a67c;">
+ <div class="swatch"></div>
+ <div class="tip">Oatmeal<br>Perfect for a cozy living room.</div>
+ </div>
+ <div class="slide" style="color: #8ee4af;">
+ <div class="swatch"></div>
+ <div class="tip>Celadon<br>Brighten up your kitchen with this hue.</div>
+ </div>
+ <div class="slide" style="color: #c65f38;">
+ <div class="swatch"></div>
+ <div class="tip>Terracotta<br>Warm your dining area with terracotta tones.</div>
+ </div>
+ <div class="slide" style="background-color: #fff9f1; color: var(--accent);">
+ <h2>DISCOVER MORE</h2>
+ <a href="#" style="text-decoration: none; font-size: 16px; text-transform: uppercase; letter-spacing: .15em; color: inherit;">EXPLORE NOW</a>
+ </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 slideTrack = document.getElementById('slideTrack');
+ const dots = document.querySelectorAll('.dot');
+ let currentIndex = 0;
+
+ function updateSlide(index) {
+ slideTrack.style.transform = `translateX(-${index * 1080}px)`;
+ dots.forEach(dot => dot.classList.remove('active'));
+ dots[index].classList.add('active');
+ currentIndex = index;
+ }
+
+ dots.forEach((dot, index) => {
+ dot.addEventListener('click', () => {
+ updateSlide(index);
+ });
+ });
+
+ document.addEventListener('keydown', (e) => {
+ if (e.key === 'ArrowRight' && currentIndex < 4) {
+ updateSlide(currentIndex + 1);
+ } else if (e.key === 'ArrowLeft' && currentIndex > 0) {
+ updateSlide(currentIndex - 1);
+ }
+ });
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.png b/data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.png
new file mode 100644
index 0000000..f1e9ec0
Binary files /dev/null and b/data/artifacts/6e1b0984b54e/hf-qwen-coder-32b.png differ
diff --git a/data/artifacts/6e1b0984b54e/kimi.html b/data/artifacts/6e1b0984b54e/kimi.html
new file mode 100644
index 0000000..cd0fc30
--- /dev/null
+++ b/data/artifacts/6e1b0984b54e/kimi.html
@@ -0,0 +1,674 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Designer Wallcoverings — Color Story</title>
+<style>
+/* ============================================
+ DESIGN TOKENS — Luxury Interior System
+ ============================================ */
+:root{
+ /* Ground & Ink (Strong Value Contrast) */
+ --bg:#f5f2ea;
+ --ink:#0d0d0f;
+ --surface:#ffffff;
+ --surface-2:#ebe7de;
+
+ /* Metallic Accent */
+ --accent:#c9a961;
+ --accent-light:#d9bc7a;
+
+ /* Utility */
+ --muted:#8a8578;
+ --line:#d9d4c9;
+ --shadow:rgba(13,13,15,0.08);
+
+ /* Typography */
+ --font-display:'Playfair Display','Didot','Bodoni MT',Georgia,serif;
+ --font-body:'Avenir Next','Century Gothic',Futura,'Segoe UI',sans-serif;
+
+ /* Spacing Scale */
+ --space-xs:4px;
+ --space-sm:8px;
+ --space-md:16px;
+ --space-lg:24px;
+ --space-xl:48px;
+ --space-2xl:64px;
+
+ /* Motion */
+ --ease-swift:cubic-bezier(.22,.9,.24,1);
+ --ease-power:cubic-bezier(.77,0,.18,1);
+ --ease-entrance:cubic-bezier(.22,1,.36,1);
+
+ /* Carousel Sizing */
+ --carousel-size:1080px;
+ --header-height:80px;
+}
+
+/* ============================================
+ RESET & BASE
+ ============================================ */
+*{box-sizing:border-box;margin:0;padding:0}
+html{height:100%}
+body{
+ font-family:var(--font-body);
+ background:var(--bg);
+ color:var(--ink);
+ line-height:1.6;
+ -webkit-font-smoothing:antialiased;
+ overflow:hidden;
+}
+
+/* ============================================
+ HEADER — Fixed Wordmark Lockup
+ ============================================ */
+header{
+ position:fixed;
+ top:0;
+ left:0;
+ right:0;
+ height:var(--header-height);
+ background:var(--bg);
+ border-bottom:1px solid var(--line);
+ display:flex;
+ align-items:center;
+ padding:0 var(--space-xl);
+ z-index:1000;
+}
+
+.wordmark{
+ font-family:var(--font-display);
+ font-size:26px;
+ letter-spacing:0.18em;
+ text-transform:uppercase;
+ color:var(--ink);
+ font-weight:400;
+ white-space:nowrap;
+}
+
+/* ============================================
+ CAROUSEL CONTAINER
+ ============================================ */
+.carousel-container{
+ position:fixed;
+ top:var(--header-height);
+ left:50%;
+ transform:translateX(-50%);
+ width:var(--carousel-size);
+ height:var(--carousel-size);
+ background:var(--surface);
+ box-shadow:0 25px 80px var(--shadow);
+ overflow:hidden;
+}
+
+.carousel-track{
+ display:flex;
+ height:100%;
+ transition:transform 0.6s var(--ease-power);
+ will-change:transform;
+}
+
+.slide{
+ width:var(--carousel-size);
+ height:var(--carousel-size);
+ flex-shrink:0;
+ position:relative;
+ overflow:hidden;
+}
+
+/* ============================================
+ TYPOGRAPHY SYSTEM
+ ============================================ */
+.display-xl{
+ font-family:var(--font-display);
+ font-size:67px;
+ line-height:1.05;
+ letter-spacing:-0.02em;
+ font-weight:400;
+}
+
+.display{
+ font-family:var(--font-display);
+ font-size:50px;
+ line-height:1.1;
+ letter-spacing:-0.01em;
+ font-weight:400;
+}
+
+.heading{
+ font-family:var(--font-display);
+ font-size:38px;
+ line-height:1.2;
+ font-weight:400;
+}
+
+.label{
+ font-family:var(--font-body);
+ font-size:12px;
+ letter-spacing:0.18em;
+ text-transform:uppercase;
+ color:var(--muted);
+ font-weight:500;
+}
+
+.body{
+ font-family:var(--font-body);
+ font-size:16px;
+ line-height:1.7;
+ color:var(--muted);
+}
+
+/* ============================================
+ SLIDE 1 — COVER
+ ============================================ */
+.slide-cover{
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ align-items:center;
+ text-align:center;
+ padding:var(--space-2xl);
+ background:linear-gradient(135deg,var(--surface) 0%,var(--bg) 100%);
+}
+
+.season-label{
+ margin-bottom:var(--space-lg);
+ animation:fadeUp 0.8s var(--ease-entrance) both;
+}
+
+.palette-name{
+ color:var(--ink);
+ margin-bottom:var(--space-md);
+ animation:fadeUp 0.8s var(--ease-entrance) 0.1s both;
+}
+
+.accent-line{
+ width:80px;
+ height:1px;
+ background:var(--accent);
+ margin:var(--space-lg) auto;
+ animation:scaleX 0.8s var(--ease-entrance) 0.2s both;
+}
+
+.palette-meta{
+ max-width:480px;
+ animation:fadeUp 0.8s var(--ease-entrance) 0.3s both;
+}
+
+/* ============================================
+ SLIDES 2-4 — COLOR SWATCHES
+ ============================================ */
+.slide-hue{
+ display:grid;
+ grid-template-columns:1fr 1fr;
+ height:100%;
+}
+
+.swatch-panel{
+ position:relative;
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ padding:var(--space-2xl);
+ overflow:hidden;
+}
+
+/* Oatmeal — Linen Texture */
+.swatch-oatmeal{
+ background-color:#D4C4B0;
+ background-image:
+ repeating-linear-gradient(90deg,transparent,transparent 2px,rgba(255,255,255,0.1) 2px,rgba(255,255,255,0.1) 4px),
+ repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,0.03) 2px,rgba(0,0,0,0.03) 4px);
+}
+
+/* Celadon — Grasscloth Texture */
+.swatch-celadon{
+ background-color:#A8B5A0;
+ background-image:
+ repeating-linear-gradient(90deg,rgba(255,255,255,0.15) 0px,rgba(255,255,255,0.15) 1px,transparent 1px,transparent 12px),
+ repeating-linear-gradient(0deg,rgba(0,0,0,0.05) 0px,rgba(0,0,0,0.05) 1px,transparent 1px,transparent 8px);
+}
+
+/* Terracotta — Geometric Deco Pattern */
+.swatch-terracotta{
+ background-color:#B85C3F;
+ background-image:
+ linear-gradient(45deg,rgba(255,255,255,0.1) 25%,transparent 25%,transparent 75%,rgba(255,255,255,0.1) 75%,rgba(255,255,255,0.1)),
+ linear-gradient(45deg,rgba(255,255,255,0.1) 25%,transparent 25%,transparent 75%,rgba(255,255,255,0.1) 75%,rgba(255,255,255,0.1));
+ background-size:60px 60px;
+ background-position:0 0,30px 30px;
+}
+
+.info-panel{
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ padding:var(--space-2xl);
+ background:var(--surface);
+}
+
+.hue-name{
+ color:var(--ink);
+ margin-bottom:var(--space-sm);
+ animation:fadeUp 0.7s var(--ease-entrance) both;
+}
+
+.hue-designer{
+ font-family:var(--font-body);
+ font-size:12px;
+ letter-spacing:0.15em;
+ text-transform:uppercase;
+ color:var(--accent);
+ margin-bottom:var(--space-xl);
+ animation:fadeUp 0.7s var(--ease-entrance) 0.1s both;
+}
+
+.hairline{
+ width:40px;
+ height:1px;
+ background:var(--line);
+ margin-bottom:var(--space-lg);
+ animation:scaleX 0.6s var(--ease-entrance) 0.2s both;
+}
+
+.room-tip{
+ max-width:360px;
+ animation:fadeUp 0.7s var(--ease-entrance) 0.3s both;
+}
+
+.tip-label{
+ display:block;
+ margin-bottom:var(--space-sm);
+}
+
+/* ============================================
+ SLIDE 5 — CTA
+ ============================================ */
+.slide-cta{
+ display:flex;
+ flex-direction:column;
+ justify-content:center;
+ align-items:center;
+ text-align:center;
+ padding:var(--space-2xl);
+ background:var(--ink);
+ color:var(--bg);
+}
+
+.cta-heading{
+ color:var(--bg);
+ margin-bottom:var(--space-md);
+ animation:fadeUp 0.8s var(--ease-entrance) both;
+}
+
+.cta-sub{
+ color:var(--muted);
+ margin-bottom:var(--space-xl);
+ max-width:420px;
+ animation:fadeUp 0.8s var(--ease-entrance) 0.1s both;
+}
+
+.cta-button{
+ display:inline-block;
+ padding:var(--space-md) var(--space-xl);
+ border:1px solid var(--accent);
+ color:var(--accent);
+ font-family:var(--font-body);
+ font-size:12px;
+ letter-spacing:0.18em;
+ text-transform:uppercase;
+ text-decoration:none;
+ transition:all 0.3s var(--ease-swift);
+ animation:fadeUp 0.8s var(--ease-entrance) 0.2s both;
+}
+
+.cta-button:hover{
+ background:var(--accent);
+ color:var(--ink);
+}
+
+/* ============================================
+ NAVIGATION DOTS
+ ============================================ */
+.nav-dots{
+ position:absolute;
+ bottom:var(--space-xl);
+ left:50%;
+ transform:translateX(-50%);
+ display:flex;
+ gap:var(--space-md);
+ z-index:100;
+}
+
+.dot{
+ width:8px;
+ height:8px;
+ border-radius:50%;
+ border:1px solid var(--line);
+ background:transparent;
+ cursor:pointer;
+ transition:all 0.3s var(--ease-swift);
+}
+
+.dot.active{
+ background:var(--accent);
+ border-color:var(--accent);
+ transform:scale(1.2);
+}
+
+/* Dark slide dots adjustment */
+.slide-cta ~ .nav-dots .dot,
+.slide-cta .nav-dots .dot{
+ border-color:rgba(245,242,234,0.4);
+}
+
+/* ============================================
+ SWIPE HINT
+ ============================================ */
+.swipe-hint{
+ position:absolute;
+ bottom:var(--space-xl);
+ right:var(--space-xl);
+ font-family:var(--font-body);
+ font-size:11px;
+ letter-spacing:0.15em;
+ text-transform:uppercase;
+ color:var(--muted);
+ display:flex;
+ align-items:center;
+ gap:var(--space-sm);
+ animation:fadeUp 0.8s var(--ease-entrance) 0.5s both;
+}
+
+.swipe-hint::after{
+ content:'→';
+ font-size:14px;
+ animation:swipeHint 2s infinite;
+}
+
+/* ============================================
+ ANIMATIONS
+ ============================================ */
+@keyframes fadeUp{
+ from{opacity:0;transform:translateY(28px)}
+ to{opacity:1;transform:none}
+}
+
+@keyframes scaleX{
+ from{transform:scaleX(0)}
+ to{transform:scaleX(1)}
+}
+
+@keyframes swipeHint{
+ 0%,100%{transform:translateX(0)}
+ 50%{transform:translateX(6px)}
+}
+
+/* ============================================
+ RESPONSIVE SCALING
+ ============================================ */
+@media(max-width:1120px){
+ :root{
+ --carousel-size:100vw;
+ }
+ .carousel-container{
+ top:var(--header-height);
+ height:calc(100vh - var(--header-height));
+ }
+ .slide{
+ height:calc(100vh - var(--header-height));
+ }
+ .display-xl{font-size:48px}
+ .display{font-size:38px}
+ .heading{font-size:32px}
+}
+</style>
+</head>
+<body>
+
+<!-- HEADER: Fixed Wordmark Lockup -->
+<header>
+ <div class="wordmark">Designer Wallcoverings</div>
+</header>
+
+<!-- CAROUSEL -->
+<div class="carousel-container" id="carousel">
+ <div class="carousel-track" id="track">
+
+ <!-- SLIDE 1: Cover -->
+ <div class="slide slide-cover">
+ <div class="label season-label">Spring 2025 Collection</div>
+ <h1 class="display-xl palette-name">Terracotta<br>& Sage</h1>
+ <div class="accent-line"></div>
+ <p class="body palette-meta">An earthy dialogue between sunbaked clay and quiet garden foliage. Designed for spaces that breathe.</p>
+ <div class="swipe-hint">Swipe</div>
+ </div>
+
+ <!-- SLIDE 2: Oatmeal -->
+ <div class="slide">
+ <div class="slide-hue">
+ <div class="swatch-panel swatch-oatmeal"></div>
+ <div class="info-panel">
+ <h2 class="heading hue-name">Oatmeal</h2>
+ <div class="hue-designer">Atelier Lune</div>
+ <div class="hairline"></div>
+ <div class="body room-tip">
+ <span class="label tip-label">Room Tip</span>
+ Layer with raw linen drapery and aged brass fixtures. Ideal for north-facing rooms that crave warmth without yellow undertones.
+ </div>
+ </div>
+ </div>
+ <div class="nav-dots" data-slide="1">
+ <span class="dot" onclick="goToSlide(0)"></span>
+ <span class="dot active" onclick="goToSlide(1)"></span>
+ <span class="dot" onclick="goToSlide(2)"></span>
+ <span class="dot" onclick="goToSlide(3)"></span>
+ <span class="dot" onclick="goToSlide(4)"></span>
+ </div>
+ </div>
+
+ <!-- SLIDE 3: Celadon -->
+ <div class="slide">
+ <div class="slide-hue">
+ <div class="swatch-panel swatch-celadon"></div>
+ <div class="info-panel">
+ <h2 class="heading hue-name">Celadon</h2>
+ <div class="hue-designer">Studio Foliage</div>
+ <div class="hairline"></div>
+ <div class="body room-tip">
+ <span class="label tip-label">Room Tip</span>
+ Pair with ebonized oak and hand-thrown ceramics. The vertical texture draws the eye upward, making ceilings feel higher.
+ </div>
+ </div>
+ </div>
+ <div class="nav-dots" data-slide="2">
+ <span class="dot" onclick="goToSlide(0)"></span>
+ <span class="dot" onclick="goToSlide(1)"></span>
+ <span class="dot active" onclick="goToSlide(2)"></span>
+ <span class="dot" onclick="goToSlide(3)"></span>
+ <span class="dot" onclick="goToSlide(4)"></span>
+ </div>
+ </div>
+
+ <!-- SLIDE 4: Terracotta -->
+ <div class="slide">
+ <div class="slide-hue">
+ <div class="swatch-panel swatch-terracotta"></div>
+ <div class="info-panel">
+ <h2 class="heading hue-name">Terracotta</h2>
+ <div class="hue-designer">Earth Works Design</div>
+ <div class="hairline"></div>
+ <div class="body room-tip">
+ <span class="label tip-label">Room Tip</span>
+ Balance with cool plaster whites and blackened steel. Use in dining spaces to stimulate conversation and appetite.
+ </div>
+ </div>
+ </div>
+ <div class="nav-dots" data-slide="3">
+ <span class="dot" onclick="goToSlide(0)"></span>
+ <span class="dot" onclick="goToSlide(1)"></span>
+ <span class="dot" onclick="goToSlide(2)"></span>
+ <span class="dot active" onclick="goToSlide(3)"></span>
+ <span class="dot" onclick="goToSlide(4)"></span>
+ </div>
+ </div>
+
+ <!-- SLIDE 5: CTA -->
+ <div class="slide slide-cta">
+ <h2 class="display cta-heading">Curate Your<br>Environment</h2>
+ <p class="body cta-sub">Request a sample portfolio or schedule a consultation with our design team.</p>
+ <a href="#" class="cta-button" onclick="showComingSoon(event)">Request Samples</a>
+ <div class="nav-dots" data-slide="4" style="margin-top:var(--space-2xl);position:static;transform:none;">
+ <span class="dot" onclick="goToSlide(0)"></span>
+ <span class="dot" onclick="goToSlide(1)"></span>
+ <span class="dot" onclick="goToSlide(2)"></span>
+ <span class="dot" onclick="goToSlide(3)"></span>
+ <span class="dot active" onclick="goToSlide(4)"></span>
+ </div>
+ </div>
+
+ </div>
+
+ <!-- Global Nav Dots (for non-split slides) -->
+ <div class="nav-dots" id="globalDots" style="display:none;">
+ <span class="dot" onclick="goToSlide(0)"></span>
+ <span class="dot" onclick="goToSlide(1)"></span>
+ <span class="dot" onclick="goToSlide(2)"></span>
+ <span class="dot" onclick="goToSlide(3)"></span>
+ <span class="dot" onclick="goToSlide(4)"></span>
+ </div>
+</div>
+
+<!-- COMING SOON OVERLAY -->
+<div id="overlay" style="position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(13,13,15,0.95);display:none;justify-content:center;align-items:center;z-index:2000;opacity:0;transition:opacity 0.4s var(--ease-swift);">
+ <div style="text-align:center;padding:var(--space-2xl);">
+ <h3 class="heading" style="color:var(--bg);margin-bottom:var(--space-md);">Coming Soon</h3>
+ <p class="body" style="color:var(--muted);margin-bottom:var(--space-xl);">Our sample ordering system launches Spring 2025.</p>
+ <button onclick="hideOverlay()" style="padding:var(--space-md) var(--space-xl);border:1px solid var(--accent);background:transparent;color:var(--accent);font-family:var(--font-body);font-size:12px;letter-spacing:0.18em;text-transform:uppercase;cursor:pointer;transition:all 0.3s var(--ease-swift);">Close</button>
+ </div>
+</div>
+
+<script>
+let currentSlide=0;
+const totalSlides=5;
+const track=document.getElementById('track');
+const carousel=document.getElementById('carousel');
+let startX=0;
+let isDragging=false;
+
+function updateCarousel(){
+ track.style.transform=`translateX(-${currentSlide*100}%)`;
+
+ // Update all dots
+ document.querySelectorAll('.nav-dots').forEach(dotContainer=>{
+ const dots=dotContainer.querySelectorAll('.dot');
+ dots.forEach((dot,index)=>{
+ if(dotContainer.getAttribute('data-slide')==String(currentSlide)){
+ dot.classList.toggle('active',index===currentSlide);
+ }else{
+ dot.classList.remove('active');
+ }
+ });
+ });
+
+ // Show/hide global dots based on slide
+ const globalDots=document.getElementById('globalDots');
+ if(currentSlide===0 || currentSlide===4){
+ globalDots.style.display='flex';
+ globalDots.querySelectorAll('.dot').forEach((dot,index)=>{
+ dot.classList.toggle('active',index===currentSlide);
+ });
+ }else{
+ globalDots.style.display='none';
+ }
+}
+
+function goToSlide(index){
+ if(index>=0 && index<totalSlides){
+ currentSlide=index;
+ updateCarousel();
+ }
+}
+
+function nextSlide(){
+ if(currentSlide<totalSlides-1){
+ currentSlide++;
+ updateCarousel();
+ }
+}
+
+function prevSlide(){
+ if(currentSlide>0){
+ currentSlide--;
+ updateCarousel();
+ }
+}
+
+// Touch/Swipe handlers
+carousel.addEventListener('touchstart',(e)=>{
+ startX=e.touches[0].clientX;
+ isDragging=true;
+},{passive:true});
+
+carousel.addEventListener('touchmove',(e)=>{
+ if(!isDragging)return;
+ const currentX=e.touches[0].clientX;
+ const diff=startX-currentX;
+ if(Math.abs(diff)>50){
+ if(diff>0)nextSlide();
+ else prevSlide();
+ isDragging=false;
+ }
+},{passive:true});
+
+carousel.addEventListener('touchend',()=>{
+ isDragging=false;
+});
+
+// Mouse drag support
+carousel.addEventListener('mousedown',(e)=>{
+ startX=e.clientX;
+ isDragging=true;
+});
+
+carousel.addEventListener('mousemove',(e)=>{
+ if(!isDragging)return;
+ const diff=startX-e.clientX;
+ if(Math.abs(diff)>50){
+ if(diff>0)nextSlide();
+ else prevSlide();
+ isDragging=false;
+ }
+});
+
+carousel.addEventListener('mouseup',()=>{
+ isDragging=false;
+});
+
+// Keyboard navigation
+document.addEventListener('keydown',(e)=>{
+ if(e.key==='ArrowRight')nextSlide();
+ if(e.key==='ArrowLeft')prevSlide();
+});
+
+// Overlay functions
+function showComingSoon(e){
+ e.preventDefault();
+ const overlay=document.getElementById('overlay');
+ overlay.style.display='flex';
+ setTimeout(()=>overlay.style.opacity='1',10);
+}
+
+function hideOverlay(){
+ const overlay=document.getElementById('overlay');
+ overlay.style.opacity='0';
+ setTimeout(()=>overlay.style.display='none',400);
+}
+
+// Initialize
+updateCarousel();
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/6e1b0984b54e/kimi.png b/data/artifacts/6e1b0984b54e/kimi.png
new file mode 100644
index 0000000..5d6a70c
Binary files /dev/null and b/data/artifacts/6e1b0984b54e/kimi.png differ
diff --git a/data/artifacts/bf0bdeb4c423/claude-code.html b/data/artifacts/bf0bdeb4c423/claude-code.html
new file mode 100644
index 0000000..a139344
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/claude-code.html
@@ -0,0 +1,858 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Guess the Style — Designer Wallcoverings</title>
+<style>
+ :root{
+ --bg:#faf8f4;
+ --surface:#ffffff;
+ --ink:#1c1a17;
+ --muted:#9b948a;
+ --accent:#b0472e;
+ --accent-2:#2f4c39;
+ --line:rgba(28,26,23,.12);
+ --hair:rgba(28,26,23,.08);
+ --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:'Cormorant Garamond','Playfair Display','EB Garamond',Didot,'Bodoni MT',Georgia,serif;
+ --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+ --gold:#b8975a;
+ }
+
+ *{box-sizing:border-box;margin:0;padding:0;}
+
+ html,body{height:100%;}
+ body{
+ background:var(--bg);
+ color:var(--ink);
+ font-family:var(--sans);
+ font-size:16px;
+ line-height:1.5;
+ -webkit-font-smoothing:antialiased;
+ min-height:100%;
+ display:flex;
+ flex-direction:column;
+ }
+
+ /* ————— HEADER / WORDMARK ————— */
+ header.topbar{
+ position:sticky;
+ top:0;
+ z-index:50;
+ background:rgba(250,248,244,.92);
+ backdrop-filter:blur(10px);
+ -webkit-backdrop-filter:blur(10px);
+ border-bottom:1px solid var(--line);
+ padding:18px 28px;
+ display:flex;
+ align-items:center;
+ gap:20px;
+ }
+ .wordmark{
+ display:flex;
+ flex-direction:column;
+ line-height:1;
+ text-decoration:none;
+ color:var(--ink);
+ }
+ .wordmark .brand{
+ font-family:var(--serif);
+ font-weight:600;
+ font-size:25px;
+ letter-spacing:.18em;
+ text-transform:uppercase;
+ color:var(--ink);
+ white-space:nowrap;
+ }
+ .wordmark .sub{
+ font-family:var(--sans);
+ font-size:9.5px;
+ letter-spacing:.34em;
+ text-transform:uppercase;
+ color:var(--muted);
+ margin-top:5px;
+ padding-left:2px;
+ }
+ .topbar-rule{
+ flex:1;
+ height:1px;
+ background:var(--line);
+ }
+ .topbar-tag{
+ font-family:var(--sans);
+ font-size:11px;
+ letter-spacing:.2em;
+ text-transform:uppercase;
+ color:var(--accent);
+ white-space:nowrap;
+ }
+
+ /* ————— LAYOUT ————— */
+ main{
+ flex:1;
+ display:flex;
+ flex-direction:column;
+ align-items:center;
+ justify-content:flex-start;
+ padding:40px 24px 64px;
+ width:100%;
+ }
+ .stage{
+ width:100%;
+ max-width:560px;
+ display:flex;
+ flex-direction:column;
+ align-items:center;
+ }
+
+ /* ————— SCOREBOARD ————— */
+ .board{
+ width:100%;
+ display:flex;
+ justify-content:space-between;
+ gap:12px;
+ margin-bottom:28px;
+ }
+ .stat{
+ flex:1;
+ background:var(--surface);
+ border:1px solid var(--hair);
+ border-radius:12px;
+ padding:12px 8px 11px;
+ text-align:center;
+ box-shadow:var(--shadow);
+ }
+ .stat .label{
+ font-family:var(--sans);
+ font-size:10px;
+ letter-spacing:.15em;
+ text-transform:uppercase;
+ color:var(--muted);
+ display:block;
+ }
+ .stat .value{
+ font-family:var(--serif);
+ font-size:30px;
+ font-weight:600;
+ color:var(--ink);
+ line-height:1.1;
+ margin-top:3px;
+ font-variant-numeric:tabular-nums;
+ }
+ .stat.accent .value{color:var(--accent);}
+ .stat.streak .value{color:var(--gold);}
+
+ /* ————— TIMER BAR ————— */
+ .timerwrap{
+ width:100%;
+ margin-bottom:22px;
+ }
+ .timer-meta{
+ display:flex;
+ justify-content:space-between;
+ align-items:baseline;
+ margin-bottom:8px;
+ }
+ .round-label{
+ font-family:var(--sans);
+ font-size:11px;
+ letter-spacing:.18em;
+ text-transform:uppercase;
+ color:var(--muted);
+ }
+ .timer-num{
+ font-family:var(--serif);
+ font-size:19px;
+ color:var(--ink);
+ font-variant-numeric:tabular-nums;
+ }
+ .timer-track{
+ width:100%;
+ height:3px;
+ background:var(--hair);
+ border-radius:2px;
+ overflow:hidden;
+ }
+ .timer-fill{
+ height:100%;
+ width:100%;
+ background:var(--accent);
+ border-radius:2px;
+ transform-origin:left;
+ transition:width .1s linear,background .3s var(--ease);
+ }
+
+ /* ————— MOTIF CARD ————— */
+ .motif-card{
+ width:100%;
+ aspect-ratio:1/1;
+ max-width:400px;
+ background:var(--surface);
+ border:1px solid var(--line);
+ border-radius:14px;
+ box-shadow:var(--shadow-hi);
+ overflow:hidden;
+ position:relative;
+ margin-bottom:26px;
+ transition:transform .5s var(--ease),box-shadow .5s var(--ease);
+ }
+ .motif-card.enter{
+ animation:fadeUp .7s var(--ease) both;
+ }
+ .motif-inner{
+ position:absolute;
+ inset:0;
+ }
+ .motif-frame{
+ position:absolute;
+ inset:14px;
+ border:1px solid var(--hair);
+ border-radius:6px;
+ pointer-events:none;
+ z-index:3;
+ }
+ .motif-card.correct{
+ box-shadow:0 0 0 2px var(--accent-2),var(--shadow-hi);
+ }
+ .motif-card.wrong{
+ animation:shake .5s var(--ease);
+ box-shadow:0 0 0 2px var(--accent),var(--shadow-hi);
+ }
+
+ /* ————— CHOICES ————— */
+ .prompt-line{
+ font-family:var(--serif);
+ font-size:24px;
+ font-weight:500;
+ text-align:center;
+ margin-bottom:20px;
+ color:var(--ink);
+ }
+ .choices{
+ width:100%;
+ display:grid;
+ grid-template-columns:1fr 1fr;
+ gap:12px;
+ }
+ .choice{
+ font-family:var(--sans);
+ font-size:12px;
+ letter-spacing:.15em;
+ text-transform:uppercase;
+ font-weight:600;
+ color:var(--ink);
+ background:var(--surface);
+ border:1px solid var(--line);
+ border-radius:12px;
+ padding:16px 10px;
+ cursor:pointer;
+ transition:transform .18s var(--ease),box-shadow .18s var(--ease),border-color .18s var(--ease),background .18s var(--ease),color .18s var(--ease);
+ box-shadow:var(--shadow);
+ position:relative;
+ }
+ .choice:hover:not(:disabled){
+ transform:translateY(-2px);
+ box-shadow:var(--shadow-hi);
+ border-color:var(--gold);
+ }
+ .choice:active:not(:disabled){transform:translateY(0);}
+ .choice:disabled{cursor:default;}
+ .choice.right{
+ background:var(--accent-2);
+ color:#fff;
+ border-color:var(--accent-2);
+ }
+ .choice.wrongpick{
+ background:var(--accent);
+ color:#fff;
+ border-color:var(--accent);
+ }
+ .choice.dim{opacity:.4;}
+
+ /* ————— OVERLAY ————— */
+ .overlay{
+ position:fixed;
+ inset:0;
+ background:rgba(28,26,23,.55);
+ backdrop-filter:blur(6px);
+ -webkit-backdrop-filter:blur(6px);
+ display:flex;
+ align-items:center;
+ justify-content:center;
+ padding:24px;
+ z-index:100;
+ opacity:0;
+ pointer-events:none;
+ transition:opacity .4s var(--ease);
+ }
+ .overlay.show{opacity:1;pointer-events:auto;}
+ .modal{
+ background:var(--surface);
+ border-radius:16px;
+ box-shadow:var(--shadow-hi);
+ border:1px solid var(--line);
+ max-width:400px;
+ width:100%;
+ padding:44px 36px 38px;
+ text-align:center;
+ transform:translateY(20px) scale(.98);
+ transition:transform .5s var(--ease);
+ }
+ .overlay.show .modal{transform:none;}
+ .modal .eyebrow{
+ font-family:var(--sans);
+ font-size:11px;
+ letter-spacing:.24em;
+ text-transform:uppercase;
+ color:var(--accent);
+ margin-bottom:14px;
+ }
+ .modal h2{
+ font-family:var(--serif);
+ font-size:44px;
+ font-weight:600;
+ line-height:1.05;
+ margin-bottom:8px;
+ color:var(--ink);
+ }
+ .modal .score-big{
+ font-family:var(--serif);
+ font-size:64px;
+ font-weight:600;
+ color:var(--accent);
+ line-height:1;
+ margin:18px 0 6px;
+ font-variant-numeric:tabular-nums;
+ }
+ .modal .score-cap{
+ font-family:var(--sans);
+ font-size:12px;
+ letter-spacing:.15em;
+ text-transform:uppercase;
+ color:var(--muted);
+ margin-bottom:8px;
+ }
+ .modal .best-note{
+ font-family:var(--sans);
+ font-size:14px;
+ color:var(--ink);
+ margin-bottom:26px;
+ }
+ .modal .best-note .crown{color:var(--gold);}
+ .btn{
+ font-family:var(--sans);
+ font-size:12px;
+ letter-spacing:.18em;
+ text-transform:uppercase;
+ font-weight:600;
+ color:#fff;
+ background:var(--ink);
+ border:none;
+ border-radius:10px;
+ padding:16px 34px;
+ cursor:pointer;
+ transition:transform .18s var(--ease),background .18s var(--ease);
+ }
+ .btn:hover{transform:translateY(-2px);background:var(--accent);}
+ .btn:active{transform:translateY(0);}
+
+ .footnote{
+ font-family:var(--sans);
+ font-size:10px;
+ letter-spacing:.2em;
+ text-transform:uppercase;
+ color:var(--muted);
+ text-align:center;
+ margin-top:30px;
+ }
+
+ /* ————— ANIMATIONS ————— */
+ @keyframes fadeUp{
+ from{opacity:0;transform:translateY(28px);}
+ to{opacity:1;transform:none;}
+ }
+ @keyframes shake{
+ 0%,100%{transform:translateX(0);}
+ 20%{transform:translateX(-8px);}
+ 40%{transform:translateX(8px);}
+ 60%{transform:translateX(-5px);}
+ 80%{transform:translateX(5px);}
+ }
+ @keyframes pop{
+ 0%{transform:scale(1);}
+ 50%{transform:scale(1.06);}
+ 100%{transform:scale(1);}
+ }
+ .pop{animation:pop .4s var(--ease);}
+
+ @media(max-width:480px){
+ header.topbar{padding:14px 18px;}
+ .wordmark .brand{font-size:21px;}
+ .topbar-tag{display:none;}
+ .prompt-line{font-size:21px;}
+ .modal h2{font-size:36px;}
+ }
+</style>
+</head>
+<body>
+ <header class="topbar">
+ <a class="wordmark" href="#" onclick="return false;">
+ <span class="brand">Designer Wallcoverings</span>
+ <span class="sub">Pattern Atelier</span>
+ </a>
+ <span class="topbar-rule"></span>
+ <span class="topbar-tag">Guess the Style</span>
+ </header>
+
+ <main>
+ <div class="stage">
+ <div class="board">
+ <div class="stat accent">
+ <span class="label">Score</span>
+ <span class="value" id="scoreVal">0</span>
+ </div>
+ <div class="stat streak">
+ <span class="label">Streak</span>
+ <span class="value" id="streakVal">0</span>
+ </div>
+ <div class="stat">
+ <span class="label">Best</span>
+ <span class="value" id="bestVal">0</span>
+ </div>
+ </div>
+
+ <div class="timerwrap">
+ <div class="timer-meta">
+ <span class="round-label" id="roundLabel">Round 1 / 10</span>
+ <span class="timer-num" id="timerNum">8.0s</span>
+ </div>
+ <div class="timer-track">
+ <div class="timer-fill" id="timerFill"></div>
+ </div>
+ </div>
+
+ <div class="motif-card" id="motifCard">
+ <div class="motif-inner" id="motifInner"></div>
+ <div class="motif-frame"></div>
+ </div>
+
+ <div class="prompt-line">Name this pattern</div>
+
+ <div class="choices" id="choices"></div>
+
+ <div class="footnote">A parlour game of pattern & provenance</div>
+ </div>
+ </main>
+
+ <div class="overlay" id="overlay">
+ <div class="modal">
+ <div class="eyebrow" id="modalEyebrow">The Reveal</div>
+ <h2 id="modalTitle">Beautifully Done</h2>
+ <div class="score-big" id="modalScore">0</div>
+ <div class="score-cap">Points of 10</div>
+ <div class="best-note" id="modalBest"></div>
+ <button class="btn" id="restartBtn">Play Again</button>
+ </div>
+ </div>
+
+<script>
+(function(){
+ "use strict";
+
+ /* ————— STYLE DEFINITIONS with distinct CSS-drawn motifs ————— */
+ const STYLES = {
+ Damask:{
+ name:"Damask",
+ draw:function(ground,ink){
+ // ornate mirrored medallion, tonal
+ return `
+ <div style="position:absolute;inset:0;background:${ground};"></div>
+ <div style="position:absolute;inset:0;background-image:
+ radial-gradient(ellipse 22% 32% at 50% 26%, ${ink} 0 42%, transparent 44%),
+ radial-gradient(ellipse 9% 20% at 50% 8%, ${ink} 0 50%, transparent 52%),
+ radial-gradient(ellipse 30% 20% at 50% 55%, ${ink} 0 40%, transparent 42%),
+ radial-gradient(circle 7% at 30% 42%, ${ink} 0 55%, transparent 57%),
+ radial-gradient(circle 7% at 70% 42%, ${ink} 0 55%, transparent 57%),
+ radial-gradient(ellipse 12% 26% at 26% 70%, ${ink} 0 46%, transparent 48%),
+ radial-gradient(ellipse 12% 26% at 74% 70%, ${ink} 0 46%, transparent 48%),
+ radial-gradient(ellipse 20% 14% at 50% 88%, ${ink} 0 44%, transparent 46%);
+ background-size:50% 50%;background-position:center;opacity:.9;"></div>
+ <div style="position:absolute;inset:0;background-image:
+ radial-gradient(ellipse 22% 32% at 0% 76%, ${ink} 0 42%, transparent 44%),
+ radial-gradient(ellipse 22% 32% at 100% 76%, ${ink} 0 42%, transparent 44%);
+ background-size:50% 50%;opacity:.55;"></div>`;
+ }
+ },
+ Toile:{
+ name:"Toile",
+ draw:function(ground,ink){
+ // fine-line pastoral scene: rolling hills, tree, cottage, sun — sketchy monochrome
+ return `
+ <div style="position:absolute;inset:0;background:${ground};"></div>
+ <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style="position:absolute;inset:0;width:100%;height:100%;">
+ <g fill="none" stroke="${ink}" stroke-width="0.7" stroke-linecap="round" opacity="0.85">
+ <path d="M0 74 Q25 62 50 72 T100 70"/>
+ <path d="M0 84 Q30 76 60 84 T100 82"/>
+ <circle cx="78" cy="22" r="7"/>
+ <path d="M78 22 L78 8 M78 22 L92 22 M78 22 L88 12 M78 22 L68 12 M78 22 L88 32"/>
+ <path d="M22 74 L22 52"/>
+ <circle cx="22" cy="44" r="9"/>
+ <circle cx="15" cy="48" r="7"/>
+ <circle cx="29" cy="48" r="7"/>
+ <path d="M46 72 L46 60 L56 52 L66 60 L66 72 Z"/>
+ <path d="M52 72 L52 64 L60 64 L60 72"/>
+ <path d="M46 60 L56 52 L66 60"/>
+ <path d="M8 72 q3 -6 6 0 M12 74 q3 -6 6 0"/>
+ </g>
+ </svg>`;
+ }
+ },
+ Ikat:{
+ name:"Ikat",
+ draw:function(ground,ink){
+ // blurred feathered diamond chevrons — the signature ikat bleed
+ return `
+ <div style="position:absolute;inset:0;background:${ground};"></div>
+ <div style="position:absolute;inset:0;background-image:
+ linear-gradient(135deg, transparent 42%, ${ink} 44%, ${ink} 56%, transparent 58%),
+ linear-gradient(45deg, transparent 42%, ${ink} 44%, ${ink} 56%, transparent 58%);
+ background-size:33.33% 33.33%;filter:blur(1.4px);opacity:.9;"></div>
+ <div style="position:absolute;inset:0;background-image:
+ linear-gradient(135deg, transparent 47%, ${ground} 48%, ${ground} 52%, transparent 53%),
+ linear-gradient(45deg, transparent 47%, ${ground} 48%, ${ground} 52%, transparent 53%);
+ background-size:33.33% 33.33%;filter:blur(1px);"></div>`;
+ }
+ },
+ Chinoiserie:{
+ name:"Chinoiserie",
+ draw:function(ground,ink){
+ // asymmetric flowering branch with blossoms and a bird — hand-painted feel
+ return `
+ <div style="position:absolute;inset:0;background:${ground};"></div>
+ <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid slice" style="position:absolute;inset:0;width:100%;height:100%;">
+ <g fill="none" stroke="${ink}" stroke-width="1.1" stroke-linecap="round" opacity="0.9">
+ <path d="M18 100 Q28 70 40 54 Q52 38 74 26"/>
+ <path d="M40 54 Q50 46 62 46"/>
+ <path d="M52 40 Q60 30 58 18"/>
+ <path d="M30 68 Q22 62 14 64"/>
+ </g>
+ <g fill="${ink}" opacity="0.82">
+ <g transform="translate(74,24)"><circle cx="0" cy="-4" r="2.4"/><circle cx="4" cy="-1" r="2.4"/><circle cx="3" cy="4" r="2.4"/><circle cx="-3" cy="4" r="2.4"/><circle cx="-4" cy="-1" r="2.4"/></g>
+ <g transform="translate(58,17)"><circle cx="0" cy="-3.5" r="2"/><circle cx="3.4" cy="-1" r="2"/><circle cx="2.6" cy="3.4" r="2"/><circle cx="-2.6" cy="3.4" r="2"/><circle cx="-3.4" cy="-1" r="2"/></g>
+ <g transform="translate(14,64)"><circle cx="0" cy="-3.5" r="2"/><circle cx="3.4" cy="-1" r="2"/><circle cx="2.6" cy="3.4" r="2"/><circle cx="-2.6" cy="3.4" r="2"/><circle cx="-3.4" cy="-1" r="2"/></g>
+ </g>
+ <g fill="none" stroke="${ink}" stroke-width="1.1" stroke-linecap="round" opacity="0.9">
+ <path d="M40 78 q6 -5 13 -3 q-3 -5 1 -10 q4 6 9 5 q-5 4 -4 10 q-9 -4 -19 -2Z"/>
+ <path d="M53 75 q7 1 12 6"/>
+ </g>
+ </svg>`;
+ }
+ },
+ Geometric:{
+ name:"Geometric",
+ draw:function(ground,ink){
+ // crisp interlocking hexagon / triangle lattice
+ return `
+ <div style="position:absolute;inset:0;background:${ground};"></div>
+ <div style="position:absolute;inset:0;background-image:
+ linear-gradient(30deg, ${ink} 12%, transparent 12.5%, transparent 87%, ${ink} 87.5%),
+ linear-gradient(150deg, ${ink} 12%, transparent 12.5%, transparent 87%, ${ink} 87.5%),
+ linear-gradient(30deg, ${ink} 12%, transparent 12.5%, transparent 87%, ${ink} 87.5%),
+ linear-gradient(150deg, ${ink} 12%, transparent 12.5%, transparent 87%, ${ink} 87.5%);
+ background-size:26px 45px;background-position:0 0,0 0,13px 22.5px,13px 22.5px;opacity:.8;"></div>
+ <div style="position:absolute;inset:0;background-image:
+ radial-gradient(circle 3px at 50% 50%, ${ink} 0 100%, transparent 0);
+ background-size:26px 45px;background-position:0 0;opacity:.6;"></div>`;
+ }
+ },
+ Grasscloth:{
+ name:"Grasscloth",
+ draw:function(ground,ink){
+ // fine woven horizontal fibre texture with subtle vertical slubs
+ return `
+ <div style="position:absolute;inset:0;background:${ground};"></div>
+ <div style="position:absolute;inset:0;background-image:
+ repeating-linear-gradient(0deg, ${ink} 0 1px, transparent 1px 4px);
+ opacity:.28;"></div>
+ <div style="position:absolute;inset:0;background-image:
+ repeating-linear-gradient(90deg, rgba(0,0,0,.10) 0 2px, transparent 2px 9px);
+ opacity:.5;mix-blend-mode:multiply;"></div>
+ <div style="position:absolute;inset:0;background-image:
+ repeating-linear-gradient(0deg, transparent 0 18px, rgba(0,0,0,.06) 18px 19px);
+ "></div>`;
+ }
+ }
+ };
+
+ // Palette pairs (ground, ink) — refined, tonal, luxe. Each round picks one.
+ const PALETTES = [
+ ["#f3ede1","#5a6f5c"], // sage on parchment
+ ["#e9e3d6","#7d3b2e"], // terracotta on oat
+ ["#eae6dd","#2f3d4c"], // slate blue on stone
+ ["#f0e9dd","#6b5636"], // bronze on cream
+ ["#e6e2da","#3a3a44"], // charcoal on grey
+ ["#efe7da","#8a6a3e"], // gold ochre on linen
+ ["#e8e8e2","#4a5d4a"], // forest on pearl
+ ["#f2e8e0","#7a4a55"] // plum-rose on blush
+ ];
+
+ const ALL_KEYS = Object.keys(STYLES);
+ const TOTAL_ROUNDS = 10;
+ const ROUND_TIME = 8.0; // seconds
+
+ // rotate through styles so each appears; shuffle order
+ function shuffle(a){
+ a=a.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;
+ }
+
+ // Build the round sequence: cycle rotated key list to length TOTAL_ROUNDS
+ function buildSequence(){
+ let seq=[];
+ while(seq.length<TOTAL_ROUNDS){
+ seq=seq.concat(shuffle(ALL_KEYS));
+ }
+ return seq.slice(0,TOTAL_ROUNDS);
+ }
+
+ // ————— STATE —————
+ const state={
+ round:0,
+ score:0,
+ streak:0,
+ best:0,
+ seq:[],
+ answer:null,
+ locked:false,
+ timer:null,
+ timeLeft:ROUND_TIME,
+ palette:null
+ };
+
+ // ————— DOM —————
+ const el={
+ score:document.getElementById('scoreVal'),
+ streak:document.getElementById('streakVal'),
+ best:document.getElementById('bestVal'),
+ round:document.getElementById('roundLabel'),
+ timerNum:document.getElementById('timerNum'),
+ timerFill:document.getElementById('timerFill'),
+ motifCard:document.getElementById('motifCard'),
+ motifInner:document.getElementById('motifInner'),
+ choices:document.getElementById('choices'),
+ overlay:document.getElementById('overlay'),
+ modalTitle:document.getElementById('modalTitle'),
+ modalScore:document.getElementById('modalScore'),
+ modalBest:document.getElementById('modalBest'),
+ modalEyebrow:document.getElementById('modalEyebrow'),
+ restart:document.getElementById('restartBtn')
+ };
+
+ // ————— localStorage best —————
+ const LS_KEY='dw_guess_style_best';
+ function loadBest(){
+ try{
+ const v=parseInt(localStorage.getItem(LS_KEY),10);
+ state.best=isNaN(v)?0:v;
+ }catch(e){state.best=0;}
+ el.best.textContent=state.best;
+ }
+ function saveBest(){
+ try{localStorage.setItem(LS_KEY,String(state.best));}catch(e){}
+ }
+
+ // ————— render a round —————
+ function startGame(){
+ state.round=0;
+ state.score=0;
+ state.streak=0;
+ state.seq=buildSequence();
+ el.score.textContent='0';
+ el.streak.textContent='0';
+ el.overlay.classList.remove('show');
+ nextRound();
+ }
+
+ function nextRound(){
+ clearInterval(state.timer);
+ if(state.round>=TOTAL_ROUNDS){
+ endGame();
+ return;
+ }
+ state.locked=false;
+ const key=state.seq[state.round];
+ state.answer=key;
+ state.round++;
+ state.palette=PALETTES[Math.floor(Math.random()*PALETTES.length)];
+
+ el.round.textContent=`Round ${state.round} / ${TOTAL_ROUNDS}`;
+
+ // draw motif
+ const [ground,ink]=state.palette;
+ el.motifInner.innerHTML=STYLES[key].draw(ground,ink);
+ el.motifCard.classList.remove('correct','wrong','enter');
+ void el.motifCard.offsetWidth;
+ el.motifCard.classList.add('enter');
+
+ // build choices: correct + 3 distractors
+ const distractors=shuffle(ALL_KEYS.filter(k=>k!==key)).slice(0,3);
+ const options=shuffle(distractors.concat([key]));
+ el.choices.innerHTML='';
+ options.forEach(function(optKey){
+ const b=document.createElement('button');
+ b.className='choice';
+ b.textContent=STYLES[optKey].name;
+ b.dataset.key=optKey;
+ b.addEventListener('click',function(){onPick(optKey,b);});
+ el.choices.appendChild(b);
+ });
+
+ // timer
+ state.timeLeft=ROUND_TIME;
+ updateTimer();
+ state.timer=setInterval(tick,100);
+ }
+
+ function tick(){
+ state.timeLeft-=0.1;
+ if(state.timeLeft<=0){
+ state.timeLeft=0;
+ updateTimer();
+ timeout();
+ return;
+ }
+ updateTimer();
+ }
+
+ function updateTimer(){
+ const pct=(state.timeLeft/ROUND_TIME)*100;
+ el.timerFill.style.width=pct+'%';
+ el.timerNum.textContent=state.timeLeft.toFixed(1)+'s';
+ if(pct<30){
+ el.timerFill.style.background='var(--accent)';
+ }else if(pct<60){
+ el.timerFill.style.background='var(--gold)';
+ }else{
+ el.timerFill.style.background='var(--accent-2)';
+ }
+ }
+
+ function timeout(){
+ clearInterval(state.timer);
+ if(state.locked)return;
+ state.locked=true;
+ // reveal correct, count as wrong
+ revealAnswer(null);
+ state.streak=0;
+ el.streak.textContent='0';
+ el.motifCard.classList.add('wrong');
+ setTimeout(nextRound,1300);
+ }
+
+ function onPick(optKey,btn){
+ if(state.locked)return;
+ state.locked=true;
+ clearInterval(state.timer);
+
+ const correct=(optKey===state.answer);
+ if(correct){
+ // points: base 5 + time bonus (up to 5)
+ const bonus=Math.round((state.timeLeft/ROUND_TIME)*5);
+ const pts=5+bonus;
+ state.score+=pts;
+ state.streak++;
+ el.score.textContent=state.score;
+ el.streak.textContent=state.streak;
+ el.score.parentElement.classList.remove('pop');
+ void el.score.offsetWidth;
+ el.score.parentElement.classList.add('pop');
+ el.streak.parentElement.classList.add('pop');
+ el.motifCard.classList.add('correct');
+ btn.classList.add('right');
+ dimOthers(btn);
+ }else{
+ state.streak=0;
+ el.streak.textContent='0';
+ btn.classList.add('wrongpick');
+ el.motifCard.classList.add('wrong');
+ revealAnswer(btn);
+ }
+ setTimeout(nextRound, correct?1050:1350);
+ }
+
+ function revealAnswer(exceptBtn){
+ Array.prototype.forEach.call(el.choices.children,function(b){
+ if(b.dataset.key===state.answer){
+ b.classList.add('right');
+ }else if(b!==exceptBtn){
+ b.classList.add('dim');
+ }
+ b.disabled=true;
+ });
+ }
+
+ function dimOthers(rightBtn){
+ Array.prototype.forEach.call(el.choices.children,function(b){
+ b.disabled=true;
+ if(b!==rightBtn)b.classList.add('dim');
+ });
+ }
+
+ function endGame(){
+ clearInterval(state.timer);
+ const isRecord=state.score>state.best;
+ if(isRecord){
+ state.best=state.score;
+ el.best.textContent=state.best;
+ saveBest();
+ }
+ el.modalScore.textContent=state.score;
+
+ // flavour title based on performance (max score = 100)
+ let eyebrow="The Reveal", title="Well Played";
+ const pct=state.score/100;
+ if(pct>=0.85){eyebrow="Connoisseur";title="Exquisite Eye";}
+ else if(pct>=0.6){eyebrow="The Reveal";title="Beautifully Done";}
+ else if(pct>=0.35){eyebrow="The Reveal";title="A Fine Showing";}
+ else{eyebrow="The Reveal";title="Keep Curating";}
+ el.modalEyebrow.textContent=eyebrow;
+ el.modalTitle.textContent=title;
+
+ if(isRecord){
+ el.modalBest.innerHTML='<span class="crown">✦</span> A new personal best';
+ }else{
+ el.modalBest.innerHTML='Personal best: <strong>'+state.best+'</strong>';
+ }
+
+ el.overlay.classList.add('show');
+ }
+
+ el.restart.addEventListener('click',startGame);
+
+ // keyboard: 1-4 to answer
+ document.addEventListener('keydown',function(e){
+ if(el.overlay.classList.contains('show')){
+ if(e.key==='Enter')startGame();
+ return;
+ }
+ const n=parseInt(e.key,10);
+ if(n>=1&&n<=4){
+ const btn=el.choices.children[n-1];
+ if(btn&&!state.locked)btn.click();
+ }
+ });
+
+ // init
+ loadBest();
+ startGame();
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/claude-code.png b/data/artifacts/bf0bdeb4c423/claude-code.png
new file mode 100644
index 0000000..14bf376
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/claude-code.png differ
diff --git a/data/artifacts/bf0bdeb4c423/gemma3-12b.html b/data/artifacts/bf0bdeb4c423/gemma3-12b.html
new file mode 100644
index 0000000..3ff0298
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/gemma3-12b.html
@@ -0,0 +1,306 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Guess the Design Style</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #1c1a17;
+ --muted: #9b948a;
+ --accent: #b0472e; /* Deep red/burgundy */
+ --line: rgba(0, 0, 0, 0.05);
+ --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;
+ }
+
+ header {
+ background-color: var(--surface);
+ padding: 24px;
+ text-align: left;
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: calc(1em + 3vw); /* Responsive scaling */
+ letter-spacing: .18em;
+ text-transform: uppercase;
+ }
+
+ .container {
+ padding: 96px;
+ max-width: 1200px;
+ margin: 0 auto;
+ }
+
+ #wallpaper {
+ width: 100%;
+ height: 400px; /* Fixed height */
+ background-size: cover;
+ border-radius: 14px;
+ box-shadow: 0 8px 24px var(--shadow);
+ }
+
+ .style-buttons {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
+ gap: 24px;
+ margin-top: 32px;
+ }
+
+ .style-button {
+ background-color: var(--surface);
+ border: 1px solid var(--line);
+ padding: 16px;
+ text-align: center;
+ text-transform: uppercase;
+ font-size: calc(0.75em + 0.2vw); /* Responsive */
+ letter-spacing: .15em;
+ color: var(--muted);
+ border-radius: 8px;
+ cursor: pointer;
+ transition: background-color 0.2s var(--ease), transform 0.15s var(--ease);
+ }
+
+ .style-button:hover {
+ background-color: rgba(255, 255, 255, 0.9); /* Slightly transparent */
+ transform: scale(1.05);
+ }
+
+ #score-container {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 24px;
+ margin-top: 32px;
+ }
+
+ .scoreboard {
+ background-color: var(--surface);
+ border: 1px solid var(--line);
+ padding: 16px;
+ text-align: center;
+ text-transform: uppercase;
+ font-size: calc(0.75em + 0.2vw); /* Responsive */
+ letter-spacing: .15em;
+ color: var(--muted);
+ }
+
+ #game-over {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(255, 255, 255, 0.9); /* Semi-transparent */
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ z-index: 1000;
+ }
+
+ #game-over h2 {
+ font-family: 'Playfair Display', Georgia, serif;
+ text-align: center;
+ }
+
+ .restart-button {
+ margin-top:32px;
+ background-color: var(--accent);
+ color: var(--surface);
+ padding: 16px 24px;
+ border: none;
+ text-transform: uppercase;
+ font-size: calc(0.75em + 0.2vw);
+ cursor: pointer;
+ border-radius: 8px;
+ }
+ </style>
+</head>
+<body>
+
+ <header>
+ DESIGNER WALLCOVERINGS
+ </header>
+
+ <div class="container">
+ <div id="wallpaper"></div>
+
+ <div class="style-buttons">
+ <button class="style-button" data-style="damask">Damask</button>
+ <button class="style-button" data-style="toile">Toile</button>
+ <button class="style-button" data-style="ikat">Ikat</button>
+ <button class="style-button" data-style="chinoiserie">Chinoiserie</button>
+ </div>
+
+ <div id="score-container">
+ <div class="scoreboard">Score: <span id="score">0</span></div>
+ <div class="scoreboard">Streak: <span id="streak">0</span></div>
+ <div class="scoreboard">Round: <span id="round">1</span> / 10</div>
+ </div>
+
+ <div id="game-over" style="display: none;">
+ <h2>Game Over!</h2>
+ <p>Your Final Score: <span id="final-score">0</span></p>
+ <button class="restart-button" onclick="restartGame()">Restart Game</button>
+ </div>
+ </div>
+
+ <script>
+ const wallpaperElement = document.getElementById('wallpaper');
+ const scoreElement = document.getElementById('score');
+ const streakElement = document.getElementById('streak');
+ const roundElement = document.getElementById('round');
+ const gameOverElement = document.getElementById('game-over');
+ const finalScoreElement = document.getElementById('final-score');
+
+ let score = 0;
+ let streak = 0;
+ let round = 1;
+ let bestScore = localStorage.getItem('bestScore') || 0; // Initialize from localStorage
+ const styles = ['damask', 'toile', 'ikat', 'chinoiserie'];
+ let currentStyleIndex = 0;
+
+ const styleButtons = document.querySelectorAll('.style-button');
+ let timer;
+
+
+ function getRandomStyle() {
+ return styles[Math.floor(Math.random() * styles.length)];
+ }
+
+ function setWallpaper(style) {
+ switch (style) {
+ case 'damask':
+ wallpaperElement.style.backgroundImage = `linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.3)), url("data:image/svg+xml,%3Csvg width='200' height='400' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='damask-pattern' width='50' height='50' patternUnits='userSpaceOnUse'%3E%3Crect x='0' y='0' width='50' height='50' fill='%23f5f2ea'/%3E%3Crect x='25' y='0' width='25' height='50' fill='%23c9a961'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='200' height='400' fill='url(%23damask-pattern)'/%3E%3C/svg%3E")`;
+ break;
+ case 'toile':
+ wallpaperElement.style.backgroundImage = `linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.3)), url("data:image/svg+xml,%3Csvg width='200' height='400' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='toile-pattern' width='50' height='50' patternUnits='userSpaceOnUse'%3E%3Crect x='0' y='0' width='50' height='50' fill='%23f5f2ea'/%3E%3Cpath d='M25 0 L40 10 C45 15, 45 25, 40 30 L25 40 C20 35, 20 25, 25 30 Z' fill='%23c9a961'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='200' height='400' fill='url(%23toile-pattern)'/%3E%3C/svg%3E")`;
+ break;
+ case 'ikat':
+ wallpaperElement.style.backgroundImage = `linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.3)), url("data:image/svg+xml,%3Csvg width='200' height='400' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='ikat-pattern' width='50' height='50' patternUnits='userSpaceOnUse'%3E%3Crect x='0' y='0' width='50' height='50' fill='%23f5f2ea'/%3E%3Cpath d='M25 0 L40 10 C45 15, 45 25, 40 30 L25 40 C20 35, 20 25, 25 30 Z' fill='%23c9a961'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='200' height='400' fill='url(%23ikat-pattern)'/%3E%3C/svg%3E")`;
+
+ break;
+ case 'chinoiserie':
+ wallpaperElement.style.backgroundImage = `linear-gradient(45deg, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.3)), url("data:image/svg+xml,%3Csvg width='200' height='400' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='chinoiserie-pattern' width='50' height='50' patternUnits='userSpaceOnUse'%3E%3Crect x='0' y='0' width='50' height='50' fill='%23f5f2ea'/%3E%3Cpath d='M25 0 L40 10 C45 15, 45 25, 40 30 L25 40 C20 35, 20 25, 25 30 Z' fill='%23c9a961'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='200' height='400' fill='url(%23chinoiserie-pattern)'/%3E%3C/svg%3E")`;
+ break;
+
+ }
+ }
+
+ function checkAnswer(selectedStyle) {
+ if (selectedStyle === getRandomStyle()) {
+ score++;
+ streak++;
+ updateScoreboard();
+ setFeedback('correct');
+ setTimeout(() => setFeedback('hidden'), 500);
+ nextRound();
+ } else {
+ streak = 0;
+ updateScoreboard();
+ setFeedback('incorrect');
+ setTimeout(() => setFeedback('hidden'), 750);
+ gameOver();
+ }
+ }
+
+ function updateScoreboard() {
+ scoreElement.textContent = score;
+ streakElement.textContent = streak;
+ roundElement.textContent = `${round} / 10`;
+
+ if (score > bestScore) {
+ bestScore = score;
+ localStorage.setItem('bestScore', bestScore);
+ }
+ }
+
+
+ function setFeedback(state) {
+ const feedbackContainer = document.createElement('div');
+ feedbackContainer.id = 'feedback';
+ feedbackContainer.textContent = state === 'correct' ? 'Correct!' : 'Incorrect.';
+ feedbackContainer.style.position = 'absolute';
+ feedbackContainer.style.top = '50%';
+ feedbackContainer.style.left = '50%';
+ feedbackContainer.style.transform = 'translate(-50%, -50%)';
+ feedbackContainer.style.padding = '16px';
+ feedbackContainer.style.borderRadius = '8px';
+ feedbackContainer.style.backgroundColor = state === 'correct' ? 'rgba(73, 204, 129, 0.8)' : 'rgba(235, 68, 68, 0.8)';
+ feedbackContainer.style.color = '#fff';
+ document.body.appendChild(feedbackContainer);
+
+ setTimeout(() => {
+ feedbackContainer.remove();
+ }, 1000);
+ }
+
+
+ function nextRound() {
+ round++;
+ if (round <= 10) {
+ currentStyleIndex = (currentStyleIndex + 1) % styles.length;
+ setWallpaper(getRandomStyle());
+ updateScoreboard();
+
+ // Reset button text to original values after feedback disappears
+ for (let i = 0; i < styleButtons.length; i++) {
+ styleButtons[i].textContent = styleButtons[i].dataset.style.charAt(0).toUpperCase() + styleButtons[i].dataset.style.slice(1);
+ }
+
+ } else {
+ gameOver();
+ }
+ }
+
+
+ function gameOver() {
+ finalScoreElement.textContent = score;
+ gameOverElement.style.display = 'flex';
+ }
+
+
+
+ function restartGame() {
+ score = 0;
+ streak = 0;
+ round = 1;
+ currentStyleIndex = 0;
+ setWallpaper(getRandomStyle());
+ updateScoreboard();
+
+ gameOverElement.style.display = 'none';
+ }
+
+
+ function startGame() {
+ setWallpaper(getRandomStyle());
+ updateScoreboard();
+ }
+
+
+ // Event listeners for style buttons
+ for (let i = 0; i < styleButtons.length; i++) {
+ styleButtons[i].addEventListener('click', function() {
+ checkAnswer(this.dataset.style);
+ });
+ }
+
+ window.onload = () => {
+ startGame();
+ };
+
+
+
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/gemma3-12b.png b/data/artifacts/bf0bdeb4c423/gemma3-12b.png
new file mode 100644
index 0000000..eb0c4c3
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/gemma3-12b.png differ
diff --git a/data/artifacts/bf0bdeb4c423/gpt.html b/data/artifacts/bf0bdeb4c423/gpt.html
new file mode 100644
index 0000000..2b3813f
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/gpt.html
@@ -0,0 +1,1219 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8" />
+<title>Designer Wallcoverings — Guess the Design Style</title>
+<style>
+:root {
+ /* Design tokens */
+ --bg: #f5f2ea;
+ --surface: #ffffff;
+ --ink: #151417;
+ --muted: #8a8578;
+ --accent: #c9a961; /* single metallic/jewel accent: soft antique gold */
+ --accent-soft: #e4d5a2;
+ --line: rgba(0, 0, 0, 0.08);
+ --shadow-soft: 0 18px 40px rgba(12, 10, 6, 0.16);
+ --shadow-subtle: 0 10px 30px rgba(12, 10, 6, 0.12);
+ --shadow-hairline: 0 0 0 1px var(--line);
+ --radius-card: 18px;
+ --radius-pill: 999px;
+ --ease-swift: cubic-bezier(.22,.9,.24,1);
+ --ease-pop: cubic-bezier(.34,1.56,.64,1);
+
+ --font-display: "Playfair Display", "Didot", "Bodoni MT", Georgia, serif;
+ --font-body: "Avenir Next", "Century Gothic", Futura, "Segoe UI", sans-serif;
+
+ --fs-caption: 12px;
+ --fs-label: 12px;
+ --fs-body: 16px;
+ --fs-lead: 21px;
+ --fs-h3: 28px;
+ --fs-h2: 38px;
+ --fs-h1: 50px;
+
+ --transition-fast: 160ms var(--ease-swift);
+ --transition-med: 220ms var(--ease-swift);
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+html, body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+}
+
+body {
+ font-family: var(--font-body);
+ background: radial-gradient(circle at top, #faf6ed 0, var(--bg) 55%, #e7dfcf 100%);
+ color: var(--ink);
+ -webkit-font-smoothing: antialiased;
+}
+
+/* Layout */
+
+.app-shell {
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+header.app-header {
+ position: fixed;
+ inset: 0 0 auto 0;
+ z-index: 10;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 16px 32px 14px;
+ background: linear-gradient(to bottom, rgba(245,242,234,0.96), rgba(245,242,234,0.92), rgba(245,242,234,0.9));
+ backdrop-filter: blur(10px);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+}
+
+/* Wordmark lockup */
+
+.brand-lockup {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.brand-wordmark {
+ font-family: var(--font-display);
+ font-size: 18px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ line-height: 1.15;
+ white-space: nowrap;
+}
+
+@media (max-width: 640px) {
+ .brand-wordmark {
+ font-size: 15px;
+ white-space: normal; /* allow graceful wrap without clipping */
+ }
+}
+
+.brand-tagline {
+ font-size: 11px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+/* Header meta */
+
+.header-meta {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+ font-size: var(--fs-caption);
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.header-pill {
+ border-radius: var(--radius-pill);
+ padding: 5px 14px 6px;
+ border: 1px solid rgba(0,0,0,0.08);
+ background: rgba(255,255,255,0.7);
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.7);
+}
+
+.header-metric-label {
+ display: block;
+ font-size: 10px;
+ letter-spacing: 0.18em;
+ margin-bottom: 3px;
+}
+
+.header-metric-value {
+ font-size: 12px;
+ letter-spacing: 0.08em;
+ color: var(--ink);
+}
+
+/* Main */
+
+main {
+ flex: 1;
+ padding: 96px 24px 32px;
+ display: flex;
+ justify-content: center;
+ align-items: stretch;
+}
+
+.game-shell {
+ max-width: 980px;
+ width: 100%;
+ margin: 0 auto;
+ display: grid;
+ grid-template-columns: minmax(0, 3fr) minmax(260px, 2.2fr);
+ gap: 28px;
+ align-items: stretch;
+}
+
+@media (max-width: 900px) {
+ main {
+ padding-top: 92px;
+ }
+ .game-shell {
+ grid-template-columns: minmax(0, 1fr);
+ }
+}
+
+/* Pattern card */
+
+.pattern-card {
+ position: relative;
+ border-radius: 24px;
+ background: radial-gradient(circle at top left, #fdf8ee 0, #f2e8d3 28%, #e2d6c2 100%);
+ box-shadow: var(--shadow-soft);
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+.pattern-inner {
+ padding: 18px 18px 16px;
+ display: flex;
+ flex-direction: column;
+ gap: 14px;
+}
+
+.pattern-meta-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 18px;
+ font-size: var(--fs-caption);
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.badge-soft {
+ padding: 5px 12px 6px;
+ border-radius: var(--radius-pill);
+ border: 1px solid rgba(0,0,0,0.06);
+ background: linear-gradient(to right, rgba(255,255,255,0.8), rgba(255,255,255,0.5));
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.badge-dot {
+ width: 7px;
+ height: 7px;
+ border-radius: 50%;
+ background: radial-gradient(circle at 30% 20%, #fff, var(--accent));
+ box-shadow: 0 0 0 1px rgba(141, 111, 63, 0.35);
+}
+
+.pattern-round-label {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.pattern-round-label span {
+ font-size: 11px;
+}
+
+.pattern-title {
+ font-family: var(--font-display);
+ font-size: 24px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--ink);
+}
+
+.pattern-subtitle {
+ font-size: 13px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+/* Wallpaper viewport */
+
+.wallpaper-frame {
+ position: relative;
+ flex: 1;
+ margin: 4px;
+ border-radius: 18px;
+ background: radial-gradient(circle at top, rgba(255,255,255,0.95) 0, #f7f1e3 40%, #e3d5c2 100%);
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,0.8), inset 0 0 0 0.5px rgba(0,0,0,0.03);
+ overflow: hidden;
+}
+
+.wallpaper-inset {
+ position: absolute;
+ inset: 18px 18px 16px 18px;
+ border-radius: 16px;
+ background: #fdfaf4;
+ box-shadow: inset 0 0 0 1px rgba(0,0,0,0.04);
+ overflow: hidden;
+}
+
+.wallpaper-motif {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ transition: transform var(--transition-med), filter var(--transition-med), opacity var(--transition-med);
+}
+
+/* Feedback glows */
+
+.wallpaper-motif.correct-state {
+ box-shadow: inset 0 0 0 2px rgba(179, 140, 60, 0.82), 0 0 0 1px rgba(255,255,255,0.7);
+ transform: scale(1.01);
+ filter: saturate(1.03);
+}
+
+.wallpaper-motif.wrong-state {
+ box-shadow: inset 0 0 0 2px rgba(120, 32, 20, 0.7);
+ filter: saturate(0.85) contrast(1.02);
+}
+
+/* Pattern types */
+
+.pattern-base {
+ width: 100%;
+ height: 100%;
+ background-size: cover;
+}
+
+/* Damask: ornate mirrored floral with layered radial masks */
+
+.pattern-damask {
+ background-color: #f7f2e4;
+ background-image:
+ radial-gradient(circle at 20% 20%, rgba(40,26,14,0.13) 0, rgba(40,26,14,0) 52%),
+ radial-gradient(circle at 80% 25%, rgba(40,26,14,0.18) 0, rgba(40,26,14,0) 55%),
+ radial-gradient(circle at 50% 80%, rgba(40,26,14,0.13) 0, rgba(40,26,14,0) 52%),
+ radial-gradient(circle at 30% 50%, rgba(40,26,14,0.18) 0, rgba(40,26,14,0) 55%),
+ repeating-radial-gradient(circle at 50% 0, rgba(0,0,0,0.06) 0 1px, transparent 1px 9px),
+ radial-gradient(circle at 50% 45%, rgba(186,151,90,0.55) 0, rgba(186,151,90,0.15) 32%, rgba(186,151,90,0) 60%);
+ background-blend-mode: soft-light, soft-light, soft-light, soft-light, normal, multiply;
+}
+
+/* Toile: scenic vignettes in monochrome engraving style */
+
+.pattern-toile {
+ background-color: #faf7f0;
+ background-image:
+ radial-gradient(circle at 18% 20%, transparent 0 22px, rgba(0,0,0,0.22) 23px 24px, transparent 25px 70px),
+ radial-gradient(circle at 72% 32%, transparent 0 20px, rgba(0,0,0,0.16) 21px 22px, transparent 23px 60px),
+ radial-gradient(circle at 30% 76%, transparent 0 24px, rgba(0,0,0,0.18) 25px 26px, transparent 27px 72px),
+ repeating-linear-gradient(135deg, rgba(0,0,0,0.06) 0 1px, transparent 1px 4px),
+ repeating-linear-gradient(45deg, transparent 0 8px, rgba(0,0,0,0.04) 9px 10px),
+ radial-gradient(circle at 50% 40%, rgba(0,0,0,0.15) 0, rgba(0,0,0,0) 65%);
+ background-size: 210px 210px;
+ background-blend-mode: multiply, multiply, multiply, normal, soft-light, soft-light;
+ filter: grayscale(1);
+}
+
+/* Ikat: feathered diamond ikat */
+
+.pattern-ikat {
+ background-color: #f1e3d0;
+ background-image:
+ repeating-linear-gradient(135deg, rgba(0,0,0,0.16) 0 16px, rgba(0,0,0,0.0) 16px 32px),
+ repeating-linear-gradient(45deg, rgba(0,0,0,0.2) 0 12px, rgba(0,0,0,0) 12px 26px),
+ radial-gradient(circle at 0 0, rgba(241,227,208,1) 0, rgba(241,227,208,0) 55%),
+ radial-gradient(circle at 100% 100%, rgba(221,192,150,1) 0, rgba(221,192,150,0) 45%);
+ background-blend-mode: multiply, screen, normal, multiply;
+ background-size: 120px 120px;
+ filter: contrast(1.15) saturate(0.9);
+}
+
+/* Chinoiserie: vertical panels with organic branches and blossoms */
+
+.pattern-chinoiserie {
+ background-color: #faf6ec;
+ background-image:
+ linear-gradient(to right, rgba(0,0,0,0.1) 0 1px, transparent 1px 25%),
+ radial-gradient(circle at 10% 30%, rgba(0,0,0,0.12) 0 10px, transparent 10px 40px),
+ radial-gradient(circle at 22% 52%, rgba(0,0,0,0.14) 0 9px, transparent 9px 40px),
+ radial-gradient(circle at 68% 28%, rgba(0,0,0,0.14) 0 9px, transparent 9px 40px),
+ radial-gradient(circle at 82% 60%, rgba(0,0,0,0.12) 0 9px, transparent 9px 40px),
+ radial-gradient(circle at 44% 80%, rgba(0,0,0,0.15) 0 10px, transparent 10px 50px),
+ linear-gradient(120deg, rgba(0,0,0,0.12) 0 0.5px, transparent 0.5px 12px),
+ linear-gradient(60deg, rgba(0,0,0,0.11) 0 0.5px, transparent 0.5px 14px);
+ background-size: 140px 100%, 220px 220px, 220px 220px, 260px 260px, 260px 260px, 260px 260px, 30px 40px, 32px 40px;
+ background-blend-mode: normal, multiply, multiply, multiply, multiply, multiply, normal, normal;
+ opacity: 0.96;
+}
+
+/* Geometric: crisp isometric lattice */
+
+.pattern-geometric {
+ background-color: #f5efe2;
+ background-image:
+ linear-gradient(135deg, rgba(0,0,0,0.22) 1px, transparent 1px),
+ linear-gradient(225deg, rgba(0,0,0,0.22) 1px, transparent 1px),
+ linear-gradient(45deg, rgba(201,169,97,0.9) 2px, transparent 2px),
+ linear-gradient(to bottom, rgba(201,169,97,0.8) 0 2px, transparent 2px 24px);
+ background-size: 28px 28px, 28px 28px, 56px 56px, 100% 24px;
+ background-position: 0 0, 0 0, 0 0, 0 0;
+ background-blend-mode: multiply;
+}
+
+/* Grasscloth: subtle horizontal fibers */
+
+.pattern-grasscloth {
+ background-color: #f3ecde;
+ background-image:
+ repeating-linear-gradient(to bottom, rgba(0,0,0,0.16) 0 1px, transparent 1px 3px),
+ repeating-linear-gradient(to bottom, rgba(255,255,255,0.6) 0 1px, transparent 1px 4px),
+ repeating-linear-gradient(90deg, rgba(0,0,0,0.06) 0 0.5px, transparent 0.5px 6px),
+ radial-gradient(circle at 0 0, rgba(243,236,222,1) 0, rgba(243,236,222,0) 55%),
+ radial-gradient(circle at 100% 100%, rgba(218,198,160,1) 0, rgba(218,198,160,0) 45%);
+ background-blend-mode: multiply, screen, normal, normal, multiply;
+ filter: saturate(0.9);
+}
+
+/* Side panel */
+
+.side-panel {
+ align-self: stretch;
+ border-radius: var(--radius-card);
+ background: rgba(255,255,255,0.96);
+ box-shadow: var(--shadow-subtle);
+ padding: 18px 20px 18px;
+ display: flex;
+ flex-direction: column;
+ gap: 18px;
+}
+
+.side-heading {
+ font-family: var(--font-display);
+ font-size: 22px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--ink);
+}
+
+.side-subtitle {
+ font-size: 13px;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.stats-row {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.stat-chip {
+ min-width: 110px;
+ padding: 8px 11px 9px;
+ border-radius: 14px;
+ border: 1px solid rgba(0,0,0,0.08);
+ background: radial-gradient(circle at top left, #fdfaf4 0, #f3ede0 100%);
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.7);
+}
+
+.stat-label {
+ font-size: 10px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 4px;
+}
+
+.stat-value {
+ font-size: 14px;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+}
+
+/* Choices */
+
+.choices-group {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+}
+
+.choices-label-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 8px;
+}
+
+.choices-label {
+ font-size: 11px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.round-progress {
+ font-size: 11px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.button-grid {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 10px;
+}
+
+button.choice-btn {
+ position: relative;
+ padding: 11px 12px 13px;
+ border-radius: 999px;
+ border: 1px solid rgba(0,0,0,0.12);
+ background: linear-gradient(to bottom, #fdfbf6, #f1e7d5);
+ color: var(--ink);
+ font-family: var(--font-body);
+ font-size: 12px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.8);
+ transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
+}
+
+button.choice-btn::before {
+ content: "";
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+ background: radial-gradient(circle at 30% 20%, #fff, var(--accent));
+ box-shadow: 0 0 0 1px rgba(141, 111, 63, 0.4);
+ opacity: 0.85;
+}
+
+button.choice-btn:hover:not(:disabled) {
+ transform: translateY(-1px);
+ background: linear-gradient(to bottom, #fffdf8, #f4ead7);
+ box-shadow: 0 10px 24px rgba(15, 10, 5, 0.16);
+}
+
+button.choice-btn:active:not(:disabled) {
+ transform: translateY(0);
+ box-shadow: 0 6px 12px rgba(15,10,5,0.18);
+}
+
+button.choice-btn.correct {
+ border-color: rgba(141,111,63,0.9);
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.9), 0 0 0 2px rgba(141,111,63,0.9);
+ background: linear-gradient(to bottom, #fffdf6, #f2e4c5);
+}
+
+button.choice-btn.wrong {
+ border-color: rgba(120,32,20,0.9);
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.9), 0 0 0 2px rgba(120,32,20,0.7);
+ background: linear-gradient(to bottom, #fbf4f2, #f0d0c5);
+}
+
+button.choice-btn:disabled {
+ cursor: default;
+ opacity: 0.92;
+}
+
+/* Timer bar */
+
+.timer-shell {
+ margin-top: 2px;
+}
+
+.timer-track {
+ position: relative;
+ width: 100%;
+ height: 5px;
+ border-radius: 999px;
+ background: rgba(21,20,23,0.06);
+ overflow: hidden;
+}
+
+.timer-fill {
+ position: absolute;
+ inset: 0;
+ width: 100%;
+ transform-origin: left center;
+ background: linear-gradient(90deg, var(--accent), #f2d396);
+ transition: transform 100ms linear;
+}
+
+/* Helper row */
+
+.helper-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 12px;
+ margin-top: 8px;
+}
+
+.helper-text {
+ font-size: 12px;
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+button.secondary {
+ padding: 7px 14px 8px;
+ border-radius: 999px;
+ border: 1px solid rgba(0,0,0,0.09);
+ background: rgba(255,255,255,0.7);
+ font-family: var(--font-body);
+ font-size: 11px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ cursor: pointer;
+ color: var(--ink);
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ box-shadow: 0 0 0 1px rgba(255,255,255,0.8);
+ transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast);
+}
+
+button.secondary::before {
+ content: "";
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ border: 1px solid rgba(0,0,0,0.2);
+ box-shadow: inset 0 0 0 1px rgba(255,255,255,0.7);
+}
+
+button.secondary:hover {
+ transform: translateY(-1px);
+ background: rgba(255,255,255,0.95);
+ box-shadow: 0 10px 24px rgba(15,10,5,0.16);
+}
+
+button.secondary:active {
+ transform: translateY(0);
+ box-shadow: 0 6px 14px rgba(15,10,5,0.2);
+}
+
+/* Feedback text */
+
+.feedback-line {
+ min-height: 18px;
+ font-size: 12px;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.feedback-line span {
+ transition: color var(--transition-fast), transform var(--transition-fast);
+}
+
+.feedback-line.correct span {
+ color: var(--accent);
+ transform: translateY(-1px);
+}
+
+.feedback-line.wrong span {
+ color: #802014;
+}
+
+/* Overlay */
+
+.game-overlay {
+ position: fixed;
+ inset: 0;
+ background: radial-gradient(circle at top, rgba(245,242,234,0.95), rgba(17,13,8,0.88));
+ display: none;
+ align-items: center;
+ justify-content: center;
+ z-index: 20;
+}
+
+.game-overlay.visible {
+ display: flex;
+}
+
+.overlay-card {
+ max-width: 420px;
+ width: 90%;
+ border-radius: 24px;
+ background: radial-gradient(circle at top left, #fdfaf4 0, #f1e7d5 50%, #e1d2b8 100%);
+ box-shadow: 0 22px 60px rgba(3,2,0,0.6);
+ padding: 24px 26px 22px;
+ text-align: left;
+ position: relative;
+}
+
+.overlay-knot {
+ position: absolute;
+ top: 18px;
+ right: 22px;
+ width: 26px;
+ height: 26px;
+ border-radius: 50%;
+ background:
+ radial-gradient(circle at 30% 20%, #fff, #f8e9c7);
+ box-shadow: 0 0 0 2px rgba(141,111,63,0.5), 0 0 0 5px rgba(255,255,255,0.6);
+}
+
+.overlay-title {
+ font-family: var(--font-display);
+ font-size: 26px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ margin-bottom: 8px;
+ color: var(--ink);
+}
+
+.overlay-subtitle {
+ font-size: 13px;
+ letter-spacing: 0.12em;
+ text-transform: uppercase;
+ margin-bottom: 16px;
+ color: var(--muted);
+}
+
+.overlay-stats {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-bottom: 18px;
+}
+
+.overlay-stat {
+ flex: 1 1 130px;
+ border-radius: 14px;
+ border: 1px solid rgba(0,0,0,0.08);
+ background: linear-gradient(to bottom, rgba(255,255,255,0.9), rgba(244,230,205,0.9));
+ padding: 9px 11px 10px;
+}
+
+.overlay-stat-label {
+ font-size: 10px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 4px;
+}
+
+.overlay-stat-value {
+ font-size: 14px;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+}
+
+.overlay-actions {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-top: 4px;
+}
+
+button.primary {
+ flex: 1 1 auto;
+ padding: 10px 18px 11px;
+ border-radius: 999px;
+ border: 1px solid rgba(0,0,0,0.16);
+ background: radial-gradient(circle at top left, #fffdf7 0, #f1e7d5 45%, #e0cfac 100%);
+ color: var(--ink);
+ font-family: var(--font-body);
+ font-size: 12px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+ box-shadow: 0 12px 26px rgba(15,10,5,0.35), 0 0 0 1px rgba(255,255,255,0.8);
+ transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
+}
+
+button.primary:hover {
+ transform: translateY(-1px);
+ box-shadow: 0 18px 40px rgba(15,10,5,0.5);
+}
+
+button.primary:active {
+ transform: translateY(0);
+ box-shadow: 0 10px 22px rgba(15,10,5,0.5);
+}
+
+/* Accessibility */
+
+.visually-hidden {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ border: 0;
+ clip: rect(0,0,0,0);
+}
+</style>
+</head>
+<body>
+<div class="app-shell">
+ <header class="app-header">
+ <div class="brand-lockup">
+ <div class="brand-wordmark">DESIGNER WALLCOVERINGS</div>
+ <div class="brand-tagline">Pattern recognition study</div>
+ </div>
+ <div class="header-meta">
+ <div class="header-pill">
+ <div class="header-metric-label">Score</div>
+ <div class="header-metric-value" id="scoreHeader">0</div>
+ </div>
+ <div class="header-pill">
+ <div class="header-metric-label">Streak</div>
+ <div class="header-metric-value" id="streakHeader">0</div>
+ </div>
+ <div class="header-pill">
+ <div class="header-metric-label">Best</div>
+ <div class="header-metric-value" id="bestHeader">0</div>
+ </div>
+ </div>
+ </header>
+
+ <main>
+ <div class="game-shell">
+ <section class="pattern-card" aria-label="Wallpaper motif">
+ <div class="pattern-inner">
+ <div class="pattern-meta-row">
+ <div class="pattern-round-label badge-soft">
+ <span class="badge-dot" aria-hidden="true"></span>
+ <span id="roundLabel">Round 1 of 10</span>
+ </div>
+ <div class="pattern-subtitle" id="styleHint">Tap the style that matches this motif.</div>
+ </div>
+ <div class="pattern-title">Guess the Design Style</div>
+ </div>
+ <div class="wallpaper-frame">
+ <div class="wallpaper-inset">
+ <div class="wallpaper-motif pattern-base pattern-damask" id="patternMotif"></div>
+ </div>
+ </div>
+ </section>
+
+ <aside class="side-panel" aria-label="Controls and status">
+ <div>
+ <div class="side-heading">Style intuition</div>
+ <div class="side-subtitle">Ten quick rounds</div>
+ </div>
+
+ <div class="stats-row">
+ <div class="stat-chip">
+ <div class="stat-label">Score</div>
+ <div class="stat-value" id="scoreMain">0</div>
+ </div>
+ <div class="stat-chip">
+ <div class="stat-label">Current streak</div>
+ <div class="stat-value" id="streakMain">0</div>
+ </div>
+ <div class="stat-chip">
+ <div class="stat-label">Best score</div>
+ <div class="stat-value" id="bestMain">0</div>
+ </div>
+ </div>
+
+ <div class="choices-group">
+ <div class="choices-label-row">
+ <div class="choices-label">Select the wallpaper style</div>
+ <div class="round-progress" id="roundProgress">1 / 10</div>
+ </div>
+ <div class="button-grid" id="choicesGrid">
+ <!-- buttons inserted by JS -->
+ </div>
+ </div>
+
+ <div class="timer-shell">
+ <div class="choices-label">Time remaining</div>
+ <div class="timer-track" aria-hidden="true">
+ <div class="timer-fill" id="timerFill"></div>
+ </div>
+ </div>
+
+ <div class="helper-row">
+ <div class="helper-text" id="feedbackLine"> </div>
+ <button type="button" class="secondary" id="restartButton">
+ Restart set
+ </button>
+ </div>
+ </aside>
+ </div>
+ </main>
+
+ <div class="game-overlay" id="overlay" aria-modal="true" role="dialog">
+ <div class="overlay-card">
+ <div class="overlay-knot" aria-hidden="true"></div>
+ <div class="overlay-title" id="overlayTitle">Set complete</div>
+ <div class="overlay-subtitle" id="overlaySubtitle">Ten motifs, one trained eye</div>
+ <div class="overlay-stats">
+ <div class="overlay-stat">
+ <div class="overlay-stat-label">Score this set</div>
+ <div class="overlay-stat-value" id="overlayScore">0</div>
+ </div>
+ <div class="overlay-stat">
+ <div class="overlay-stat-label">Longest streak</div>
+ <div class="overlay-stat-value" id="overlayStreak">0</div>
+ </div>
+ <div class="overlay-stat">
+ <div class="overlay-stat-label">Best overall</div>
+ <div class="overlay-stat-value" id="overlayBest">0</div>
+ </div>
+ </div>
+ <div class="overlay-actions">
+ <button type="button" class="primary" id="playAgainButton">
+ Play another set
+ </button>
+ <button type="button" class="secondary" id="closeOverlayButton">
+ Return to board
+ </button>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+(function () {
+ const STYLES = [
+ { key: 'Damask', className: 'pattern-damask' },
+ { key: 'Toile', className: 'pattern-toile' },
+ { key: 'Ikat', className: 'pattern-ikat' },
+ { key: 'Chinoiserie', className: 'pattern-chinoiserie' },
+ { key: 'Geometric', className: 'pattern-geometric' },
+ { key: 'Grasscloth', className: 'pattern-grasscloth' }
+ ];
+
+ const TOTAL_ROUNDS = 10;
+ const ROUND_TIME_MS = 12000;
+
+ const motifEl = document.getElementById('patternMotif');
+ const scoreHeaderEl = document.getElementById('scoreHeader');
+ const streakHeaderEl = document.getElementById('streakHeader');
+ const bestHeaderEl = document.getElementById('bestHeader');
+ const scoreMainEl = document.getElementById('scoreMain');
+ const streakMainEl = document.getElementById('streakMain');
+ const bestMainEl = document.getElementById('bestMain');
+ const roundLabelEl = document.getElementById('roundLabel');
+ const roundProgressEl = document.getElementById('roundProgress');
+ const styleHintEl = document.getElementById('styleHint');
+ const choicesGridEl = document.getElementById('choicesGrid');
+ const timerFillEl = document.getElementById('timerFill');
+ const feedbackLineEl = document.getElementById('feedbackLine');
+ const restartButtonEl = document.getElementById('restartButton');
+ const overlayEl = document.getElementById('overlay');
+ const overlayTitleEl = document.getElementById('overlayTitle');
+ const overlaySubtitleEl = document.getElementById('overlaySubtitle');
+ const overlayScoreEl = document.getElementById('overlayScore');
+ const overlayStreakEl = document.getElementById('overlayStreak');
+ const overlayBestEl = document.getElementById('overlayBest');
+ const playAgainButtonEl = document.getElementById('playAgainButton');
+ const closeOverlayButtonEl = document.getElementById('closeOverlayButton');
+
+ let currentRound = 0;
+ let score = 0;
+ let streak = 0;
+ let bestScore = 0;
+ let longestStreakThisSet = 0;
+ let currentStyle = null;
+ let timerStart = null;
+ let timerId = null;
+ let acceptingInput = true;
+
+ function loadBestScore() {
+ try {
+ const stored = localStorage.getItem('dw_best_score');
+ if (stored != null) {
+ bestScore = parseInt(stored, 10) || 0;
+ } else {
+ bestScore = 0;
+ }
+ } catch (e) {
+ bestScore = 0;
+ }
+ bestHeaderEl.textContent = bestScore;
+ bestMainEl.textContent = bestScore;
+ }
+
+ function saveBestScore() {
+ try {
+ localStorage.setItem('dw_best_score', String(bestScore));
+ } catch (e) {
+ // ignore
+ }
+ }
+
+ function updateScoreDisplays() {
+ scoreHeaderEl.textContent = score;
+ scoreMainEl.textContent = score;
+ streakHeaderEl.textContent = streak;
+ streakMainEl.textContent = streak;
+ bestHeaderEl.textContent = bestScore;
+ bestMainEl.textContent = bestScore;
+ }
+
+ function clearMotifClasses() {
+ motifEl.className = 'wallpaper-motif pattern-base';
+ }
+
+ function shuffle(array) {
+ const arr = array.slice();
+ for (let i = arr.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [arr[i], arr[j]] = [arr[j], arr[i]];
+ }
+ return arr;
+ }
+
+ function sampleChoices() {
+ const all = shuffle(STYLES);
+ const correct = all[0];
+ const others = all.slice(1).sort(() => Math.random() - 0.5).slice(0, 3);
+ const options = shuffle([correct].concat(others));
+ return { correct, options };
+ }
+
+ function setTimerProgress(p) {
+ const clamped = Math.max(0, Math.min(1, p));
+ timerFillEl.style.transform = 'scaleX(' + clamped + ')';
+ }
+
+ function clearTimer() {
+ if (timerId) {
+ cancelAnimationFrame(timerId);
+ timerId = null;
+ }
+ }
+
+ function startTimer() {
+ clearTimer();
+ timerStart = performance.now();
+ setTimerProgress(1);
+
+ const step = (now) => {
+ const elapsed = now - timerStart;
+ const remaining = Math.max(0, ROUND_TIME_MS - elapsed);
+ const progress = remaining / ROUND_TIME_MS;
+ setTimerProgress(progress);
+
+ if (remaining <= 0) {
+ timerId = null;
+ handleTimeout();
+ } else {
+ timerId = requestAnimationFrame(step);
+ }
+ };
+ timerId = requestAnimationFrame(step);
+ }
+
+ function setFeedback(state, detail) {
+ feedbackLineEl.classList.remove('correct', 'wrong');
+ if (!state) {
+ feedbackLineEl.innerHTML = ' ';
+ return;
+ }
+ const span = document.createElement('span');
+ span.textContent = detail;
+ feedbackLineEl.textContent = '';
+ feedbackLineEl.appendChild(span);
+ feedbackLineEl.classList.add(state);
+ }
+
+ function startRound() {
+ currentRound += 1;
+ if (currentRound > TOTAL_ROUNDS) {
+ endGame();
+ return;
+ }
+
+ acceptingInput = true;
+ setFeedback(null, '');
+ clearMotifClasses();
+
+ const { correct, options } = sampleChoices();
+ currentStyle = correct;
+
+ motifEl.classList.add(correct.className);
+ styleHintEl.textContent = 'Is this ' + correct.key + ', Toile, Ikat, Chinoiserie, Geometric or Grasscloth?';
+
+ roundLabelEl.textContent = 'Round ' + currentRound + ' of ' + TOTAL_ROUNDS;
+ roundProgressEl.textContent = currentRound + ' / ' + TOTAL_ROUNDS;
+
+ while (choicesGridEl.firstChild) {
+ choicesGridEl.removeChild(choicesGridEl.firstChild);
+ }
+
+ options.forEach((opt) => {
+ const btn = document.createElement('button');
+ btn.type = 'button';
+ btn.className = 'choice-btn';
+ btn.textContent = opt.key;
+ btn.dataset.styleKey = opt.key;
+ btn.addEventListener('click', () => handleChoice(opt.key, btn));
+ choicesGridEl.appendChild(btn);
+ });
+
+ startTimer();
+ }
+
+ function handleChoice(choiceKey, btnEl) {
+ if (!acceptingInput) return;
+ acceptingInput = false;
+ clearTimer();
+
+ const correctKey = currentStyle.key;
+ const choiceButtons = Array.from(choicesGridEl.querySelectorAll('button'));
+
+ if (choiceKey === correctKey) {
+ score += 10;
+ streak += 1;
+ longestStreakThisSet = Math.max(longestStreakThisSet, streak);
+ btnEl.classList.add('correct');
+ motifEl.classList.add('correct-state');
+ setFeedback('correct', 'Correct — ' + correctKey + ' motif.');
+ } else {
+ streak = 0;
+ btnEl.classList.add('wrong');
+ motifEl.classList.add('wrong-state');
+ setFeedback('wrong', 'That was ' + correctKey + '.');
+ const correctBtn = choiceButtons.find((b) => b.dataset.styleKey === correctKey);
+ if (correctBtn) correctBtn.classList.add('correct');
+ }
+
+ if (score > bestScore) {
+ bestScore = score;
+ saveBestScore();
+ }
+ updateScoreDisplays();
+
+ choiceButtons.forEach((b) => (b.disabled = true));
+
+ setTimeout(() => {
+ motifEl.classList.remove('correct-state', 'wrong-state');
+ choiceButtons.forEach((b) => {
+ b.classList.remove('correct', 'wrong');
+ });
+ if (currentRound >= TOTAL_ROUNDS) {
+ endGame();
+ } else {
+ startRound();
+ }
+ }, 900);
+ }
+
+ function handleTimeout() {
+ if (!acceptingInput) return;
+ acceptingInput = false;
+ const correctKey = currentStyle ? currentStyle.key : '';
+ streak = 0;
+ setFeedback('wrong', 'Out of time — it was ' + correctKey + '.');
+ motifEl.classList.add('wrong-state');
+ const choiceButtons = Array.from(choicesGridEl.querySelectorAll('button'));
+ choiceButtons.forEach((b) => {
+ b.disabled = true;
+ if (b.dataset.styleKey === correctKey) {
+ b.classList.add('correct');
+ }
+ });
+ updateScoreDisplays();
+
+ setTimeout(() => {
+ motifEl.classList.remove('wrong-state');
+ choiceButtons.forEach((b) => b.classList.remove('correct', 'wrong'));
+ if (currentRound >= TOTAL_ROUNDS) {
+ endGame();
+ } else {
+ startRound();
+ }
+ }, 900);
+ }
+
+ function resetGame() {
+ clearTimer();
+ currentRound = 0;
+ score = 0;
+ streak = 0;
+ longestStreakThisSet = 0;
+ updateScoreDisplays();
+ setFeedback(null, '');
+ setTimerProgress(1);
+ startRound();
+ }
+
+ function endGame() {
+ clearTimer();
+ acceptingInput = false;
+ setTimerProgress(0);
+ setFeedback(null, '');
+
+ overlayScoreEl.textContent = score;
+ overlayStreakEl.textContent = longestStreakThisSet;
+ overlayBestEl.textContent = bestScore;
+
+ if (score >= 80) {
+ overlayTitleEl.textContent = 'Impeccable eye';
+ overlaySubtitleEl.textContent = 'You placed these patterns like a seasoned designer.';
+ } else if (score >= 50) {
+ overlayTitleEl.textContent = 'Refined instincts';
+ overlaySubtitleEl.textContent = 'A strong grasp of wallpaper archetypes.';
+ } else {
+ overlayTitleEl.textContent = 'Emerging taste';
+ overlaySubtitleEl.textContent = 'Spend another set with the collection.';
+ }
+
+ overlayEl.classList.add('visible');
+ }
+
+ restartButtonEl.addEventListener('click', () => {
+ overlayEl.classList.remove('visible');
+ resetGame();
+ });
+
+ playAgainButtonEl.addEventListener('click', () => {
+ overlayEl.classList.remove('visible');
+ resetGame();
+ });
+
+ closeOverlayButtonEl.addEventListener('click', () => {
+ overlayEl.classList.remove('visible');
+ });
+
+ overlayEl.addEventListener('click', (e) => {
+ if (e.target === overlayEl) {
+ overlayEl.classList.remove('visible');
+ }
+ });
+
+ document.addEventListener('visibilitychange', () => {
+ if (document.hidden) {
+ clearTimer();
+ } else if (currentRound > 0 && currentRound <= TOTAL_ROUNDS && acceptingInput) {
+ startTimer();
+ }
+ });
+
+ loadBestScore();
+ resetGame();
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/gpt.png b/data/artifacts/bf0bdeb4c423/gpt.png
new file mode 100644
index 0000000..887c65b
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/gpt.png differ
diff --git a/data/artifacts/bf0bdeb4c423/grok.html b/data/artifacts/bf0bdeb4c423/grok.html
new file mode 100644
index 0000000..94a8052
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/grok.html
@@ -0,0 +1,1336 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Guess the Design Style — Designer Wallcoverings</title>
+<style>
+:root {
+ --bg: #f7f3eb;
+ --bg-deep: #efe8dc;
+ --surface: #fffcf6;
+ --ink: #14120f;
+ --ink-soft: #3a3530;
+ --muted: #8a8478;
+ --accent: #9a7b2f;
+ --accent-bright: #c4a35a;
+ --accent-deep: #6e5620;
+ --line: rgba(20, 18, 15, 0.12);
+ --line-strong: rgba(20, 18, 15, 0.22);
+ --shadow: 0 12px 40px rgba(20, 18, 15, 0.08), 0 2px 8px rgba(20, 18, 15, 0.04);
+ --shadow-lg: 0 24px 64px rgba(20, 18, 15, 0.14), 0 4px 16px rgba(20, 18, 15, 0.06);
+ --correct: #2f5d3a;
+ --wrong: #8b2e2e;
+ --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', 'EB Garamond', Georgia, 'Times New Roman', serif;
+ --sans: 'Avenir Next', 'Century Gothic', 'Helvetica Neue', Futura, sans-serif;
+ --header-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.5;
+ -webkit-font-smoothing: antialiased;
+ overflow-x: hidden;
+}
+
+/* —— Header / wordmark —— */
+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: 15px;
+ font-weight: 400;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ line-height: 1.25;
+ max-width: 280px;
+ white-space: normal;
+}
+
+.header-meta {
+ display: flex;
+ align-items: center;
+ gap: 22px;
+ font-family: var(--sans);
+ font-size: 10px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.header-meta b {
+ color: var(--ink);
+ font-weight: 600;
+ margin-left: 6px;
+}
+
+.header-meta .sep {
+ width: 1px;
+ height: 14px;
+ background: var(--line-strong);
+}
+
+/* —— Main layout —— */
+main {
+ min-height: 100%;
+ padding: calc(var(--header-h) + 36px) 24px 48px;
+ max-width: 920px;
+ margin: 0 auto;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.eyebrow {
+ font-family: var(--sans);
+ font-size: 11px;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ color: var(--accent);
+ margin-bottom: 10px;
+}
+
+h1.game-title {
+ font-family: var(--serif);
+ font-size: 38px;
+ font-weight: 400;
+ letter-spacing: -0.02em;
+ line-height: 1.1;
+ color: var(--ink);
+ text-align: center;
+ margin-bottom: 8px;
+}
+
+.subhead {
+ font-size: 14px;
+ color: var(--muted);
+ text-align: center;
+ max-width: 42ch;
+ margin-bottom: 32px;
+ line-height: 1.6;
+}
+
+/* —— Stage / wallpaper —— */
+.stage-wrap {
+ width: 100%;
+ max-width: 560px;
+ position: relative;
+}
+
+.stage {
+ width: 100%;
+ aspect-ratio: 5 / 4;
+ background: var(--surface);
+ border: 1px solid var(--line-strong);
+ box-shadow: var(--shadow-lg);
+ position: relative;
+ overflow: hidden;
+ border-radius: var(--radius);
+}
+
+.wallpaper {
+ position: absolute;
+ inset: 0;
+ transition: opacity 0.45s var(--ease), transform 0.55s var(--ease-out);
+}
+
+.wallpaper.exit {
+ opacity: 0;
+ transform: scale(1.03);
+}
+
+.wallpaper.enter {
+ animation: revealIn 0.55s var(--ease-out) both;
+}
+
+@keyframes revealIn {
+ from { opacity: 0; transform: scale(0.97); }
+ to { opacity: 1; transform: scale(1); }
+}
+
+/* Frame bevel */
+.stage::after {
+ content: '';
+ position: absolute;
+ inset: 10px;
+ border: 1px solid rgba(255,255,255,0.18);
+ pointer-events: none;
+ z-index: 2;
+ mix-blend-mode: soft-light;
+}
+
+/* —— Progress / timer —— */
+.hud {
+ width: 100%;
+ max-width: 560px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin: 22px 0 18px;
+ gap: 16px;
+}
+
+.progress-track {
+ flex: 1;
+ height: 2px;
+ background: var(--line);
+ position: relative;
+ overflow: hidden;
+}
+
+.progress-fill {
+ height: 100%;
+ background: var(--accent);
+ width: 0%;
+ transition: width 0.45s var(--ease);
+}
+
+.hud-stat {
+ font-family: var(--sans);
+ font-size: 10px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ color: var(--muted);
+ white-space: nowrap;
+}
+
+.hud-stat em {
+ font-style: normal;
+ color: var(--ink);
+ font-weight: 600;
+ margin-left: 4px;
+}
+
+.timer-bar {
+ width: 100%;
+ max-width: 560px;
+ height: 3px;
+ background: var(--line);
+ margin-bottom: 28px;
+ position: relative;
+ overflow: hidden;
+}
+
+.timer-fill {
+ height: 100%;
+ width: 100%;
+ background: linear-gradient(90deg, var(--accent-deep), var(--accent-bright));
+ transform-origin: left center;
+ transition: background 0.3s var(--ease);
+}
+
+.timer-fill.urgent {
+ background: linear-gradient(90deg, var(--wrong), #c45c5c);
+}
+
+/* —— Choice buttons —— */
+.choices {
+ width: 100%;
+ max-width: 560px;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 10px;
+}
+
+.choice {
+ appearance: none;
+ border: 1px solid var(--line-strong);
+ background: var(--surface);
+ color: var(--ink);
+ font-family: var(--sans);
+ font-size: 11px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ padding: 18px 14px;
+ cursor: pointer;
+ transition: border-color 0.25s var(--ease), background 0.25s var(--ease),
+ color 0.25s var(--ease), transform 0.3s var(--ease-pop),
+ box-shadow 0.25s var(--ease);
+ box-shadow: 0 1px 0 rgba(255,255,255,0.6) inset;
+ position: relative;
+}
+
+.choice:hover:not(:disabled) {
+ border-color: var(--accent);
+ color: var(--accent-deep);
+ transform: translateY(-1px);
+ box-shadow: var(--shadow);
+}
+
+.choice:active:not(:disabled) {
+ transform: translateY(0);
+}
+
+.choice:disabled {
+ cursor: default;
+}
+
+.choice.correct {
+ border-color: var(--correct);
+ background: rgba(47, 93, 58, 0.08);
+ color: var(--correct);
+ animation: pulseCorrect 0.5s var(--ease-pop);
+}
+
+.choice.wrong {
+ border-color: var(--wrong);
+ background: rgba(139, 46, 46, 0.07);
+ color: var(--wrong);
+ animation: shakeWrong 0.45s var(--ease);
+}
+
+.choice.dim {
+ opacity: 0.4;
+}
+
+@keyframes pulseCorrect {
+ 0% { transform: scale(1); }
+ 40% { transform: scale(1.03); }
+ 100% { transform: scale(1); }
+}
+
+@keyframes shakeWrong {
+ 0%, 100% { transform: translateX(0); }
+ 20% { transform: translateX(-6px); }
+ 40% { transform: translateX(5px); }
+ 60% { transform: translateX(-3px); }
+ 80% { transform: translateX(2px); }
+}
+
+/* Feedback flash on stage */
+.feedback-flash {
+ position: absolute;
+ inset: 0;
+ z-index: 5;
+ pointer-events: none;
+ opacity: 0;
+ transition: opacity 0.3s var(--ease);
+}
+
+.feedback-flash.show-correct {
+ opacity: 1;
+ background: linear-gradient(180deg, rgba(47,93,58,0.18), transparent 60%);
+ box-shadow: inset 0 0 0 3px var(--correct);
+}
+
+.feedback-flash.show-wrong {
+ opacity: 1;
+ background: linear-gradient(180deg, rgba(139,46,46,0.16), transparent 60%);
+ box-shadow: inset 0 0 0 3px var(--wrong);
+}
+
+/* —— Overlays —— */
+.overlay {
+ position: fixed;
+ inset: 0;
+ z-index: 200;
+ background: rgba(20, 18, 15, 0.55);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 24px;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity 0.4s var(--ease), visibility 0.4s;
+}
+
+.overlay.open {
+ opacity: 1;
+ visibility: visible;
+}
+
+.panel {
+ background: var(--surface);
+ border: 1px solid var(--line-strong);
+ box-shadow: var(--shadow-lg);
+ max-width: 420px;
+ width: 100%;
+ padding: 48px 40px 40px;
+ text-align: center;
+ transform: translateY(12px) scale(0.98);
+ transition: transform 0.45s var(--ease-out);
+}
+
+.overlay.open .panel {
+ transform: translateY(0) scale(1);
+}
+
+.panel .ornament {
+ width: 40px;
+ height: 1px;
+ background: var(--accent);
+ margin: 0 auto 24px;
+}
+
+.panel h2 {
+ font-family: var(--serif);
+ font-size: 32px;
+ font-weight: 400;
+ letter-spacing: -0.02em;
+ line-height: 1.15;
+ margin-bottom: 12px;
+ color: var(--ink);
+}
+
+.panel p {
+ font-size: 14px;
+ color: var(--muted);
+ line-height: 1.65;
+ margin-bottom: 8px;
+}
+
+.panel .score-big {
+ font-family: var(--serif);
+ font-size: 56px;
+ color: var(--accent-deep);
+ line-height: 1;
+ margin: 20px 0 4px;
+}
+
+.panel .score-label {
+ font-size: 10px;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--muted);
+ margin-bottom: 28px;
+}
+
+.panel .stats-row {
+ display: flex;
+ justify-content: center;
+ gap: 28px;
+ margin-bottom: 32px;
+ padding: 16px 0;
+ border-top: 1px solid var(--line);
+ border-bottom: 1px solid var(--line);
+}
+
+.panel .stat-item span {
+ display: block;
+ font-family: var(--serif);
+ font-size: 24px;
+ color: var(--ink);
+ line-height: 1.2;
+}
+
+.panel .stat-item small {
+ font-size: 10px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--muted);
+}
+
+.btn-primary {
+ appearance: none;
+ border: none;
+ background: var(--ink);
+ color: var(--bg);
+ font-family: var(--sans);
+ font-size: 11px;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ padding: 16px 36px;
+ cursor: pointer;
+ transition: background 0.25s var(--ease), transform 0.25s var(--ease-pop);
+}
+
+.btn-primary:hover {
+ background: var(--accent-deep);
+ transform: translateY(-1px);
+}
+
+.btn-ghost {
+ appearance: none;
+ border: 1px solid var(--line-strong);
+ background: transparent;
+ color: var(--ink-soft);
+ font-family: var(--sans);
+ font-size: 10px;
+ letter-spacing: 0.16em;
+ text-transform: uppercase;
+ padding: 12px 24px;
+ cursor: pointer;
+ margin-top: 12px;
+ transition: border-color 0.25s var(--ease), color 0.25s var(--ease);
+}
+
+.btn-ghost:hover {
+ border-color: var(--accent);
+ color: var(--accent-deep);
+}
+
+/* Best badge */
+.best-badge {
+ display: inline-block;
+ margin-top: 8px;
+ font-size: 10px;
+ letter-spacing: 0.14em;
+ text-transform: uppercase;
+ color: var(--accent);
+ border: 1px solid var(--accent);
+ padding: 4px 10px;
+}
+
+/* ============ WALLPAPER MOTIFS (pure CSS / SVG) ============ */
+
+/* --- DAMASK: ornate diamond medallion --- */
+.motif-damask {
+ background-color: #1a1510;
+ background-image:
+ radial-gradient(ellipse 28% 22% at 50% 50%, rgba(201,169,97,0.35) 0%, transparent 70%),
+ radial-gradient(ellipse 12% 18% at 50% 32%, rgba(201,169,97,0.5) 0%, transparent 60%),
+ radial-gradient(ellipse 18% 10% at 50% 68%, rgba(201,169,97,0.4) 0%, transparent 60%),
+ radial-gradient(circle at 50% 50%, transparent 38%, rgba(201,169,97,0.12) 39%, rgba(201,169,97,0.12) 42%, transparent 43%),
+ radial-gradient(circle at 0% 0%, transparent 30%, rgba(201,169,97,0.08) 31%, transparent 45%),
+ radial-gradient(circle at 100% 0%, transparent 30%, rgba(201,169,97,0.08) 31%, transparent 45%),
+ radial-gradient(circle at 0% 100%, transparent 30%, rgba(201,169,97,0.08) 31%, transparent 45%),
+ radial-gradient(circle at 100% 100%, transparent 30%, rgba(201,169,97,0.08) 31%, transparent 45%);
+ background-size: 120px 160px;
+ background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 60px 0, 0 80px, 60px 80px;
+}
+.motif-damask::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image:
+ radial-gradient(ellipse 8% 12% at 50% 50%, #c9a961 0%, transparent 100%),
+ radial-gradient(circle at 25% 25%, transparent 8%, rgba(201,169,97,0.25) 9%, transparent 12%),
+ radial-gradient(circle at 75% 25%, transparent 8%, rgba(201,169,97,0.25) 9%, transparent 12%),
+ radial-gradient(circle at 25% 75%, transparent 8%, rgba(201,169,97,0.25) 9%, transparent 12%),
+ radial-gradient(circle at 75% 75%, transparent 8%, rgba(201,169,97,0.25) 9%, transparent 12%);
+ background-size: 120px 160px;
+ opacity: 0.9;
+}
+
+/* --- TOILE: pastoral line-drawing feel via SVG pattern --- */
+.motif-toile {
+ background-color: #f0e6d8;
+}
+.motif-toile svg {
+ width: 100%;
+ height: 100%;
+ display: block;
+}
+
+/* --- IKAT: blurred diamond / chevron warp --- */
+.motif-ikat {
+ background-color: #2a1f18;
+ background-image:
+ linear-gradient(90deg,
+ transparent 0%, transparent 8%,
+ #8b3a2a 8%, #8b3a2a 14%,
+ transparent 14%, transparent 22%,
+ #c4a35a 22%, #c4a35a 30%,
+ transparent 30%, transparent 38%,
+ #3d5c4a 38%, #3d5c4a 48%,
+ transparent 48%, transparent 55%,
+ #8b3a2a 55%, #8b3a2a 62%,
+ transparent 62%, transparent 70%,
+ #c4a35a 70%, #c4a35a 78%,
+ transparent 78%, transparent 86%,
+ #3d5c4a 86%, #3d5c4a 94%,
+ transparent 94%),
+ linear-gradient(90deg,
+ #c4a35a 0%, #c4a35a 6%,
+ transparent 6%, transparent 18%,
+ #3d5c4a 18%, #3d5c4a 28%,
+ transparent 28%, transparent 40%,
+ #8b3a2a 40%, #8b3a2a 50%,
+ transparent 50%, transparent 62%,
+ #c4a35a 62%, #c4a35a 72%,
+ transparent 72%, transparent 84%,
+ #3d5c4a 84%, #3d5c4a 92%,
+ transparent 92%);
+ background-size: 80px 48px, 80px 48px;
+ background-position: 0 0, 40px 24px;
+ filter: url(#ikat-blur);
+}
+.motif-ikat::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background:
+ repeating-linear-gradient(0deg,
+ transparent 0px, transparent 22px,
+ rgba(0,0,0,0.15) 22px, rgba(0,0,0,0.15) 24px,
+ transparent 24px, transparent 46px,
+ rgba(255,255,255,0.04) 46px, rgba(255,255,255,0.04) 48px);
+ mix-blend-mode: multiply;
+ pointer-events: none;
+}
+
+/* Ikat without SVG filter fallback — feathered edges via gradients */
+.motif-ikat-css {
+ background-color: #1e1814;
+ position: absolute;
+ inset: 0;
+ overflow: hidden;
+}
+.motif-ikat-css .band {
+ position: absolute;
+ left: -5%;
+ right: -5%;
+ height: 14%;
+ background: linear-gradient(90deg,
+ transparent 0%, #a ag 2%,
+ var(--c1) 4%, var(--c1) 12%,
+ transparent 16%, transparent 22%,
+ var(--c2) 26%, var(--c2) 38%,
+ transparent 42%, transparent 50%,
+ var(--c1) 54%, var(--c1) 66%,
+ transparent 70%, transparent 78%,
+ var(--c2) 82%, var(--c2) 92%,
+ transparent 96%);
+ filter: blur(2.5px);
+ opacity: 0.92;
+}
+
+/* --- CHINOISERIE: branch + bird silhouettes --- */
+.motif-chinoiserie {
+ background:
+ radial-gradient(ellipse 80% 60% at 70% 20%, rgba(232, 210, 160, 0.25) 0%, transparent 50%),
+ linear-gradient(165deg, #1c2a24 0%, #0f1a16 40%, #1a2820 100%);
+}
+.motif-chinoiserie svg {
+ width: 100%;
+ height: 100%;
+ display: block;
+}
+
+/* --- GEOMETRIC: crisp art-deco lattice --- */
+.motif-geometric {
+ background-color: #0e0e12;
+ background-image:
+ linear-gradient(30deg, #c9a961 1px, transparent 1px),
+ linear-gradient(150deg, #c9a961 1px, transparent 1px),
+ linear-gradient(90deg, rgba(201,169,97,0.35) 1px, transparent 1px),
+ linear-gradient(0deg, rgba(201,169,97,0.2) 1px, transparent 1px),
+ repeating-linear-gradient(60deg,
+ transparent 0 18px,
+ rgba(201,169,97,0.08) 18px 19px),
+ radial-gradient(circle at 50% 50%, rgba(201,169,97,0.15) 0 4px, transparent 5px);
+ background-size:
+ 48px 84px,
+ 48px 84px,
+ 24px 24px,
+ 24px 24px,
+ 48px 84px,
+ 48px 84px;
+ background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 24px 42px;
+}
+.motif-geometric::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image:
+ polygon, /* ignored */
+ linear-gradient(30deg, transparent 46%, #c9a961 46%, #c9a961 54%, transparent 54%),
+ linear-gradient(150deg, transparent 46%, #c9a961 46%, #c9a961 54%, transparent 54%);
+ background-size: 96px 168px;
+ background-position: 0 0, 48px 0;
+ opacity: 0.45;
+ pointer-events: none;
+}
+.motif-geometric::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background:
+ radial-gradient(circle at center, transparent 28%, rgba(14,14,18,0.35) 70%);
+ pointer-events: none;
+}
+
+/* --- GRASSCLOTH: fine horizontal fiber weave --- */
+.motif-grasscloth {
+ background-color: #c4b49a;
+ background-image:
+ repeating-linear-gradient(0deg,
+ rgba(90,70,40,0.07) 0px,
+ rgba(90,70,40,0.07) 1px,
+ transparent 1px,
+ transparent 3px),
+ repeating-linear-gradient(90deg,
+ rgba(60,45,25,0.05) 0px,
+ transparent 1px,
+ transparent 4px,
+ rgba(120,100,70,0.06) 5px,
+ transparent 6px,
+ transparent 9px),
+ repeating-linear-gradient(0.5deg,
+ transparent 0px,
+ transparent 7px,
+ rgba(80,60,35,0.04) 7px,
+ rgba(80,60,35,0.04) 8px),
+ linear-gradient(180deg,
+ #d4c4a8 0%,
+ #c4b49a 30%,
+ #b8a68c 55%,
+ #c9b89e 80%,
+ #bbaa8e 100%);
+}
+.motif-grasscloth::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image:
+ repeating-linear-gradient(91deg,
+ rgba(255,255,255,0.04) 0 1px,
+ transparent 1px 11px,
+ rgba(40,30,15,0.05) 11px 12px,
+ transparent 12px 23px);
+ pointer-events: none;
+}
+.motif-grasscloth::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background:
+ radial-gradient(ellipse 120% 80% at 50% 0%, rgba(255,255,255,0.12), transparent 50%),
+ radial-gradient(ellipse 100% 60% at 50% 100%, rgba(60,45,25,0.1), transparent 50%);
+ pointer-events: none;
+}
+
+/* Start screen specifics */
+.start-only { display: block; }
+.playing .start-only { display: none; }
+
+@media (max-width: 560px) {
+ .wordmark { font-size: 12px; max-width: 180px; letter-spacing: 0.14em; }
+ header.site-header { padding: 0 16px; height: 64px; }
+ :root { --header-h: 64px; }
+ h1.game-title { font-size: 28px; }
+ .choices { grid-template-columns: 1fr; }
+ .header-meta { gap: 10px; font-size: 9px; }
+ .header-meta .hide-sm { display: none; }
+ .panel { padding: 36px 24px 28px; }
+ .panel h2 { font-size: 26px; }
+}
+</style>
+</head>
+<body>
+<header class="site-header">
+ <div class="wordmark">Designer<br>Wallcoverings</div>
+ <div class="header-meta">
+ <span class="hide-sm">Score<b id="scoreDisplay">0</b></span>
+ <span class="sep hide-sm"></span>
+ <span>Streak<b id="streakDisplay">0</b></span>
+ <span class="sep"></span>
+ <span>Best<b id="bestDisplay">0</b></span>
+ </div>
+</header>
+
+<main id="app">
+ <div class="eyebrow">A study in pattern</div>
+ <h1 class="game-title">Guess the Design Style</h1>
+ <p class="subhead">Ten rounds. Identify the wallcovering tradition from its motif alone. Trust your eye.</p>
+
+ <div class="stage-wrap">
+ <div class="stage" id="stage">
+ <div class="wallpaper enter" id="wallpaper"></div>
+ <div class="feedback-flash" id="flash"></div>
+ </div>
+ </div>
+
+ <div class="hud">
+ <span class="hud-stat">Round<em id="roundDisplay">1 / 10</em></span>
+ <div class="progress-track"><div class="progress-fill" id="progressFill"></div></div>
+ <span class="hud-stat">Time<em id="timeDisplay">8.0s</em></span>
+ </div>
+ <div class="timer-bar"><div class="timer-fill" id="timerFill"></div></div>
+
+ <div class="choices" id="choices"></div>
+</main>
+
+<!-- Start overlay -->
+<div class="overlay open" id="startOverlay">
+ <div class="panel">
+ <div class="ornament"></div>
+ <h2>Guess the Style</h2>
+ <p>A wallpaper motif appears. Choose its design tradition from four options. Ten rounds — accuracy and speed build your score.</p>
+ <p style="margin-bottom:28px;margin-top:12px;font-size:12px;letter-spacing:0.08em;text-transform:uppercase;color:var(--accent);">Damask · Toile · Ikat · Chinoiserie · Geometric · Grasscloth</p>
+ <button class="btn-primary" id="btnStart">Begin</button>
+ </div>
+</div>
+
+<!-- Result overlay -->
+<div class="overlay" id="resultOverlay">
+ <div class="panel">
+ <div class="ornament"></div>
+ <h2 id="resultTitle">Collection Complete</h2>
+ <div class="score-big" id="resultScore">0</div>
+ <div class="score-label">Final Score</div>
+ <div class="stats-row">
+ <div class="stat-item"><span id="resultCorrect">0</span><small>Correct</small></div>
+ <div class="stat-item"><span id="resultStreak">0</span><small>Best Streak</small></div>
+ <div class="stat-item"><span id="resultBest">0</span><small>All-Time</small></div>
+ </div>
+ <div id="newBestWrap" style="display:none;margin-bottom:20px;"><span class="best-badge">New Best Score</span></div>
+ <button class="btn-primary" id="btnRestart">Play Again</button>
+ </div>
+</div>
+
+<!-- Hidden SVG defs for patterns -->
+<svg width="0" height="0" style="position:absolute" aria-hidden="true">
+ <defs>
+ <filter id="ikatSoft" x="-10%" y="-10%" width="120%" height="120%">
+ <feGaussianBlur in="SourceGraphic" stdDeviation="1.2"/>
+ </filter>
+ </defs>
+</svg>
+
+<script>
+(function () {
+ const STYLES = ['Damask', 'Toile', 'Ikat', 'Chinoiserie', 'Geometric', 'Grasscloth'];
+ const ROUNDS = 10;
+ const ROUND_TIME = 8; // seconds
+
+ const $ = (id) => document.getElementById(id);
+ const wallpaperEl = $('wallpaper');
+ const choicesEl = $('choices');
+ const flashEl = $('flash');
+ const timerFill = $('timerFill');
+ const progressFill = $('progressFill');
+
+ let score = 0;
+ let streak = 0;
+ let bestStreak = 0;
+ let round = 0;
+ let correctCount = 0;
+ let currentStyle = null;
+ let locked = false;
+ let timerId = null;
+ let timerStart = 0;
+ let remaining = ROUND_TIME;
+ let bestScore = parseInt(localStorage.getItem('dw_guess_best') || '0', 10);
+
+ $('bestDisplay').textContent = bestScore;
+
+ /* ---------- Motif builders (inline SVG / CSS) ---------- */
+ function buildDamask() {
+ const hues = [
+ { bg: '#1a1510', gold: '#c9a961' },
+ { bg: '#1c1218', gold: '#b8956a' },
+ { bg: '#12181a', gold: '#a8b89a' }
+ ];
+ const h = hues[Math.floor(Math.random() * hues.length)];
+ return {
+ className: '',
+ html: `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 240 320" preserveAspectRatio="xMidYMid slice">
+ <rect width="240" height="320" fill="${h.bg}"/>
+ <defs>
+ <g id="med">
+ <path d="M60 20 C60 20 72 40 60 55 C48 40 60 20 60 20Z" fill="none" stroke="${h.gold}" stroke-width="1.2" opacity="0.85"/>
+ <path d="M60 55 C60 55 78 70 60 95 C42 70 60 55 60 55Z" fill="none" stroke="${h.gold}" stroke-width="1.2" opacity="0.85"/>
+ <path d="M60 95 C60 95 72 115 60 140 C48 115 60 95 60 95Z" fill="none" stroke="${h.gold}" stroke-width="1.1" opacity="0.7"/>
+ <ellipse cx="60" cy="80" rx="8" ry="14" fill="none" stroke="${h.gold}" stroke-width="1" opacity="0.9"/>
+ <circle cx="60" cy="80" r="3" fill="${h.gold}" opacity="0.7"/>
+ <path d="M40 80 Q50 70 60 80 Q70 90 80 80" fill="none" stroke="${h.gold}" stroke-width="0.8" opacity="0.55"/>
+ <path d="M40 80 Q50 90 60 80 Q70 70 80 80" fill="none" stroke="${h.gold}" stroke-width="0.8" opacity="0.55"/>
+ <path d="M60 40 Q48 55 60 70 Q72 55 60 40" fill="${h.gold}" opacity="0.15"/>
+ <path d="M30 80 Q45 55 60 80 Q45 105 30 80Z" fill="none" stroke="${h.gold}" stroke-width="0.7" opacity="0.45"/>
+ <path d="M90 80 Q75 55 60 80 Q75 105 90 80Z" fill="none" stroke="${h.gold}" stroke-width="0.7" opacity="0.45"/>
+ </g>
+ <pattern id="damaskP" width="120" height="160" patternUnits="userSpaceOnUse">
+ <use href="#med"/>
+ <use href="#med" transform="translate(120,0) scale(-1,1)"/>
+ <use href="#med" transform="translate(0,160) scale(1,-1)"/>
+ <use href="#med" transform="translate(120,160) scale(-1,-1)"/>
+ <circle cx="0" cy="0" r="2" fill="${h.gold}" opacity="0.5"/>
+ <circle cx="120" cy="0" r="2" fill="${h.gold}" opacity="0.5"/>
+ <circle cx="0" cy="160" r="2" fill="${h.gold}" opacity="0.5"/>
+ <circle cx="120" cy="160" r="2" fill="${h.gold}" opacity="0.5"/>
+ <circle cx="60" cy="80" r="1.5" fill="${h.gold}" opacity="0.35"/>
+ </pattern>
+ </defs>
+ <rect width="240" height="320" fill="url(#damaskP)"/>
+ <rect width="240" height="320" fill="url(#damaskP)" transform="translate(60,80)" opacity="0.35"/>
+ </svg>`
+ };
+ }
+
+ function buildToile() {
+ const schemes = [
+ { paper: '#f2e8d8', ink: '#2c4a6e' },
+ { paper: '#f5efe4', ink: '#6b2c2c' },
+ { paper: '#ebe6dc', ink: '#1e3a2f' }
+ ];
+ const s = schemes[Math.floor(Math.random() * schemes.length)];
+ return {
+ className: '',
+ html: `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 400 320" preserveAspectRatio="xMidYMid slice">
+ <rect width="400" height="320" fill="${s.paper}"/>
+ <g fill="none" stroke="${s.ink}" stroke-width="1.1" opacity="0.85">
+ <!-- Tree -->
+ <path d="M70 280 C72 220 60 180 80 140 C95 110 90 90 100 70"/>
+ <path d="M100 70 C110 55 130 50 140 65 C150 50 170 55 175 75"/>
+ <path d="M80 140 C55 130 40 150 50 170"/>
+ <path d="M80 140 C110 125 130 145 120 165"/>
+ <path d="M85 200 C60 195 50 210 55 230"/>
+ <path d="M88 200 C115 190 130 210 120 235"/>
+ <!-- Foliage clusters -->
+ <ellipse cx="100" cy="70" rx="22" ry="16"/>
+ <ellipse cx="130" cy="78" rx="18" ry="12"/>
+ <ellipse cx="85" cy="95" rx="14" ry="10"/>
+ <path d="M55 170 c-8-4-14 2-12 10 c-10 0-10 12 0 12 c-2 8 6 12 12 6 c6 6 14 2 12-6 c8 2 10-8 2-12 c4-6-2-12-14-10z" fill="${s.ink}" opacity="0.12" stroke="${s.ink}"/>
+ <!-- Shepherd figure -->
+ <ellipse cx="210" cy="210" rx="10" ry="8"/>
+ <path d="M210 218 L210 255"/>
+ <path d="M210 230 L195 245"/>
+ <path d="M210 230 L225 248"/>
+ <path d="M210 255 L200 280"/>
+ <path d="M210 255 L220 280"/>
+ <path d="M225 220 Q240 200 235 185"/>
+ <!-- Sheep -->
+ <ellipse cx="260" cy="265" rx="18" ry="12"/>
+ <circle cx="275" cy="260" r="7"/>
+ <path d="M280 262 L286 268"/>
+ <ellipse cx="300" cy="270" rx="14" ry="10"/>
+ <circle cx="312" cy="266" r="5.5"/>
+ <!-- Distant ruin -->
+ <path d="M320 160 L320 200 L360 200 L360 150 L345 140 L330 150 Z"/>
+ <path d="M330 200 L330 170 M350 200 L350 165"/>
+ <path d="M325 150 Q340 130 355 150"/>
+ <!-- Birds -->
+ <path d="M150 50 q8-6 16 0" stroke-width="0.9"/>
+ <path d="M180 40 q6-5 12 0" stroke-width="0.9"/>
+ <!-- Ground line -->
+ <path d="M20 280 Q100 270 200 282 Q300 275 390 285" stroke-width="0.8" opacity="0.5"/>
+ <!-- Floral sprig bottom left -->
+ <path d="M40 300 C50 280 70 290 65 305"/>
+ <circle cx="55" cy="285" r="4" fill="${s.ink}" opacity="0.2"/>
+ <path d="M55 285 l-6-10 M55 285 l6-10 M55 285 l0-12"/>
+ <!-- Repeat motif right -->
+ <g transform="translate(200,-40) scale(0.7)" opacity="0.55">
+ <path d="M70 280 C72 220 60 180 80 140 C95 110 90 90 100 70"/>
+ <ellipse cx="100" cy="70" rx="22" ry="16"/>
+ <ellipse cx="130" cy="78" rx="18" ry="12"/>
+ </g>
+ </g>
+ </svg>`
+ };
+ }
+
+ function buildIkat() {
+ const pals = [
+ ['#1e1814', '#c4a35a', '#8b3a2a', '#3d5c4a'],
+ ['#1a1a22', '#d4c4a0', '#4a6fa5', '#a04540'],
+ ['#221810', '#e8d5a3', '#b85c38', '#2f4a3c']
+ ];
+ const p = pals[Math.floor(Math.random() * pals.length)];
+ // Feathered vertical ikat columns via SVG
+ const cols = [];
+ const w = 400, h = 320;
+ const colW = 28;
+ for (let x = 0; x < w + colW; x += colW) {
+ const c = p[1 + (Math.floor(x / colW) % 3)];
+ const phase = (x * 0.07) % (Math.PI * 2);
+ // diamond-like vertical blobs
+ let d = '';
+ for (let y = -20; y < h + 40; y += 56) {
+ const yy = y + Math.sin(phase + y * 0.02) * 8;
+ const hw = 7 + Math.sin(phase * 2 + y * 0.03) * 4;
+ d += `M${x + colW/2},${yy} L${x + colW/2 + hw},${yy + 14} L${x + colW/2},${yy + 28} L${x + colW/2 - hw},${yy + 14} Z `;
+ }
+ cols.push(`<path d="${d}" fill="${c}" opacity="0.88"/>`);
+ // secondary offset row
+ let d2 = '';
+ for (let y = 8; y < h + 40; y += 56) {
+ const yy = y + Math.cos(phase + y * 0.02) * 6;
+ const hw = 5 + Math.cos(phase + y * 0.04) * 3;
+ d2 += `M${x + colW/2},${yy} L${x + colW/2 + hw},${yy + 12} L${x + colW/2},${yy + 24} L${x + colW/2 - hw},${yy + 12} Z `;
+ }
+ const c2 = p[1 + ((Math.floor(x / colW) + 1) % 3)];
+ cols.push(`<path d="${d2}" fill="${c2}" opacity="0.55"/>`);
+ }
+ return {
+ className: '',
+ html: `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 ${w} ${h}" preserveAspectRatio="xMidYMid slice">
+ <rect width="${w}" height="${h}" fill="${p[0]}"/>
+ <g filter="url(#ikatSoft)">${cols.join('')}</g>
+ <!-- soft horizontal weave suggestion -->
+ <g opacity="0.12" stroke="${p[1]}" stroke-width="0.6">
+ ${Array.from({length: 20}, (_, i) => `<line x1="0" y1="${i*16+8}" x2="${w}" y2="${i*16+8}"/>`).join('')}
+ </g>
+ </svg>`
+ };
+ }
+
+ function buildChinoiserie() {
+ const schemes = [
+ { sky: '#1a2820', mist: '#2a4034', gold: '#d4c08a', leaf: '#8aab78' },
+ { sky: '#1a2030', mist: '#2a3548', gold: '#c9b896', leaf: '#7a9a8a' },
+ { sky: '#251a18', mist: '#3a2824', gold: '#e0c890', leaf: '#a08060' }
+ ];
+ const s = schemes[Math.floor(Math.random() * schemes.length)];
+ return {
+ className: '',
+ html: `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 400 320" preserveAspectRatio="xMidYMid slice">
+ <defs>
+ <linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="${s.mist}"/>
+ <stop offset="100%" stop-color="${s.sky}"/>
+ </linearGradient>
+ <radialGradient id="moon" cx="70%" cy="18%" r="20%">
+ <stop offset="0%" stop-color="${s.gold}" stop-opacity="0.35"/>
+ <stop offset="100%" stop-color="${s.gold}" stop-opacity="0"/>
+ </radialGradient>
+ </defs>
+ <rect width="400" height="320" fill="url(#sky)"/>
+ <rect width="400" height="320" fill="url(#moon)"/>
+ <!-- Pagoda silhouette far -->
+ <g fill="${s.gold}" opacity="0.25">
+ <rect x="300" y="160" width="50" height="40"/>
+ <path d="M290 160 L325 140 L360 160 Z"/>
+ <path d="M295 140 L325 122 L355 140 Z"/>
+ <path d="M305 122 L325 108 L345 122 Z"/>
+ <rect x="320" y="95" width="10" height="14"/>
+ </g>
+ <!-- Willow / flowering branch -->
+ <g fill="none" stroke="${s.gold}" stroke-width="1.4" stroke-linecap="round">
+ <path d="M40 320 C60 240 40 180 90 120 C120 85 160 70 200 80"/>
+ <path d="M90 120 C70 100 90 60 120 50" stroke-width="1"/>
+ <path d="M140 95 C150 60 190 55 210 75" stroke-width="1"/>
+ <path d="M180 82 C200 50 250 55 260 90" stroke-width="1.1"/>
+ <path d="M200 80 C230 90 270 100 300 140" stroke-width="1"/>
+ <!-- hanging willow strands -->
+ <path d="M120 55 C115 90 125 120 118 150" stroke-width="0.7" opacity="0.7"/>
+ <path d="M135 52 C138 95 128 130 140 165" stroke-width="0.7" opacity="0.65"/>
+ <path d="M160 58 C155 100 168 140 158 180" stroke-width="0.7" opacity="0.6"/>
+ <path d="M190 60 C195 105 185 145 198 190" stroke-width="0.65" opacity="0.55"/>
+ <path d="M230 70 C225 110 240 150 228 195" stroke-width="0.65" opacity="0.5"/>
+ </g>
+ <!-- Blossoms -->
+ <g fill="${s.gold}" opacity="0.7">
+ <circle cx="120" cy="48" r="4"/><circle cx="128" cy="44" r="2.5"/><circle cx="114" cy="42" r="2"/>
+ <circle cx="175" cy="58" r="3.5"/><circle cx="183" cy="54" r="2"/>
+ <circle cx="220" cy="68" r="4"/><circle cx="228" cy="62" r="2.5"/><circle cx="214" cy="62" r="2"/>
+ <circle cx="255" cy="88" r="3"/>
+ <circle cx="95" cy="100" r="2.5"/>
+ </g>
+ <!-- Leaves -->
+ <g fill="${s.leaf}" opacity="0.45">
+ <ellipse cx="150" cy="90" rx="8" ry="3" transform="rotate(-30 150 90)"/>
+ <ellipse cx="205" cy="95" rx="9" ry="3" transform="rotate(20 205 95)"/>
+ <ellipse cx="100" cy="130" rx="7" ry="2.5" transform="rotate(-40 100 130)"/>
+ <ellipse cx="280" cy="130" rx="8" ry="3" transform="rotate(35 280 130)"/>
+ </g>
+ <!-- Crane / bird -->
+ <g fill="none" stroke="${s.gold}" stroke-width="1.2" opacity="0.9">
+ <path d="M250 150 Q270 140 290 155"/>
+ <path d="M290 155 L300 148"/>
+ <path d="M270 148 Q275 135 285 140"/>
+ <path d="M265 152 Q260 170 255 175"/>
+ <path d="M255 175 L250 185 M255 175 L262 186"/>
+ <circle cx="298" cy="147" r="1.5" fill="${s.gold}"/>
+ </g>
+ <!-- Bridge hint -->
+ <path d="M20 270 Q80 240 140 270" fill="none" stroke="${s.gold}" stroke-width="1" opacity="0.3"/>
+ <path d="M50 270 L50 290 M90 268 L90 295 M120 270 L120 288" stroke="${s.gold}" stroke-width="0.8" opacity="0.25"/>
+ </svg>`
+ };
+ }
+
+ function buildGeometric() {
+ const schemes = [
+ { bg: '#0e0e12', line: '#c9a961', soft: 'rgba(201,169,97,0.2)' },
+ { bg: '#14101a', line: '#a890c0', soft: 'rgba(168,144,192,0.2)' },
+ { bg: '#101816', line: '#80a890', soft: 'rgba(128,168,144,0.22)' }
+ ];
+ const s = schemes[Math.floor(Math.random() * schemes.length)];
+ return {
+ className: '',
+ html: `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 360 288" preserveAspectRatio="xMidYMid slice">
+ <rect width="360" height="288" fill="${s.bg}"/>
+ <defs>
+ <pattern id="geo" width="72" height="84" patternUnits="userSpaceOnUse">
+ <!-- hex lattice -->
+ <path d="M36 2 L66 19 L66 53 L36 70 L6 53 L6 19 Z" fill="none" stroke="${s.line}" stroke-width="1" opacity="0.85"/>
+ <path d="M36 18 L54 28 L54 48 L36 58 L18 48 L18 28 Z" fill="none" stroke="${s.line}" stroke-width="0.7" opacity="0.5"/>
+ <circle cx="36" cy="36" r="3" fill="${s.line}" opacity="0.7"/>
+ <circle cx="36" cy="36" r="7" fill="none" stroke="${s.line}" stroke-width="0.6" opacity="0.4"/>
+ <!-- diamond accents at corners -->
+ <path d="M0 42 L6 36 L0 30" fill="none" stroke="${s.line}" stroke-width="0.6" opacity="0.45"/>
+ <path d="M72 42 L66 36 L72 30" fill="none" stroke="${s.line}" stroke-width="0.6" opacity="0.45"/>
+ <!-- thin rays -->
+ <line x1="36" y1="2" x2="36" y2="18" stroke="${s.line}" stroke-width="0.5" opacity="0.4"/>
+ <line x1="36" y1="58" x2="36" y2="70" stroke="${s.line}" stroke-width="0.5" opacity="0.4"/>
+ </pattern>
+ <pattern id="geo2" width="72" height="84" patternUnits="userSpaceOnUse" patternTransform="translate(36,42)">
+ <path d="M36 10 L58 23 L58 49 L36 62 L14 49 L14 23 Z" fill="${s.soft}"/>
+ </pattern>
+ </defs>
+ <rect width="360" height="288" fill="url(#geo2)"/>
+ <rect width="360" height="288" fill="url(#geo)"/>
+ <!-- art deco fan corners -->
+ <g stroke="${s.line}" fill="none" stroke-width="0.8" opacity="0.35">
+ <path d="M0 0 Q40 40 0 80 M0 0 Q60 40 0 80 M0 0 Q80 40 0 80"/>
+ <path d="M360 288 Q320 248 360 208 M360 288 Q300 248 360 208 M360 288 Q280 248 360 208"/>
+ </g>
+ </svg>`
+ };
+ }
+
+ function buildGrasscloth() {
+ const tones = [
+ { base: '#c4b49a', dark: '#8a7a60', light: '#d8cab0', fiber: '#6a5a42' },
+ { base: '#b7a890', dark: '#7a6c54', light: '#cdc0a8', fiber: '#5c4e38' },
+ { base: '#c8b8a0', dark: '#9a8870', light: '#e0d4bc', fiber: '#70604a' },
+ { base: '#a8b09a', dark: '#6a7860', light: '#c0c8b0', fiber: '#4a5840' }
+ ];
+ const t = tones[Math.floor(Math.random() * tones.length)];
+ // Simulate woven fibers with many fine lines of varying opacity
+ const lines = [];
+ for (let y = 0; y < 320; y += 2) {
+ const op = 0.04 + Math.random() * 0.12;
+ const wobble = (Math.random() - 0.5) * 1.5;
+ const col = Math.random() > 0.5 ? t.dark : t.fiber;
+ lines.push(`<line x1="0" y1="${y + wobble}" x2="400" y2="${y + wobble}" stroke="${col}" stroke-width="${1 + Math.random()}" opacity="${op}"/>`);
+ }
+ // Vertical slubs
+ const slubs = [];
+ for (let x = 0; x < 400; x += 3 + Math.random() * 5) {
+ const op = 0.03 + Math.random() * 0.08;
+ slubs.push(`<line x1="${x}" y1="0" x2="${x + (Math.random()-0.5)*2}" y2="320" stroke="${t.fiber}" stroke-width="${0.6 + Math.random()}" opacity="${op}"/>`);
+ }
+ return {
+ className: '',
+ html: `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 400 320" preserveAspectRatio="xMidYMid slice">
+ <defs>
+ <linearGradient id="gc" x1="0" y1="0" x2="0" y2="1">
+ <stop offset="0%" stop-color="${t.light}"/>
+ <stop offset="40%" stop-color="${t.base}"/>
+ <stop offset="70%" stop-color="${t.dark}" stop-opacity="0.35"/>
+ <stop offset="100%" stop-color="${t.base}"/>
+ </linearGradient>
+ </defs>
+ <rect width="400" height="320" fill="url(#gc)"/>
+ <g stroke-linecap="butt">${lines.join('')}</g>
+ <g>${slubs.join('')}</g>
+ <!-- subtle panel variation -->
+ <rect x="0" y="0" width="133" height="320" fill="${t.light}" opacity="0.06"/>
+ <rect x="266" y="0" width="134" height="320" fill="${t.dark}" opacity="0.05"/>
+ </svg>`
+ };
+ }
+
+ const BUILDERS = {
+ Damask: buildDamask,
+ Toile: buildToile,
+ Ikat: buildIkat,
+ Chinoiserie: buildChinoiserie,
+ Geometric: buildGeometric,
+ Grasscloth: buildGrasscloth
+ };
+
+ /* ---------- Game logic ---------- */
+ function shuffle(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 pickOptions(correct) {
+ const others = shuffle(STYLES.filter(s => s !== correct)).slice(0, 3);
+ return shuffle([correct, ...others]);
+ }
+
+ function updateHUD() {
+ $('scoreDisplay').textContent = score;
+ $('streakDisplay').textContent = streak;
+ $('bestDisplay').textContent = bestScore;
+ $('roundDisplay').textContent = Math.min(round, ROUNDS) + ' / ' + ROUNDS;
+ progressFill.style.width = ((Math.min(round, ROUNDS) / ROUNDS) * 100) + '%';
+ }
+
+ function stopTimer() {
+ if (timerId) {
+ cancelAnimationFrame(timerId);
+ timerId = null;
+ }
+ }
+
+ function startTimer() {
+ stopTimer();
+ timerStart = performance.now();
+ remaining = ROUND_TIME;
+ timerFill.style.transition = 'none';
+ timerFill.style.transform = 'scaleX(1)';
+ timerFill.classList.remove('urgent');
+ $('timeDisplay').textContent = ROUND_TIME.toFixed(1) + 's';
+
+ // force reflow then animate
+ void timerFill.offsetWidth;
+ timerFill.style.transition = `transform ${ROUND_TIME}s linear`;
+ timerFill.style.transform = 'scaleX(0)';
+
+ function tick(now) {
+ const elapsed = (now - timerStart) / 1000;
+ remaining = Math.max(0, ROUND_TIME - elapsed);
+ $('timeDisplay').textContent = remaining.toFixed(1) + 's';
+ if (remaining <= 2.5) timerFill.classList.add('urgent');
+ if (remaining <= 0) {
+ onTimeout();
+ return;
+ }
+ timerId = requestAnimationFrame(tick);
+ }
+ timerId = requestAnimationFrame(tick);
+ }
+
+ function showMotif(style) {
+ const built = BUILDERS[style]();
+ wallpaperEl.classList.remove('enter');
+ wallpaperEl.classList.add('exit');
+ setTimeout(() => {
+ wallpaperEl.className = 'wallpaper enter' + (built.className ? ' ' + built.className : '');
+ wallpaperEl.innerHTML = built.html || '';
+ }, 200);
+ }
+
+ function renderChoices(options) {
+ choicesEl.innerHTML = '';
+ options.forEach(opt => {
+ const btn = document.createElement('button');
+ btn.className = 'choice';
+ btn.type = 'button';
+ btn.textContent = opt;
+ btn.dataset.style = opt;
+ btn.addEventListener('click', () => onGuess(opt, btn));
+ choicesEl.appendChild(btn);
+ });
+ }
+
+ function nextRound() {
+ if (round >= ROUNDS) {
+ endGame();
+ return;
+ }
+ round += 1;
+ locked = false;
+ flashEl.className = 'feedback-flash';
+ currentStyle = STYLES[Math.floor(Math.random() * STYLES.length)];
+ // avoid same style thrice in a row by light shuffle pressure
+ showMotif(currentStyle);
+ renderChoices(pickOptions(currentStyle));
+ updateHUD();
+ startTimer();
+ }
+
+ function onGuess(choice, btn) {
+ if (locked) return;
+ locked = true;
+ stopTimer();
+
+ const buttons = [...choicesEl.querySelectorAll('.choice')];
+ const correct = choice === currentStyle;
+ const timeBonus = Math.round(remaining * 12);
+
+ buttons.forEach(b => {
+ b.disabled = true;
+ if (b.dataset.style === currentStyle) b.classList.add('correct');
+ else if (b === btn && !correct) b.classList.add('wrong');
+ else b.classList.add('dim');
+ });
+
+ if (correct) {
+ streak += 1;
+ bestStreak = Math.max(bestStreak, streak);
+ correctCount += 1;
+ const pts = 100 + timeBonus + Math.min(streak * 15, 75);
+ score += pts;
+ flashEl.className = 'feedback-flash show-correct';
+ } else {
+ streak = 0;
+ flashEl.className = 'feedback-flash show-wrong';
+ }
+ updateHUD();
+
+ setTimeout(() => nextRound(), 900);
+ }
+
+ function onTimeout() {
+ if (locked) return;
+ locked = true;
+ stopTimer();
+ streak = 0;
+ flashEl.className = 'feedback-flash show-wrong';
+ const buttons = [...choicesEl.querySelectorAll('.choice')];
+ buttons.forEach(b => {
+ b.disabled = true;
+ if (b.dataset.style === currentStyle) b.classList.add('correct');
+ else b.classList.add('dim');
+ });
+ updateHUD();
+ setTimeout(() => nextRound(), 900);
+ }
+
+ function endGame() {
+ stopTimer();
+ let isNew = false;
+ if (score > bestScore) {
+ bestScore = score;
+ localStorage.setItem('dw_guess_best', String(bestScore));
+ isNew = true;
+ }
+ updateHUD();
+ $('resultTitle').textContent = correctCount >= 8 ? 'Impeccable Taste' :
+ correctCount >= 5 ? 'Collection Complete' : 'A Study Continued';
+ $('resultScore').textContent = score;
+ $('resultCorrect').textContent = correctCount + '/' + ROUNDS;
+ $('resultStreak').textContent = bestStreak;
+ $('resultBest').textContent = bestScore;
+ $('newBestWrap').style.display = isNew ? 'block' : 'none';
+ $('resultOverlay').classList.add('open');
+ }
+
+ function startGame() {
+ score = 0;
+ streak = 0;
+ bestStreak = 0;
+ round = 0;
+ correctCount = 0;
+ locked = false;
+ updateHUD();
+ progressFill.style.width = '0%';
+ $('startOverlay').classList.remove('open');
+ $('resultOverlay').classList.remove('open');
+ nextRound();
+ }
+
+ $('btnStart').addEventListener('click', startGame);
+ $('btnRestart').addEventListener('click', startGame);
+
+ // Preview motif on start screen
+ showMotif(STYLES[Math.floor(Math.random() * STYLES.length)]);
+ renderChoices(shuffle(STYLES).slice(0, 4));
+ [...choicesEl.querySelectorAll('.choice')].forEach(b => { b.disabled = true; b.classList.add('dim'); });
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/grok.png b/data/artifacts/bf0bdeb4c423/grok.png
new file mode 100644
index 0000000..541d4bc
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/grok.png differ
diff --git a/data/artifacts/bf0bdeb4c423/hermes3-8b.html b/data/artifacts/bf0bdeb4c423/hermes3-8b.html
new file mode 100644
index 0000000..8db3f94
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/hermes3-8b.html
@@ -0,0 +1,236 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Wallpaper Style Game</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --text: #1c1a17;
+ --muted: #9b948a;
+ --accent1: #b0472e;
+ --accent2: #2f4c39;
+ --line: 1px solid #dcdcdc;
+ --shadow-light: 0 8px 24px rgba(255, 255, 255, .12);
+ --shadow-dark: 0 8px 24px rgba(0, 0, 0, .12);
+ --ease-in-out-quart: cubic-bezier(.22, 1, .36, 1);
+ }
+
+ body {
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ line-height: 1.6;
+ background-color: var(--bg);
+ color: var(--text);
+ }
+
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ padding: 32px 24px;
+ background-color: var(--bg);
+ box-shadow: var(--line) calc(var(--line) * 2) 0;
+ }
+
+ .wordmark {
+ font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+ font-size: 36px;
+ letter-spacing: .15em;
+ color: #333;
+ }
+
+ main {
+ margin-top: 96px;
+ padding: 0 24px;
+ }
+
+ h1 {
+ font-size: 50px;
+ text-align: center;
+ }
+
+ .card {
+ display: flex;
+ justify-content: space-around;
+ align-items: center;
+ margin-bottom: 32px;
+ padding: 48px;
+ background-color: var(--surface);
+ border-radius: 14px;
+ box-shadow: var(--shadow-light);
+ transition: box-shadow .3s var(--ease-in-out-quart), transform .7s var(--ease-in-out-quart);
+ }
+
+ .card:hover {
+ box-shadow: var(--shadow-dark);
+ transform: translateY(-8px);
+ }
+
+ .button {
+ background-color: var(--muted);
+ border: none;
+ color: var(--surface);
+ font-size: 24px;
+ padding: 16px 32px;
+ cursor: pointer;
+ transition: background-color .3s, box-shadow .3s, transform .7s var(--ease-in-out-quart), color .3s;
+ }
+
+ .button:hover {
+ background-color: var(--accent1);
+ color: #fff;
+ box-shadow: 0 8px 24px rgba(0, 0, 0, .18);
+ transform: scale(1.05);
+ }
+
+ .overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: var(--bg);
+ opacity: 0;
+ transition: opacity .5s, visibility .5s;
+ }
+
+ .overlay.active {
+ opacity: 1;
+ visibility: visible;
+ }
+ </style>
+</head>
+<body>
+ <header>
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ </header>
+
+ <main>
+ <h1>Guess the Wallpaper Style</h1>
+
+ <div class="card active">
+ <button class="button" id="damask">Damask</button>
+ <button class="button" id="toile">Toile</button>
+ <button class="button" id="ikат">Ikat</button>
+ <button class="button" id="chinoiserie">Chinoiserie</button>
+ </div>
+
+ <!-- Overlay for game over/winner states -->
+ <div class="overlay" id="gameOverOverlay">
+ <h2>Game Over!</h2>
+ <p>Your final score: <span id="finalScore"></span></p>
+ <button onclick="restart()">Play Again</button>
+ </div>
+
+ <!-- Overlay for winner state -->
+ <div class="overlay" id="winnerOverlay">
+ <h2>Congrats, You Won!</h2>
+ <p>Your score: <span id="winningScore"></span></span></p>
+ <button onclick="restart()">Play Again</button>
+ </div>
+
+ <!-- Overlay for round result -->
+ <div class="overlay" id="resultOverlay">
+ <h2 id="feedback"></h2>
+ <p>Score: <span id="score"></span></p>
+ <button onclick="nextRound()">Next Round</button>
+ </div>
+ </main>
+
+ <script>
+ let rounds = 0;
+ const maxRounds = 10;
+ let score = 0;
+ const streak = [0, 0];
+ const styles = ["damask", "toile", "ikat", "chinoiserie"];
+
+ const bgTokens = getComputedStyle(document.documentElement).getPropertyValue('--bg');
+ const surfaceTokens = getComputedStyle(document.documentElement).getPropertyValue('--surface');
+ const textTokens = getComputedStyle(document.documentElement).getPropertyValue('--text');
+
+ function nextRound() {
+ rounds++;
+
+ if (rounds > maxRounds) {
+ endGame();
+ return;
+ }
+
+ document.getElementById(styles[getRandomInt(0, 4)]).click();
+ }
+
+ function restart() {
+ rounds = 0;
+ score = 0;
+ streak = [0, 0];
+ updateScoreBoard();
+ nextRound();
+ }
+
+ function endGame() {
+ const finalScore = JSON.parse(localStorage.getItem('wallpaperScore')) || { overall: 0 };
+ finalScore.overall += score;
+ localStorage.setItem('wallpaperScore', JSON.stringify(finalScore));
+
+ document.getElementById('gameOverOverlay').classList.add('active');
+ document.getElementById('finalScore').textContent = finalScore.overall;
+ }
+
+ function checkAnswer(selectedStyle, correctStyle) {
+ if (selectedStyle === correctStyle) {
+ streak[1]++;
+ if (streak[0] !== 2 || streak[1] !== 3) {
+ score += Math.pow(2, streak[0] + streak[1]);
+ updateScoreBoard();
+
+ document.getElementById('resultOverlay').classList.add('active');
+ document.getElementById('feedback').textContent = "Correct!";
+ nextRound();
+ } else {
+ declareWinner();
+ }
+ } else {
+ streak[0]++;
+
+ document.getElementById('resultOverlay').classList.add('active');
+ document.getElementById('feedback').textContent = "Wrong!";
+ nextRound();
+ }
+ }
+
+ function updateScoreBoard() {
+ document.getElementById('score').textContent = score;
+ }
+
+ function getRandomInt(min, max) {
+ min = Math.ceil(min);
+ max = Math.floor(max);
+ return Math.floor(Math.random() * (max - min)) + min;
+ }
+
+ function declareWinner() {
+ const winningScore = JSON.parse(localStorage.getItem('wallpaperScore')) || { overall: 0 };
+
+ document.getElementById('winnerOverlay').classList.add('active');
+ document.getElementById('winningScore').textContent = winningScore.overall;
+
+ localStorage.setItem('wallpaperScore', JSON.stringify({ overall: winningScore.overall }));
+ }
+
+ function selectStyle(style) {
+ const correctStyle = styles[getRandomInt(0, 4)];
+ checkAnswer(style, correctStyle);
+ }
+
+ document.getElementById('damask').addEventListener('click', () => selectStyle('damask'));
+ document.getElementById('toile').addEventListener('click', () => selectStyle('toile'));
+ document.getElementById('ikat').addEventListener('click', () => selectStyle('ikат'));
+ document.getElementById('chinoiserie').addEventListener('click', () => selectStyle('chinoiserie'));
+
+ restart();
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/hermes3-8b.png b/data/artifacts/bf0bdeb4c423/hermes3-8b.png
new file mode 100644
index 0000000..75049d1
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/hermes3-8b.png differ
diff --git a/data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.html b/data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.html
new file mode 100644
index 0000000..e9deb85
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.html
@@ -0,0 +1,252 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Guess the Design Style</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --ink: #1c1a17;
+ --muted: #9b948a;
+ --accent: #b0472e;
+ --line: #e0dcd3;
+ --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 {
+ margin: 0;
+ font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ background-color: var(--bg);
+ color: var(--ink);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ font-size: 16px;
+ line-height: 1.5;
+ }
+ header {
+ width: 100%;
+ padding: 24px 32px;
+ background-color: var(--surface);
+ box-shadow: 0 8px 24px var(--shadow);
+ display: flex;
+ align-items: center;
+ }
+ .wordmark {
+ font-family: 'Playfair Display', Georgia, serif;
+ font-size: 38px;
+ letter-spacing: .18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ }
+ main {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 96px 24px;
+ width: 100%;
+ }
+ .wallpaper-container {
+ position: relative;
+ width: 320px;
+ height: 320px;
+ margin-bottom: 48px;
+ background-color: var(--surface);
+ box-shadow: 0 8px 24px var(--shadow);
+ border-radius: 14px;
+ overflow: hidden;
+ }
+ .wallpaper {
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-size: cover;
+ }
+ .options {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
+ gap: 24px;
+ width: 100%;
+ max-width: 640px;
+ }
+ .option {
+ background-color: var(--surface);
+ border-radius: 14px;
+ padding: 16px;
+ text-align: center;
+ font-weight: bold;
+ letter-spacing: .15em;
+ color: var(--muted);
+ cursor: pointer;
+ transition: box-shadow .2s ease, transform .2s ease;
+ }
+ .option:hover {
+ box-shadow: 0 16px 48px var(--hover-shadow);
+ transform: translateY(-4px);
+ }
+ .overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, .7);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ animation: fadeUp .7s var(--ease) both;
+ }
+ .overlay-content {
+ background-color: var(--surface);
+ padding: 48px;
+ border-radius: 14px;
+ box-shadow: 0 24px 64px var(--hover-shadow);
+ text-align: center;
+ }
+ .overlay-content h2 {
+ font-size: 38px;
+ margin-bottom: 24px;
+ }
+ .overlay-content p {
+ font-size: 18px;
+ color: var(--muted);
+ margin-bottom: 24px;
+ }
+ .overlay-content button {
+ background-color: var(--accent);
+ color: var(--surface);
+ border: none;
+ padding: 12px 24px;
+ font-weight: bold;
+ letter-spacing: .15em;
+ cursor: pointer;
+ transition: background-color .2s ease;
+ }
+ .overlay-content button:hover {
+ background-color: var(--ink);
+ }
+ </style>
+</head>
+<body>
+ <header>
+ <div class="wordmark">DESIGNER WALLCOVERINGS</div>
+ </header>
+ <main>
+ <div class="wallpaper-container">
+ <div id="wallpaper" class="wallpaper"></div>
+ </div>
+ <div class="options">
+ <button data-style="Damask" class="option">DAMASK</button>
+ <button data-style="Toile" class="option">TOILE</button>
+ <button data-style="Ikat" class="option">IKAT</button>
+ <button data-style="Chinoiserie" class="option">CHINOISERIE</button>
+ <button data-style="Geometric" class="option">GEOMETRIC</button>
+ <button data-style="Grasscloth" class="option">GRASSCLOTH</button>
+ </div>
+ </main>
+ <script>
+ const styles = {
+ Damask: `background-image: linear-gradient(45deg, transparent 25%, var(--muted) 25%, var(--muted) 75%, transparent 75%), linear-gradient(45deg, transparent 25%, var(--accent) 25%, var(--accent) 75%, transparent 75%);
+ background-size: 60px 60px;`,
+ Toile: `background-image: radial-gradient(circle at center, var(--muted), transparent);
+ background-size: 80px 80px;
+ background-position: center;`,
+ Ikat: `background-image: repeating-linear-gradient(45deg, var(--accent) 0%, var(--accent) 10%, transparent 10%, transparent 20%);
+ background-size: 30px 30px;`,
+ Chinoiserie: `background-image: linear-gradient(to right, var(--muted), transparent),
+ linear-gradient(to bottom, var(--muted), transparent);
+ background-size: 40px 40px;
+ background-position: center;`,
+ Geometric: `background-image: radial-gradient(circle at top left, var(--accent) 25%, transparent 25%),
+ radial-gradient(circle at top right, var(--accent) 25%, transparent 25%),
+ radial-gradient(circle at bottom left, var(--accent) 25%, transparent 25%),
+ radial-gradient(circle at bottom right, var(--accent) 25%, transparent 25%);
+ background-size: 60px 60px;
+ background-position: center;`,
+ Grasscloth: `background-image: url('data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22%3E%3Cpath d=%22M50,0 L60,90 L40,90 Z%22 fill=%22var(--muted)%22/%3E%3Cpath d=%22M50,100 L60,10 L40,10 Z%22 fill=%22var(--accent)%22/%3E%3C/svg%3E');
+ background-size: 10px 10px;
+ background-repeat: repeat;`
+ };
+ const wallpaper = document.getElementById('wallpaper');
+ const options = document.querySelectorAll('.option');
+ let score = 0;
+ let streak = 0;
+ let bestScore = localStorage.getItem('bestScore') || 0;
+ let currentStyle;
+ let rounds = 10;
+ let round = 0;
+ let timer;
+
+ function startGame() {
+ round++;
+ if (round > rounds) {
+ endGame();
+ return;
+ }
+ currentStyle = Object.keys(styles)[Math.floor(Math.random() * Object.keys(styles).length)];
+ wallpaper.setAttribute('style', styles[currentStyle]);
+ timer = setTimeout(() => {
+ revealResult(false);
+ }, 5000);
+ }
+
+ function checkAnswer(event) {
+ clearTimeout(timer);
+ const selectedStyle = event.target.getAttribute('data-style');
+ if (selectedStyle === currentStyle) {
+ score++;
+ streak++;
+ revealResult(true);
+ } else {
+ streak = 0;
+ revealResult(false);
+ }
+ }
+
+ function revealResult(correct) {
+ const overlayContent = `
+ <h2>${correct ? 'CORRECT!' : 'WRONG!'}</h2>
+ <p>Score: ${score}<br>Streak: ${streak}<br>Round: ${round}/${rounds}</p>
+ <button onclick="restartGame()">RESTART</button>
+ `;
+ const overlay = document.createElement('div');
+ overlay.classList.add('overlay');
+ overlay.innerHTML = `<div class="overlay-content">${overlayContent}</div>`;
+ document.body.appendChild(overlay);
+ }
+
+ function endGame() {
+ if (score > bestScore) {
+ localStorage.setItem('bestScore', score);
+ bestScore = score;
+ }
+ const overlayContent = `
+ <h2>GAME OVER</h2>
+ <p>Final Score: ${score}<br>Best Score: ${bestScore}</p>
+ <button onclick="restartGame()">RESTART</button>
+ `;
+ const overlay = document.createElement('div');
+ overlay.classList.add('overlay');
+ overlay.innerHTML = `<div class="overlay-content">${overlayContent}</div>`;
+ document.body.appendChild(overlay);
+ }
+
+ function restartGame() {
+ score = 0;
+ streak = 0;
+ round = 0;
+ document.querySelectorAll('.overlay').forEach(el => el.remove());
+ startGame();
+ }
+
+ options.forEach(option => option.addEventListener('click', checkAnswer));
+ startGame();
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.png b/data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.png
new file mode 100644
index 0000000..2a3793b
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/hf-qwen-coder-32b.png differ
diff --git a/data/artifacts/bf0bdeb4c423/kimi.html b/data/artifacts/bf0bdeb4c423/kimi.html
new file mode 100644
index 0000000..2ec8e60
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/kimi.html
@@ -0,0 +1,680 @@
+<!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 Quiz</title>
+<style>
+:root {
+ /* Luxury Palette — warm ivory ground */
+ --bg: #f5f2ea;
+ --surface: #ffffff;
+ --ink: #1a1a1a;
+ --muted: #8a8578;
+ --accent: #c9a961;
+ --accent-hover: #b8994d;
+ --line: #e0dbd0;
+ --shadow: 0 4px 24px rgba(26,26,26,0.08);
+ --shadow-deep: 0 8px 32px rgba(26,26,26,0.12);
+
+ /* Typography */
+ --font-display: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+ --font-ui: 'Avenir Next', 'Century Gothic', Futura, 'Segoe UI', sans-serif;
+
+ /* Motion */
+ --ease-hero: cubic-bezier(.22,1,.36,1);
+ --ease-ui: cubic-bezier(.22,.9,.24,1);
+
+ /* Scale */
+ --text-caption: 12px;
+ --text-body: 16px;
+ --text-h3: 28px;
+ --text-h2: 38px;
+ --text-display: 48px;
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html {
+ font-size: 16px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+body {
+ font-family: var(--font-ui);
+ background: var(--bg);
+ color: var(--ink);
+ line-height: 1.6;
+ min-height: 100vh;
+ padding-top: 80px;
+}
+
+/* Fixed Header */
+header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 72px;
+ background: var(--surface);
+ border-bottom: 1px solid var(--line);
+ display: flex;
+ align-items: center;
+ padding: 0 48px;
+ z-index: 100;
+ box-shadow: var(--shadow);
+}
+
+.wordmark {
+ font-family: var(--font-display);
+ font-size: 18px;
+ font-weight: 400;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: var(--ink);
+ line-height: 1.2;
+}
+
+/* Main Layout */
+main {
+ max-width: 900px;
+ margin: 0 auto;
+ padding: 48px;
+}
+
+/* Game Stats Bar */
+.stats-bar {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 40px;
+ padding-bottom: 24px;
+ border-bottom: 1px solid var(--line);
+}
+
+.stat-group {
+ display: flex;
+ gap: 32px;
+}
+
+.stat {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+
+.stat-label {
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 0.16em;
+ color: var(--muted);
+ font-weight: 500;
+}
+
+.stat-value {
+ font-size: var(--text-h3);
+ font-weight: 600;
+ color: var(--ink);
+ line-height: 1;
+}
+
+.stat-value.accent {
+ color: var(--accent);
+}
+
+/* Pattern Stage */
+.pattern-stage {
+ position: relative;
+ width: 100%;
+ aspect-ratio: 4/3;
+ background: var(--surface);
+ border-radius: 2px;
+ box-shadow: var(--shadow-deep);
+ overflow: hidden;
+ margin-bottom: 40px;
+ border: 1px solid var(--line);
+}
+
+.pattern-display {
+ width: 100%;
+ height: 100%;
+ position: relative;
+}
+
+/* Pattern Styles — Pure CSS/SVG */
+.pattern-damask {
+ background-color: #f8f6f1;
+ background-image:
+ radial-gradient(circle at 30% 30%, var(--accent) 0%, transparent 50%),
+ radial-gradient(circle at 70% 70%, var(--accent) 0%, transparent 50%),
+ radial-gradient(circle at 50% 50%, rgba(201,169,97,0.3) 0%, transparent 70%);
+ background-size: 60px 60px, 60px 60px, 120px 120px;
+}
+
+.pattern-damask::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%3Cpath d='M60 20c-8 0-15 6-15 14 0 5 3 9 7 12-4 2-8 6-8 12 0 8 7 14 16 14 4 0 7-1 10-3 3 2 6 3 10 3 9 0 16-6 16-14 0-6-4-10-8-12 4-3 7-7 7-12 0-8-7-14-15-14-4 0-8 2-10 5-2-3-6-5-10-5z' fill='%23c9a961' fill-opacity='0.25'/%3E%3C/svg%3E");
+ opacity: 0.6;
+}
+
+.pattern-toile {
+ background-color: #f0ebe3;
+ position: relative;
+}
+
+.pattern-toile::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 200 200'%3E%3Cg fill='%232d4a3e' fill-opacity='0.15'%3E%3Cpath d='M40 160c0-20 10-30 20-40s20-20 20-40c0-15-10-25-20-30s-20-15-20-30c0-10 5-20 15-25s20-10 25-5' stroke='%232d4a3e' stroke-width='1' fill='none'/%3E%3Ccircle cx='100' cy='60' r='8'/%3E%3Cpath d='M140 180c10-20 5-40-10-55s-30-25-30-45c0-20 15-35 30-40' stroke='%232d4a3e' stroke-width='1' fill='none'/%3E%3Cpath d='M160 40c-15 5-25 20-25 35s10 25 20 30' stroke='%232d4a3e' stroke-width='1' fill='none'/%3E%3C/g%3E%3C/svg%3E");
+}
+
+.pattern-ikat {
+ background:
+ repeating-linear-gradient(45deg, transparent, transparent 10px, rgba(201,169,97,0.3) 10px, rgba(201,169,97,0.3) 20px),
+ repeating-linear-gradient(-45deg, transparent, transparent 15px, rgba(139,90,43,0.2) 15px, rgba(139,90,43,0.2) 30px),
+ linear-gradient(135deg, #e8ddd0 0%, #d4c4b0 100%);
+ background-size: 100px 100px, 120px 120px, 100% 100%;
+ filter: blur(0.5px);
+}
+
+.pattern-chinoiserie {
+ background-color: #f5f2ea;
+ position: relative;
+}
+
+.pattern-chinoiserie::before {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180' viewBox='0 0 180 180'%3E%3Cg fill='none' stroke='%235a7a6a' stroke-width='1.5' stroke-opacity='0.3'%3E%3Cpath d='M40 140c20-10 30-30 35-50s5-40-5-55'/%3E%3Cpath d='M80 150c15-5 25-20 30-35s5-35-5-50'/%3E%3Cpath d='M120 145c10-15 15-35 10-55'/%3E%3Ccircle cx='60' cy='50' r='6' fill='%235a7a6a' fill-opacity='0.2' stroke='none'/%3E%3Ccircle cx='130' cy='70' r='4' fill='%235a7a6a' fill-opacity='0.2' stroke='none'/%3E%3C/g%3E%3C/svg%3E");
+}
+
+.pattern-geometric {
+ background-color: #faf9f7;
+ background-image:
+ linear-gradient(30deg, var(--accent) 12%, transparent 12.5%, transparent 87%, var(--accent) 87.5%, var(--accent)),
+ linear-gradient(150deg, var(--accent) 12%, transparent 12.5%, transparent 87%, var(--accent) 87.5%, var(--accent)),
+ linear-gradient(30deg, var(--accent) 12%, transparent 12.5%, transparent 87%, var(--accent) 87.5%, var(--accent)),
+ linear-gradient(150deg, var(--accent) 12%, transparent 12.5%, transparent 87%, var(--accent) 87.5%, var(--accent));
+ background-size: 40px 70px;
+ background-position: 0 0, 0 0, 20px 35px, 20px 35px;
+ opacity: 0.8;
+}
+
+.pattern-grasscloth {
+ background-color: #e8e4dc;
+ background-image:
+ repeating-linear-gradient(90deg, transparent, transparent 2px, rgba(139,134,120,0.15) 2px, rgba(139,134,120,0.15) 4px),
+ repeating-linear-gradient(0deg, transparent, transparent 1px, rgba(139,134,120,0.1) 1px, rgba(139,134,120,0.1) 3px);
+ position: relative;
+}
+
+.pattern-grasscloth::after {
+ content: '';
+ position: absolute;
+ inset: 0;
+ background: repeating-linear-gradient(0deg, transparent, transparent 8px, rgba(0,0,0,0.03) 8px, rgba(0,0,0,0.03) 9px);
+}
+
+/* Answer Grid */
+.answer-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 16px;
+ margin-bottom: 32px;
+}
+
+.answer-btn {
+ font-family: var(--font-ui);
+ font-size: 13px;
+ text-transform: uppercase;
+ letter-spacing: 0.12em;
+ font-weight: 500;
+ padding: 24px 32px;
+ background: var(--surface);
+ border: 1px solid var(--line);
+ color: var(--ink);
+ cursor: pointer;
+ transition: all 0.3s var(--ease-ui);
+ position: relative;
+ overflow: hidden;
+}
+
+.answer-btn:hover:not(:disabled) {
+ border-color: var(--accent);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow);
+}
+
+.answer-btn.correct {
+ background: rgba(201,169,97,0.1);
+ border-color: var(--accent);
+ color: var(--accent);
+}
+
+.answer-btn.wrong {
+ background: rgba(180,80,60,0.05);
+ border-color: rgba(180,80,60,0.3);
+ color: rgba(180,80,60,0.8);
+ animation: shake 0.4s ease-in-out;
+}
+
+.answer-btn:disabled {
+ cursor: not-allowed;
+ opacity: 0.7;
+}
+
+@keyframes shake {
+ 0%, 100% { transform: translateX(0); }
+ 25% { transform: translateX(-6px); }
+ 75% { transform: translateX(6px); }
+}
+
+/* Progress */
+.progress-bar {
+ width: 100%;
+ height: 2px;
+ background: var(--line);
+ position: relative;
+ margin-bottom: 48px;
+}
+
+.progress-fill {
+ height: 100%;
+ background: var(--accent);
+ transition: width 0.5s var(--ease-ui);
+}
+
+/* Overlay */
+.overlay {
+ position: fixed;
+ inset: 0;
+ background: rgba(245,242,234,0.95);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 200;
+ opacity: 0;
+ pointer-events: none;
+ transition: opacity 0.4s var(--ease-hero);
+}
+
+.overlay.active {
+ opacity: 1;
+ pointer-events: all;
+}
+
+.overlay-content {
+ text-align: center;
+ padding: 64px;
+ max-width: 500px;
+}
+
+.overlay h2 {
+ font-family: var(--font-display);
+ font-size: var(--text-display);
+ font-weight: 400;
+ margin-bottom: 16px;
+ color: var(--ink);
+}
+
+.overlay p {
+ font-size: var(--text-body);
+ color: var(--muted);
+ margin-bottom: 32px;
+ line-height: 1.6;
+}
+
+.final-score {
+ font-size: 64px;
+ font-weight: 300;
+ color: var(--accent);
+ margin: 24px 0;
+ line-height: 1;
+}
+
+.best-score {
+ font-size: 14px;
+ color: var(--muted);
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ margin-bottom: 40px;
+}
+
+.btn-primary {
+ font-family: var(--font-ui);
+ font-size: 12px;
+ text-transform: uppercase;
+ letter-spacing: 0.16em;
+ font-weight: 600;
+ padding: 18px 48px;
+ background: var(--ink);
+ color: var(--bg);
+ border: none;
+ cursor: pointer;
+ transition: all 0.3s var(--ease-ui);
+}
+
+.btn-primary:hover {
+ background: var(--accent);
+ color: var(--ink);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-deep);
+}
+
+/* Feedback toast */
+.feedback {
+ position: fixed;
+ top: 96px;
+ left: 50%;
+ transform: translateX(-50%) translateY(-20px);
+ padding: 16px 32px;
+ background: var(--surface);
+ border: 1px solid var(--line);
+ box-shadow: var(--shadow-deep);
+ font-size: 12px;
+ text-transform: uppercase;
+ letter-spacing: 0.12em;
+ opacity: 0;
+ pointer-events: none;
+ transition: all 0.4s var(--ease-ui);
+ z-index: 150;
+}
+
+.feedback.show {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+}
+
+.feedback.correct {
+ border-color: var(--accent);
+ color: var(--accent);
+}
+
+.feedback.wrong {
+ border-color: rgba(180,80,60,0.5);
+ color: rgba(180,80,60,0.9);
+}
+
+/* Responsive */
+@media (max-width: 768px) {
+ header {
+ padding: 0 24px;
+ height: 64px;
+ }
+
+ .wordmark {
+ font-size: 14px;
+ }
+
+ main {
+ padding: 24px;
+ }
+
+ .answer-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .stat-group {
+ gap: 16px;
+ }
+}
+</style>
+</head>
+<body>
+
+<header>
+ <div class="wordmark">Designer Wallcoverings</div>
+</header>
+
+<main>
+ <div class="stats-bar">
+ <div class="stat-group">
+ <div class="stat">
+ <span class="stat-label">Round</span>
+ <span class="stat-value" id="round">1/10</span>
+ </div>
+ <div class="stat">
+ <span class="stat-label">Score</span>
+ <span class="stat-value accent" id="score">0</span>
+ </div>
+ <div class="stat">
+ <span class="stat-label">Streak</span>
+ <span class="stat-value" id="streak">0</span>
+ </div>
+ </div>
+ <div class="stat">
+ <span class="stat-label">Time</span>
+ <span class="stat-value" id="timer">30</span>
+ </div>
+ </div>
+
+ <div class="progress-bar">
+ <div class="progress-fill" id="progress" style="width: 10%"></div>
+ </div>
+
+ <div class="pattern-stage">
+ <div class="pattern-display" id="pattern"></div>
+ </div>
+
+ <div class="answer-grid" id="answers"></div>
+</main>
+
+<div class="feedback" id="feedback"></div>
+
+<div class="overlay" id="overlay">
+ <div class="overlay-content">
+ <h2 id="end-title">Game Over</h2>
+ <div class="final-score" id="final-score">0</div>
+ <div class="best-score" id="best-score">Best: 0</div>
+ <p id="end-message">Your eye for design is impeccable.</p>
+ <button class="btn-primary" onclick="game.restart()">Play Again</button>
+ </div>
+</div>
+
+<script>
+const STYLES = ['Damask', 'Toile', 'Ikat', 'Chinoiserie', 'Geometric', 'Grasscloth'];
+const PATTERN_CLASSES = {
+ 'Damask': 'pattern-damask',
+ 'Toile': 'pattern-toile',
+ 'Ikat': 'pattern-ikat',
+ 'Chinoiserie': 'pattern-chinoiserie',
+ 'Geometric': 'pattern-geometric',
+ 'Grasscloth': 'pattern-grasscloth'
+};
+
+class Game {
+ constructor() {
+ this.round = 1;
+ this.maxRounds = 10;
+ this.score = 0;
+ this.streak = 0;
+ this.timeLeft = 30;
+ this.timer = null;
+ this.currentStyle = null;
+ this.answered = false;
+ this.bestScore = parseInt(localStorage.getItem('dw_best_score') || '0');
+
+ this.elements = {
+ round: document.getElementById('round'),
+ score: document.getElementById('score'),
+ streak: document.getElementById('streak'),
+ timer: document.getElementById('timer'),
+ progress: document.getElementById('progress'),
+ pattern: document.getElementById('pattern'),
+ answers: document.getElementById('answers'),
+ feedback: document.getElementById('feedback'),
+ overlay: document.getElementById('overlay'),
+ endTitle: document.getElementById('end-title'),
+ finalScore: document.getElementById('final-score'),
+ bestScore: document.getElementById('best-score'),
+ endMessage: document.getElementById('end-message')
+ };
+
+ this.init();
+ }
+
+ init() {
+ this.startRound();
+ }
+
+ startRound() {
+ this.answered = false;
+ this.timeLeft = 30;
+ this.updateStats();
+ this.generatePattern();
+ this.generateOptions();
+ this.startTimer();
+ }
+
+ generatePattern() {
+ this.currentStyle = STYLES[Math.floor(Math.random() * STYLES.length)];
+ this.elements.pattern.className = 'pattern-display ' + PATTERN_CLASSES[this.currentStyle];
+ }
+
+ generateOptions() {
+ const options = [this.currentStyle];
+ const remaining = STYLES.filter(s => s !== this.currentStyle);
+
+ while (options.length < 4) {
+ const idx = Math.floor(Math.random() * remaining.length);
+ options.push(remaining.splice(idx, 1)[0]);
+ }
+
+ // Shuffle
+ options.sort(() => Math.random() - 0.5);
+
+ this.elements.answers.innerHTML = '';
+ options.forEach(style => {
+ const btn = document.createElement('button');
+ btn.className = 'answer-btn';
+ btn.textContent = style;
+ btn.onclick = () => this.answer(style, btn);
+ this.elements.answers.appendChild(btn);
+ });
+ }
+
+ answer(selected, btn) {
+ if (this.answered) return;
+ this.answered = true;
+ clearInterval(this.timer);
+
+ const correct = selected === this.currentStyle;
+ const buttons = this.elements.answers.querySelectorAll('button');
+
+ buttons.forEach(b => {
+ b.disabled = true;
+ if (b.textContent === this.currentStyle) {
+ b.classList.add('correct');
+ }
+ });
+
+ if (correct) {
+ const points = Math.max(10, Math.floor(this.timeLeft * 3.33));
+ this.score += points + (this.streak * 5);
+ this.streak++;
+ btn.classList.add('correct');
+ this.showFeedback('Correct — ' + this.currentStyle, true);
+ } else {
+ this.streak = 0;
+ btn.classList.add('wrong');
+ this.showFeedback('It was ' + this.currentStyle, false);
+ }
+
+ this.updateStats();
+
+ setTimeout(() => {
+ if (this.round < this.maxRounds) {
+ this.round++;
+ this.startRound();
+ } else {
+ this.endGame();
+ }
+ }, 1500);
+ }
+
+ showFeedback(text, isCorrect) {
+ const f = this.elements.feedback;
+ f.textContent = text;
+ f.className = 'feedback show ' + (isCorrect ? 'correct' : 'wrong');
+ setTimeout(() => {
+ f.classList.remove('show');
+ }, 1200);
+ }
+
+ startTimer() {
+ this.updateTimer();
+ this.timer = setInterval(() => {
+ this.timeLeft--;
+ this.updateTimer();
+ if (this.timeLeft <= 0) {
+ this.answer('', null);
+ }
+ }, 1000);
+ }
+
+ updateTimer() {
+ this.elements.timer.textContent = this.timeLeft;
+ if (this.timeLeft <= 5) {
+ this.elements.timer.style.color = 'rgba(180,80,60,0.9)';
+ } else {
+ this.elements.timer.style.color = '';
+ }
+ }
+
+ updateStats() {
+ this.elements.round.textContent = `${this.round}/${this.maxRounds}`;
+ this.elements.score.textContent = this.score;
+ this.elements.streak.textContent = this.streak;
+ this.elements.progress.style.width = `${(this.round / this.maxRounds) * 100}%`;
+ }
+
+ endGame() {
+ clearInterval(this.timer);
+
+ if (this.score > this.bestScore) {
+ this.bestScore = this.score;
+ localStorage.setItem('dw_best_score', this.bestScore.toString());
+ }
+
+ this.elements.finalScore.textContent = this.score;
+ this.elements.bestScore.textContent = `Best Score: ${this.bestScore}`;
+
+ if (this.score >= 250) {
+ this.elements.endTitle.textContent = 'Master Curator';
+ this.elements.endMessage.textContent = 'Your eye for wallcovering is extraordinary. A true connoisseur.';
+ } else if (this.score >= 150) {
+ this.elements.endTitle.textContent = 'Design Aficionado';
+ this.elements.endMessage.textContent = 'You have a refined sense of pattern and style.';
+ } else {
+ this.elements.endTitle.textContent = 'Game Complete';
+ this.elements.endMessage.textContent = 'Each pattern tells a story. Keep exploring.';
+ }
+
+ this.elements.overlay.classList.add('active');
+ }
+
+ restart() {
+ this.round = 1;
+ this.score = 0;
+ this.streak = 0;
+ this.timeLeft = 30;
+ this.answered = false;
+ this.elements.overlay.classList.remove('active');
+ this.startRound();
+ }
+}
+
+const game = new Game();
+</script>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/kimi.png b/data/artifacts/bf0bdeb4c423/kimi.png
new file mode 100644
index 0000000..34ca999
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/kimi.png differ
diff --git a/data/artifacts/bf0bdeb4c423/qwen3-14b.html b/data/artifacts/bf0bdeb4c423/qwen3-14b.html
new file mode 100644
index 0000000..29a23e1
--- /dev/null
+++ b/data/artifacts/bf0bdeb4c423/qwen3-14b.html
@@ -0,0 +1,334 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Guess the Design Style</title>
+ <style>
+ :root {
+ --bg: #faf8f4;
+ --surface: #ffffff;
+ --ink: #1c1a17;
+ --muted: #9b948a;
+ --accent: #b0472e;
+ --line: #eae8e3;
+ --shadow: 0 8px 24px rgba(0,0,0,0.12);
+ --ease: cubic-bezier(0.22,1,0.36,1);
+ --glow: 0 0 24px rgba(176, 71, 46, 0.35);
+ --spacing: 24px;
+ --card-radius: 14px;
+ --card-gap: 24px;
+ --font-display: 'Playfair Display', Georgia, serif;
+ --font-body: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+ }
+
+ * {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ font-family: var(--font-body);
+ }
+
+ body {
+ background-color: var(--bg);
+ color: var(--ink);
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ font-size: 16px;
+ line-height: 1.6;
+ }
+
+ header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ padding: 16px 24px;
+ background-color: var(--surface);
+ font-family: var(--font-display);
+ font-size: 24px;
+ letter-spacing: 0.18em;
+ color: var(--ink);
+ display: flex;
+ align-items: center;
+ z-index: 1000;
+ }
+
+ main {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding-top: 80px;
+ padding-bottom: 80px;
+ }
+
+ #game {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--spacing);
+ }
+
+ #pattern {
+ width: 320px;
+ height: 320px;
+ background: linear-gradient(135deg, var(--accent) 25%, var(--surface) 50%, var(--accent) 75%);
+ background-size: 200% 200%;
+ animation: drift 18s linear infinite;
+ border: 1px solid var(--line);
+ box-shadow: var(--shadow);
+ border-radius: var(--card-radius);
+ position: relative;
+ }
+
+ #pattern svg {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 100%;
+ height: 100%;
+ }
+
+ .style-buttons {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: var(--card-gap);
+ width: 100%;
+ max-width: 768px;
+ padding: 0 var(--spacing);
+ }
+
+ .style-button {
+ background-color: var(--surface);
+ border: 1px solid var(--line);
+ box-shadow: var(--shadow);
+ border-radius: var(--card-radius);
+ padding: 24px;
+ cursor: pointer;
+ transition: all 0.2s var(--ease);
+ }
+
+ .style-button:hover {
+ box-shadow: 0 16px 48px rgba(0,0,0,0.18);
+ }
+
+ #overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.6);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 1000;
+ visibility: hidden;
+ opacity: 0;
+ transition: all 0.3s var(--ease);
+ }
+
+ #overlay.visible {
+ visibility: visible;
+ opacity: 1;
+ }
+
+ .overlay-content {
+ background-color: var(--surface);
+ border: 1px solid var(--line);
+ border-radius: var(--card-radius);
+ padding: 48px;
+ text-align: center;
+ box-shadow: var(--shadow);
+ max-width: 500px;
+ width: 90%;
+ }
+
+ .overlay-content h2 {
+ font-size: 28px;
+ margin-bottom: 24px;
+ color: var(--accent);
+ }
+
+ .overlay-content p {
+ font-size: 16px;
+ line-height: 1.6;
+ }
+
+ #scoreboard {
+ position: fixed;
+ top: 20px;
+ right: 20px;
+ background-color: var(--surface);
+ border: 1px solid var(--line);
+ border-radius: var(--card-radius);
+ padding: 12px 24px;
+ box-shadow: var(--shadow);
+ font-size: 12px;
+ letter-spacing: 0.15em;
+ text-transform: uppercase;
+ color: var(--muted);
+ }
+
+ @keyframes drift {
+ 0% { background-position: 0% 50%; }
+ 100% { background-position: 100% 50%; }
+ }
+
+ @keyframes fadeUp {
+ from {
+ opacity: 0;
+ transform: translateY(28px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+ }
+
+ .fade-in {
+ animation: fadeUp 0.7s var(--ease) forwards;
+ }
+ </style>
+</head>
+<body>
+ <header>
+ DESIGNER WALLCOVERINGS
+ </header>
+
+ <main>
+ <div id="scoreboard">
+ Score: <span id="score">0</span> | Streak: <span id="streak">0</span> | Round: <span id="round">1</span>/10
+ </div>
+
+ <div id="game">
+ <div id="pattern">
+ <svg viewBox="0 0 320 320" preserveAspectRatio="xMidYMid slice">
+ <defs>
+ <pattern id="damask" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
+ <path d="M 0 0 L 100 0 L 100 100 L 0 100 Z" fill="none" stroke="var(--accent)" stroke-width="1"/>
+ </pattern>
+ <pattern id="toile" x="0" y="0" width="60" height="60" patternUnits="userSpaceOnUse">
+ <circle cx="30" cy="30" r="15" fill="var(--accent)"/>
+ <circle cx="30" cy="30" r="15" fill="url(#toile)" opacity="0.2"/>
+ </pattern>
+ <pattern id="ikat" x="0" y="0" width="120" height="120" patternUnits="userSpaceOnUse">
+ <path d="M 0 0 L 120 0 L 120 120 L 0 120 Z" fill="none" stroke="var(--accent)" stroke-width="4" stroke-dasharray="4,4"/>
+ </pattern>
+ <pattern id="chinoiserie" x="0" y="0" width="80" height="80" patternUnits="userSpaceOnUse">
+ <path d="M 10 10 C 20 30, 30 30, 40 10 S 60 10, 70 30 S 90 50, 80 70 S 60 70, 50 50 S 40 30, 30 30 S 20 30, 10 10 Z" fill="var(--accent)"/>
+ </pattern>
+ <pattern id="geometric" x="0" y="0" width="100" height="100" patternUnits="userSpaceOnUse">
+ <path d="M 0 0 L 100 0 L 100 50 L 50 50 L 50 100 L 0 100 Z" fill="var(--accent)" opacity="0.2"/>
+ </pattern>
+ <pattern id="grasscloth" x="0" y="0" width="120" height="120" patternUnits="userSpaceOnUse">
+ <path d="M 0 0 L 120 0 L 120 60 L 0 60 Z" fill="var(--accent)" opacity="0.4"/>
+ <path d="M 0 60 L 120 60 L 120 120 L 0 120 Z" fill="var(--surface)" opacity="0.6"/>
+ </pattern>
+ </defs>
+ </svg>
+ </div>
+
+ <div class="style-buttons" id="style-buttons">
+ <button class="style-button" data-style="damask"></button>
+ <button class="style-button" data-style="toile"></button>
+ <button class="style-button" data-style="ikat"></button>
+ <button class="style-button" data-style="chinoiserie"></button>
+ <button class="style-button" data-style="geometric"></button>
+ <button class="style-button" data-style="grasscloth"></button>
+ </div>
+ </div>
+
+ <div id="overlay">
+ <div class="overlay-content fade-in" id="overlay-content">
+ <h2 id="overlay-title">Correct!</h2>
+ <p id="overlay-message">Well done! You've guessed the design style.</p>
+ </div>
+ </div>
+ </main>
+
+ <script>
+ const styles = ["damask", "toile", "ikat", "chinoiserie", "geometric", "grasscloth"];
+ const patternElement = document.getElementById('pattern');
+ const styleButtons = document.querySelectorAll('.style-button');
+ const overlay = document.getElementById('overlay');
+ const overlayContent = document.getElementById('overlay-content');
+ const overlayTitle = document.getElementById('overlay-title');
+ const overlayMessage = document.getElementById('overlay-message');
+ const scoreboard = document.getElementById('scoreboard');
+ const scoreDisplay = document.getElementById('score');
+ const streakDisplay = document.getElementById('streak');
+ const roundDisplay = document.getElementById('round');
+
+ let currentStyle = '';
+ let score = 0;
+ let streak = 0;
+ let round = 1;
+ let bestScore = parseInt(localStorage.getItem('bestScore')) || 0;
+
+ function getRandomStyle() {
+ return styles[Math.floor(Math.random() * styles.length)];
+ }
+
+ function updateUI() {
+ const style = getRandomStyle();
+ currentStyle = style;
+ patternElement.style.backgroundImage = `url(#${style})`;
+ patternElement.style.backgroundSize = 'contain';
+ }
+
+ function updateScoreboard() {
+ scoreDisplay.textContent = score;
+ streakDisplay.textContent = streak;
+ roundDisplay.textContent = `${round}/10`;
+ if (score > bestScore) {
+ bestScore = score;
+ localStorage.setItem('bestScore', bestScore);
+ }
+ }
+
+ function showOverlay(title, message) {
+ overlayTitle.textContent = title;
+ overlayMessage.textContent = message;
+ overlay.classList.add('visible');
+ setTimeout(() => {
+ overlay.classList.remove('visible');
+ }, 1500);
+ }
+
+ function endGame() {
+ overlayTitle.textContent = "Game Over!";
+ overlayMessage.textContent = `Your final score: ${score}. Best score: ${bestScore}.`;
+ overlay.classList.add('visible');
+ document.querySelectorAll('.style-button').forEach(btn => btn.disabled = true);
+ }
+
+ styleButtons.forEach(button => {
+ button.addEventListener('click', () => {
+ const selectedStyle = button.getAttribute('data-style');
+ if (selectedStyle === currentStyle) {
+ score++;
+ streak++;
+ showOverlay("Correct!", "Well done! You've guessed the design style.");
+ } else {
+ streak = 0;
+ showOverlay("Wrong!", "Try again next round.");
+ }
+ round++;
+ updateScoreboard();
+ if (round > 10) {
+ endGame();
+ } else {
+ updateUI();
+ }
+ });
+ });
+
+ updateUI();
+ updateScoreboard();
+ </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/bf0bdeb4c423/qwen3-14b.png b/data/artifacts/bf0bdeb4c423/qwen3-14b.png
new file mode 100644
index 0000000..e2aa2bf
Binary files /dev/null and b/data/artifacts/bf0bdeb4c423/qwen3-14b.png differ
diff --git a/data/challenges.json b/data/challenges.json
index 29018eb..9556658 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -15211,13 +15211,13 @@
"queued_at": "2026-07-25T07:49:49.661Z",
"bytes": 7000,
"thumb": true,
- "aiScore": 6.8,
- "aiReason": "The simulation works well but lacks polish and visual quality in terms of color variety and smoothness.",
+ "aiScore": 7.5,
+ "aiReason": "The page is interactive and fulfills the challenge requirements well. The visual quality is good but could be slightly improved for a perfect score.",
"aiScores": {
- "qwen2.5vl:7b": 7,
- "minicpm-v:latest": 6.5
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 6
},
- "aiSpread": 0.5
+ "aiSpread": 3
},
{
"model": "hermes3-8b",
@@ -15230,13 +15230,13 @@
"queued_at": "2026-07-25T07:49:49.668Z",
"bytes": 6124,
"thumb": true,
- "aiScore": 6.8,
- "aiReason": "The simulation is functional but lacks polish and visual quality.",
+ "aiScore": 7.5,
+ "aiReason": "The model fulfills the challenge well and has good visual quality.",
"aiScores": {
- "qwen2.5vl:7b": 7,
- "minicpm-v:latest": 6.5
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 6
},
- "aiSpread": 0.5
+ "aiSpread": 3
},
{
"model": "qwen25-7b",
@@ -15248,7 +15248,14 @@
"finished_at": "2026-07-25T07:51:08.941Z",
"queued_at": "2026-07-25T07:49:49.674Z",
"bytes": 6107,
- "thumb": true
+ "thumb": true,
+ "aiScore": 7.5,
+ "aiReason": "The page is interactive and fulfills the challenge requirements well. The visual quality is good but could be improved further.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 6
+ },
+ "aiSpread": 3
},
{
"model": "hf-qwen-coder-32b",
@@ -15260,12 +15267,20 @@
"finished_at": "2026-07-25T08:04:14.401Z",
"queued_at": "2026-07-25T07:49:49.677Z",
"bytes": 6050,
- "thumb": true
+ "thumb": true,
+ "aiScore": 7.8,
+ "aiReason": "The page is visually appealing and fulfills the challenge requirements effectively.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 6.5
+ },
+ "aiSpread": 2.5
}
],
- "judging": true,
+ "judging": false,
"category": "Custom",
- "judged_at": null
+ "judged_at": "2026-07-25T12:33:51.326Z",
+ "aiPick": "hf-qwen-coder-32b"
},
{
"id": "028885e12558",
@@ -23935,27 +23950,52 @@
"finished_at": "2026-07-25T12:25:19.543Z",
"queued_at": "2026-07-25T12:24:18.202Z",
"bytes": 7101,
- "thumb": true
+ "thumb": true,
+ "aiScore": 8.3,
+ "aiReason": "The HTML file effectively fulfills the challenge requirements and presents a visually appealing seasonal wallcovering color story.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 7.5
+ },
+ "aiSpread": 1.5
},
{
"model": "gemma3-12b",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 53,
+ "cost": 0,
"started_at": "2026-07-25T12:25:19.553Z",
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.209Z"
+ "finished_at": "2026-07-25T12:26:12.621Z",
+ "queued_at": "2026-07-25T12:24:18.209Z",
+ "bytes": 6102,
+ "thumb": true,
+ "aiScore": 9.3,
+ "aiReason": "The HTML file meets all the requirements and presents a visually appealing seasonal wallcovering color story with a polished design.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 9.5
+ },
+ "aiSpread": 0.5
},
{
"model": "hermes3-8b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.218Z"
+ "seconds": 23,
+ "cost": 0,
+ "started_at": "2026-07-25T12:26:12.634Z",
+ "finished_at": "2026-07-25T12:26:35.154Z",
+ "queued_at": "2026-07-25T12:24:18.218Z",
+ "bytes": 5044,
+ "thumb": true,
+ "aiScore": 8.3,
+ "aiReason": "The HTML file effectively fulfills the challenge requirements and presents a visually appealing seasonal wallcovering color story.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 7.5
+ },
+ "aiSpread": 1.5
},
{
"model": "qwen25-7b",
@@ -23967,17 +24007,33 @@
"finished_at": "2026-07-25T12:24:51.257Z",
"queued_at": "2026-07-25T12:24:18.225Z",
"bytes": 4634,
- "thumb": true
+ "thumb": true,
+ "aiScore": 7.3,
+ "aiReason": "The HTML file meets most of the requirements but lacks some visual elements and does not fully utilize CSS gradients or inline SVG for patterns.",
+ "aiScores": {
+ "qwen2.5vl:7b": 7,
+ "minicpm-v:latest": 7.5
+ },
+ "aiSpread": 0.5
},
{
"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-25T12:24:18.229Z"
+ "seconds": 72,
+ "cost": 0,
+ "started_at": "2026-07-25T12:26:35.163Z",
+ "finished_at": "2026-07-25T12:27:46.705Z",
+ "queued_at": "2026-07-25T12:24:18.229Z",
+ "bytes": 5603,
+ "thumb": true,
+ "aiScore": 6.3,
+ "aiReason": "The design is visually appealing and fulfills most of the requirements, but it lacks some motion effects and could benefit from more refined typography.",
+ "aiScores": {
+ "qwen2.5vl:7b": 7,
+ "minicpm-v:latest": 5.5
+ },
+ "aiSpread": 1.5
},
{
"model": "claude-code",
@@ -23993,13 +24049,22 @@
},
{
"model": "kimi",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 103,
+ "cost": 0.0193,
"started_at": "2026-07-25T12:24:18.258Z",
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.236Z"
+ "finished_at": "2026-07-25T12:26:01.131Z",
+ "queued_at": "2026-07-25T12:24:18.236Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes",
+ "hyperframes",
+ "opendesign"
+ ],
+ "bytes": 17969,
+ "thumb": true
},
{
"model": "gpt",
@@ -24032,9 +24097,11 @@
"opendesign",
"hyperframes"
],
- "bytes": 21926
+ "bytes": 21926,
+ "thumb": true
}
- ]
+ ],
+ "judging": true
},
{
"id": "bf0bdeb4c423",
@@ -24047,33 +24114,60 @@
"runs": [
{
"model": "qwen3-14b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.301Z"
+ "seconds": 70,
+ "cost": 0,
+ "started_at": "2026-07-25T12:27:46.709Z",
+ "finished_at": "2026-07-25T12:28:56.383Z",
+ "queued_at": "2026-07-25T12:24:18.301Z",
+ "bytes": 9778,
+ "thumb": true,
+ "aiScore": 6.8,
+ "aiReason": "The design is visually appealing and follows the luxury UI requirements well, but some elements like the buttons could be more refined in terms of spacing and alignment.",
+ "aiScores": {
+ "qwen2.5vl:7b": 7,
+ "minicpm-v:latest": 6.5
+ },
+ "aiSpread": 0.5
},
{
"model": "gemma3-12b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.305Z"
+ "seconds": 89,
+ "cost": 0,
+ "started_at": "2026-07-25T12:28:56.391Z",
+ "finished_at": "2026-07-25T12:30:25.800Z",
+ "queued_at": "2026-07-25T12:24:18.305Z",
+ "bytes": 10454,
+ "thumb": true,
+ "aiScore": 8.3,
+ "aiReason": "The HTML file is well-structured and fulfills all the requirements of the challenge. The design style is correctly identified as Geometric, with a refined luxury palette and appropriate UI elements.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 7.5
+ },
+ "aiSpread": 1.5
},
{
"model": "hermes3-8b",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.309Z"
+ "seconds": 27,
+ "cost": 0,
+ "started_at": "2026-07-25T12:30:25.811Z",
+ "finished_at": "2026-07-25T12:30:52.757Z",
+ "queued_at": "2026-07-25T12:24:18.309Z",
+ "bytes": 8024,
+ "thumb": true,
+ "aiScore": 6.8,
+ "aiReason": "The HTML fulfills the challenge requirements but lacks some visual flair and refinement in design elements.",
+ "aiScores": {
+ "qwen2.5vl:7b": 7,
+ "minicpm-v:latest": 6.5
+ },
+ "aiSpread": 0.5
},
{
"model": "qwen25-7b",
@@ -24085,58 +24179,98 @@
"finished_at": "2026-07-25T12:25:33.359Z",
"queued_at": "2026-07-25T12:24:18.313Z",
"bytes": 5109,
- "thumb": true
+ "thumb": true,
+ "aiScore": 6.8,
+ "aiReason": "The design is visually appealing and adheres to the luxury UI requirements. However, some elements like the button styles could be more refined for a polished look.",
+ "aiScores": {
+ "qwen2.5vl:7b": 7,
+ "minicpm-v:latest": 6.5
+ },
+ "aiSpread": 0.5
},
{
"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-25T12:24:18.317Z"
+ "seconds": 110,
+ "cost": 0,
+ "started_at": "2026-07-25T12:30:52.769Z",
+ "finished_at": "2026-07-25T12:32:42.493Z",
+ "queued_at": "2026-07-25T12:24:18.317Z",
+ "bytes": 9388,
+ "thumb": true,
+ "aiScore": 8.3,
+ "aiReason": "The HTML file meets all the requirements and has a polished visual quality.",
+ "aiScores": {
+ "qwen2.5vl:7b": 9,
+ "minicpm-v:latest": 7.5
+ },
+ "aiSpread": 1.5
},
{
"model": "claude-code",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 120,
+ "cost": 0,
"started_at": "2026-07-25T12:25:33.450Z",
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.321Z"
+ "finished_at": "2026-07-25T12:27:33.157Z",
+ "queued_at": "2026-07-25T12:24:18.321Z",
+ "bytes": 25968,
+ "thumb": true
},
{
"model": "kimi",
- "status": "queued",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
- "started_at": null,
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.324Z"
+ "seconds": 103,
+ "cost": 0.0179,
+ "started_at": "2026-07-25T12:26:01.151Z",
+ "finished_at": "2026-07-25T12:27:44.174Z",
+ "queued_at": "2026-07-25T12:24:18.324Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 17322,
+ "thumb": true
},
{
"model": "gpt",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 87,
+ "cost": 0.1486,
"started_at": "2026-07-25T12:25:15.317Z",
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.328Z"
+ "finished_at": "2026-07-25T12:26:42.377Z",
+ "queued_at": "2026-07-25T12:24:18.328Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 32680,
+ "thumb": true
},
{
"model": "grok",
- "status": "running",
+ "status": "done",
"error": null,
- "seconds": null,
- "cost": null,
+ "seconds": 195,
+ "cost": 0.2433,
"started_at": "2026-07-25T12:25:52.633Z",
- "finished_at": null,
- "queued_at": "2026-07-25T12:24:18.332Z"
+ "finished_at": "2026-07-25T12:29:07.546Z",
+ "queued_at": "2026-07-25T12:24:18.332Z",
+ "toolCalls": [
+ "opendesign",
+ "opendesign",
+ "hyperframes"
+ ],
+ "bytes": 43226,
+ "thumb": true
}
- ]
+ ],
+ "judging": true
}
]
\ No newline at end of file
diff --git a/data/costlog.jsonl b/data/costlog.jsonl
index 6c6ab0c..e8e409d 100644
--- a/data/costlog.jsonl
+++ b/data/costlog.jsonl
@@ -329,3 +329,7 @@
{"ts":"2026-07-25T12:15:48.332Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena-tools","input_tokens":3472,"output_tokens":11514,"cost_usd":0.030868}
{"ts":"2026-07-25T12:25:15.290Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":3255,"output_tokens":7324,"cost_usd":0.108232}
{"ts":"2026-07-25T12:25:52.620Z","provider":"xai","model":"grok-4.5","task":"model-arena-tools","input_tokens":4389,"output_tokens":7486,"cost_usd":0.125457}
+{"ts":"2026-07-25T12:26:01.127Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena-tools","input_tokens":6284,"output_tokens":6196,"cost_usd":0.01926}
+{"ts":"2026-07-25T12:26:42.374Z","provider":"openai","model":"gpt-5.1","task":"model-arena-tools","input_tokens":3229,"output_tokens":10212,"cost_usd":0.148619}
+{"ts":"2026-07-25T12:27:44.170Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena-tools","input_tokens":3603,"output_tokens":6305,"cost_usd":0.017924}
+{"ts":"2026-07-25T12:29:07.544Z","provider":"xai","model":"grok-4.5","task":"model-arena-tools","input_tokens":3971,"output_tokens":15424,"cost_usd":0.243273}
← 28d8f03 Shell: mandate darkest-ink wordmark color (never var(--surfa
·
back to Model Arena
·
night-loop: cycle 05:36 — judged=172f180e3161 · fired 2 →; F 3c06c80 →