[object Object]

← back to Model Arena

complete five Grateful Dead gallery challenges

dd56f03757ad029c2a27022c1287fc5a8f1d2e85 · 2026-09-01 13:14:24 -0700 · Steve Abrams

Files touched

Diff

commit dd56f03757ad029c2a27022c1287fc5a8f1d2e85
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Sep 1 13:14:24 2026 -0700

    complete five Grateful Dead gallery challenges
---
 data/artifacts/4c73c905dfd0/claude-code.html | 845 ++++++++++++++++++++++++
 data/artifacts/4c73c905dfd0/claude-code.png  | Bin 0 -> 70338 bytes
 data/artifacts/4c73c905dfd0/qwen25-7b.html   |  92 +++
 data/artifacts/4c73c905dfd0/qwen3-14b.html   | 328 ++++++++++
 data/artifacts/6d9acbcfa9a2/claude-code.html | 924 +++++++++++++++++++++++++++
 data/artifacts/6d9acbcfa9a2/claude-code.png  | Bin 0 -> 238461 bytes
 data/artifacts/6d9acbcfa9a2/qwen25-7b.html   | 141 ++++
 data/artifacts/6d9acbcfa9a2/qwen3-14b.html   | 340 ++++++++++
 data/artifacts/a5990564b1ee/claude-code.html | 837 ++++++++++++++++++++++++
 data/artifacts/a5990564b1ee/qwen25-7b.html   | 131 ++++
 data/artifacts/a5990564b1ee/qwen3-14b.html   | 289 +++++++++
 data/artifacts/b05597bd9f5a/claude-code.html | 768 ++++++++++++++++++++++
 data/artifacts/b05597bd9f5a/qwen25-7b.html   |  81 +++
 data/artifacts/b05597bd9f5a/qwen3-14b.html   | 417 ++++++++++++
 data/artifacts/f6e40f30be85/claude-code.html | 796 +++++++++++++++++++++++
 data/artifacts/f6e40f30be85/qwen25-7b.html   | 154 +++++
 data/artifacts/f6e40f30be85/qwen3-14b.html   | 350 ++++++++++
 data/challenges.json                         |  86 ++-
 verification/grateful-dead-five-live.png     | Bin 0 -> 7458268 bytes
 verification/grateful-dead-five-proof.json   |  48 ++
 verification/grateful-dead-five.e2e.js       |  56 ++
 21 files changed, 6666 insertions(+), 17 deletions(-)

diff --git a/data/artifacts/4c73c905dfd0/claude-code.html b/data/artifacts/4c73c905dfd0/claude-code.html
new file mode 100644
index 0000000..a4a66ca
--- /dev/null
+++ b/data/artifacts/4c73c905dfd0/claude-code.html
@@ -0,0 +1,845 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Objects in the Golden Road — A Collector Catalog</title>
+<style>
+  :root{
+    --ivory:#f6f2ea;
+    --ivory-2:#efe9dd;
+    --surface:#fffdf8;
+    --ink:#1a1713;
+    --ink-soft:#3b352d;
+    --muted:#928b7c;
+    --muted-2:#b6ad9c;
+    --gold:#9a7b3f;
+    --gold-lit:#c2a05e;
+    --gold-ox:#7d6a45;
+    --rose:#c58a83;
+    --rose-deep:#a5645d;
+    --line:#ddd4c2;
+    --shadow:0 8px 24px rgba(40,32,18,.12);
+    --shadow-hi:0 18px 52px rgba(40,32,18,.20);
+    --sp-1:4px;--sp-2:8px;--sp-3:12px;--sp-4:16px;--sp-6:24px;--sp-8:32px;--sp-12:48px;--sp-16:64px;--sp-24:96px;
+    --serif:'Didot','Bodoni MT','Playfair Display',Georgia,'Times New Roman',serif;
+    --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+    --ease:cubic-bezier(.22,1,.36,1);
+  }
+  *{box-sizing:border-box}
+  html{scroll-behavior:smooth}
+  body{
+    margin:0;background:var(--ivory);color:var(--ink);font-family:var(--sans);
+    font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased;
+    background-image:
+      radial-gradient(1200px 600px at 80% -10%, rgba(197,138,131,.06), transparent 60%),
+      radial-gradient(1000px 700px at -10% 20%, rgba(154,123,63,.05), transparent 55%);
+  }
+  ::selection{background:rgba(197,138,131,.28)}
+  a{color:inherit}
+  img{max-width:100%}
+  .wrap{max-width:1200px;margin:0 auto;padding:0 var(--sp-6)}
+  .cap{font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);font-weight:600}
+  .serif{font-family:var(--serif)}
+  .rule{height:1px;border:0;background:linear-gradient(90deg,transparent,var(--gold-ox),var(--gold-lit),var(--gold-ox),transparent);opacity:.7;margin:var(--sp-8) 0}
+  .prism{background:linear-gradient(90deg,#c58a83,#c2a05e,#8fae94,#7fa6c4,#a98bbd,#c58a83);background-size:300% 100%}
+
+  /* focus */
+  :focus-visible{outline:2px solid var(--rose-deep);outline-offset:3px;border-radius:2px}
+  .skip{position:absolute;left:-999px;top:0;background:var(--ink);color:var(--ivory);padding:10px 16px;z-index:200}
+  .skip:focus{left:12px;top:12px}
+
+  /* ---------- Header ---------- */
+  header.masthead{position:relative;overflow:hidden;border-bottom:1px solid var(--line)}
+  .mast-bar{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-4);padding:var(--sp-4) var(--sp-6);max-width:1200px;margin:0 auto}
+  .institution{font-size:11px;letter-spacing:.28em;text-transform:uppercase;color:var(--gold-ox);font-weight:700}
+  .mast-tools{display:flex;gap:var(--sp-2);flex-wrap:wrap}
+  .hero{max-width:1200px;margin:0 auto;padding:var(--sp-16) var(--sp-6) var(--sp-12)}
+  .hero .eyebrow{margin-bottom:var(--sp-4)}
+  .hero h1{font-family:var(--serif);font-weight:400;font-size:clamp(42px,8vw,88px);line-height:.98;letter-spacing:-.01em;margin:0 0 var(--sp-6);max-width:14ch}
+  .hero h1 em{font-style:italic;color:var(--rose-deep)}
+  .hero .lede{font-size:clamp(17px,2.2vw,21px);max-width:60ch;color:var(--ink-soft);line-height:1.7}
+  .hero .meta-row{display:flex;gap:var(--sp-8);flex-wrap:wrap;margin-top:var(--sp-8);padding-top:var(--sp-6);border-top:1px solid var(--line)}
+  .hero .meta-row div{min-width:120px}
+  .hero .meta-row strong{display:block;font-family:var(--serif);font-size:20px;font-weight:500;margin-top:2px}
+  .prism-thread{position:absolute;top:0;right:8%;width:2px;height:100%;opacity:.5;animation:drift 18s var(--ease) infinite alternate}
+  @keyframes drift{from{background-position:0% 0}to{background-position:100% 0}}
+
+  /* ---------- Controls ---------- */
+  .controls{position:sticky;top:0;z-index:40;background:rgba(246,242,234,.86);backdrop-filter:saturate(140%) blur(10px);border-bottom:1px solid var(--line)}
+  .controls-inner{display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);padding:var(--sp-3) var(--sp-6);max-width:1200px;margin:0 auto;flex-wrap:wrap}
+  .seg{display:inline-flex;border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--surface)}
+  .seg button{border:0;background:transparent;padding:9px 14px;font:inherit;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);cursor:pointer;transition:all .18s var(--ease)}
+  .seg button[aria-pressed="true"]{background:var(--ink);color:var(--ivory)}
+  .field{display:flex;align-items:center;gap:var(--sp-2)}
+  .field label{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);font-weight:600}
+  select,input[type="search"]{font:inherit;font-size:14px;padding:8px 12px;border:1px solid var(--line);border-radius:9px;background:var(--surface);color:var(--ink)}
+  input[type="search"]{min-width:180px}
+  .btn{font:inherit;font-size:12px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:9px 14px;border:1px solid var(--gold-ox);border-radius:10px;background:var(--surface);color:var(--ink-soft);cursor:pointer;transition:all .2s var(--ease)}
+  .btn:hover{background:var(--ink);color:var(--ivory);border-color:var(--ink);transform:translateY(-1px)}
+  .btn.ghost{border-color:var(--line)}
+  .btn:disabled{opacity:.4;cursor:not-allowed;transform:none}
+  .count-pill{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
+
+  /* ---------- Grid ---------- */
+  main{padding:var(--sp-12) 0 160px}
+  .section-head{display:flex;align-items:baseline;justify-content:space-between;gap:var(--sp-4);margin-bottom:var(--sp-8);flex-wrap:wrap}
+  .section-head h2{font-family:var(--serif);font-weight:400;font-size:clamp(26px,4vw,38px);margin:0}
+  .gallery{display:grid;gap:var(--sp-6)}
+  .gallery.grid{grid-template-columns:repeat(auto-fill,minmax(300px,1fr))}
+  .gallery.list{grid-template-columns:1fr}
+
+  .card{background:var(--surface);border:1px solid var(--line);border-radius:14px;overflow:hidden;box-shadow:var(--shadow);transition:transform .3s var(--ease),box-shadow .3s var(--ease);display:flex;flex-direction:column;animation:fadeUp .7s var(--ease) both}
+  @keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
+  .card:hover{transform:translateY(-4px);box-shadow:var(--shadow-hi)}
+  .plate{position:relative;background:linear-gradient(160deg,#fffdf8,#f0ead d);aspect-ratio:4/3;display:block;width:100%;border:0;padding:0;cursor:zoom-in;overflow:hidden}
+  .plate svg{display:block;width:100%;height:100%}
+  .plate .accn{position:absolute;left:12px;bottom:10px;font-size:10px;letter-spacing:.14em;color:var(--gold-ox);background:rgba(255,253,248,.82);padding:3px 8px;border-radius:20px;font-weight:700}
+  .plate .zoomhint{position:absolute;right:12px;bottom:10px;font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);opacity:0;transition:opacity .25s}
+  .plate:hover .zoomhint,.plate:focus .zoomhint{opacity:1}
+  .card-body{padding:var(--sp-6);display:flex;flex-direction:column;gap:var(--sp-3);flex:1}
+  .card-body h3{font-family:var(--serif);font-weight:500;font-size:23px;line-height:1.15;margin:0}
+  .card-body .obj-type{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--rose-deep);font-weight:700}
+  .card-body .dates{font-size:13px;color:var(--muted)}
+  .card-body .snip{font-size:14px;color:var(--ink-soft);line-height:1.65;margin:0}
+  .card-actions{display:flex;gap:var(--sp-2);margin-top:auto;padding-top:var(--sp-3);flex-wrap:wrap}
+  .chip{font:inherit;font-size:11px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:6px 11px;border:1px solid var(--line);border-radius:20px;background:transparent;color:var(--muted);cursor:pointer;transition:all .18s var(--ease)}
+  .chip:hover{border-color:var(--gold-ox);color:var(--ink)}
+  .chip[aria-pressed="true"]{background:var(--rose);border-color:var(--rose);color:#fff}
+  .chip.saved[aria-pressed="true"]{background:var(--gold);border-color:var(--gold)}
+
+  /* list view specifics */
+  .gallery.list .card{flex-direction:row;align-items:stretch}
+  .gallery.list .plate{width:280px;flex:0 0 280px;aspect-ratio:auto}
+  .gallery.list .card-body{padding:var(--sp-8)}
+  .gallery.list .snip{max-width:70ch}
+  .specs-inline{display:none}
+  .gallery.list .specs-inline{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--sp-3) var(--sp-6);margin-top:var(--sp-2)}
+  .gallery.list .specs-inline div{font-size:12.5px}
+  .specs-inline dt{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:700}
+  .specs-inline dd{margin:2px 0 0;color:var(--ink-soft)}
+
+  /* ---------- Glossary ---------- */
+  .glossary{margin-top:var(--sp-24)}
+  .gloss-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--sp-6);margin-top:var(--sp-8)}
+  .gloss-item{border-left:2px solid var(--gold-ox);padding:var(--sp-2) 0 var(--sp-2) var(--sp-6)}
+  .gloss-item dt{font-family:var(--serif);font-size:19px;margin-bottom:var(--sp-1)}
+  .gloss-item dd{margin:0;color:var(--ink-soft);font-size:14.5px;line-height:1.6}
+
+  footer{border-top:1px solid var(--line);margin-top:var(--sp-24);padding:var(--sp-12) 0}
+  footer .wrap{display:flex;justify-content:space-between;gap:var(--sp-8);flex-wrap:wrap;color:var(--muted);font-size:13px}
+
+  /* ---------- Modal ---------- */
+  .overlay{position:fixed;inset:0;z-index:100;background:rgba(26,23,19,.55);backdrop-filter:blur(4px);display:none;align-items:flex-start;justify-content:center;padding:var(--sp-8) var(--sp-4);overflow-y:auto}
+  .overlay.open{display:flex;animation:fadeIn .3s var(--ease)}
+  @keyframes fadeIn{from{opacity:0}to{opacity:1}}
+  .dialog{background:var(--ivory);border:1px solid var(--line);border-radius:16px;max-width:1040px;width:100%;box-shadow:var(--shadow-hi);animation:fadeUp .5s var(--ease) both;overflow:hidden}
+  .dialog-top{display:flex;justify-content:space-between;align-items:center;padding:var(--sp-4) var(--sp-6);border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--ivory);z-index:2}
+  .dialog-top .accn{font-size:11px;letter-spacing:.16em;color:var(--gold-ox);font-weight:700}
+  .close{border:1px solid var(--line);background:var(--surface);width:38px;height:38px;border-radius:50%;font-size:18px;cursor:pointer;line-height:1;color:var(--ink);transition:all .2s var(--ease)}
+  .close:hover{background:var(--ink);color:var(--ivory);transform:rotate(90deg)}
+  .detail{display:grid;grid-template-columns:1.15fr 1fr;gap:0}
+  .detail-visual{background:linear-gradient(160deg,#fffdf8,#ece5d6);padding:var(--sp-8);display:flex;flex-direction:column;gap:var(--sp-4);border-right:1px solid var(--line)}
+  .zoom-stage{position:relative;background:var(--surface);border:1px solid var(--line);border-radius:12px;overflow:hidden;aspect-ratio:4/3;box-shadow:inset 0 0 0 8px #fff, inset 0 0 40px rgba(0,0,0,.05)}
+  .zoom-stage .frame{position:absolute;inset:0;transition:transform .25s var(--ease);transform-origin:center center}
+  .zoom-stage svg{width:100%;height:100%;display:block}
+  .zoom-controls{display:flex;align-items:center;gap:var(--sp-3)}
+  .zoom-controls input[type=range]{flex:1;accent-color:var(--rose-deep)}
+  .zoom-controls .zval{font-size:12px;color:var(--muted);min-width:44px;text-align:right;font-variant-numeric:tabular-nums}
+  .detail-info{padding:var(--sp-8);overflow-y:auto}
+  .detail-info .obj-type{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--rose-deep);font-weight:700}
+  .detail-info h2{font-family:var(--serif);font-weight:400;font-size:clamp(28px,4vw,40px);margin:var(--sp-2) 0 var(--sp-4);line-height:1.05}
+  .spec-table{width:100%;border-collapse:collapse;margin:var(--sp-4) 0}
+  .spec-table th,.spec-table td{text-align:left;padding:var(--sp-3) 0;border-bottom:1px solid var(--line);vertical-align:top;font-size:14px}
+  .spec-table th{width:38%;font-weight:600;font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);padding-right:var(--sp-4)}
+  .spec-table td{color:var(--ink-soft)}
+  .curator{margin-top:var(--sp-6);padding-top:var(--sp-6);border-top:1px solid var(--gold-ox)}
+  .curator .cap{margin-bottom:var(--sp-3);display:block}
+  .curator p{font-family:var(--serif);font-size:18px;line-height:1.7;color:var(--ink);font-style:italic;margin:0}
+  .curator .signoff{font-style:normal;font-family:var(--sans);font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-top:var(--sp-4)}
+  .detail-actions{display:flex;gap:var(--sp-2);margin-top:var(--sp-6);flex-wrap:wrap}
+
+  /* comparison */
+  .compare-grid{display:grid;gap:0;grid-template-columns:180px repeat(var(--cols,2),1fr)}
+  .compare-grid .cc{padding:var(--sp-4) var(--sp-4);border-bottom:1px solid var(--line);font-size:13.5px}
+  .compare-grid .rowlabel{font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted);font-weight:700;background:var(--ivory-2)}
+  .compare-grid .head{background:var(--ivory-2);border-bottom:2px solid var(--gold-ox)}
+  .compare-grid .head .miniplate{aspect-ratio:4/3;border-radius:8px;overflow:hidden;border:1px solid var(--line);margin-bottom:var(--sp-2)}
+  .compare-grid .head h4{font-family:var(--serif);font-weight:500;font-size:17px;margin:0}
+  .compare-empty{padding:var(--sp-16) var(--sp-8);text-align:center;color:var(--muted)}
+
+  /* ---------- Saved tray ---------- */
+  .tray{position:fixed;left:0;right:0;bottom:0;z-index:60;background:var(--ink);color:var(--ivory);transform:translateY(100%);transition:transform .4s var(--ease)}
+  .tray.show{transform:translateY(0)}
+  .tray-inner{max-width:1200px;margin:0 auto;padding:var(--sp-3) var(--sp-6);display:flex;align-items:center;gap:var(--sp-4);flex-wrap:wrap}
+  .tray-inner .tlabel{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--gold-lit);font-weight:700}
+  .tray-items{display:flex;gap:var(--sp-2);flex:1;flex-wrap:wrap;align-items:center}
+  .tray-item{display:flex;align-items:center;gap:8px;background:rgba(255,253,248,.09);border:1px solid rgba(255,253,248,.18);border-radius:24px;padding:5px 6px 5px 12px;font-size:12px}
+  .tray-item .tmini{width:30px;height:24px;border-radius:5px;overflow:hidden;border:1px solid rgba(255,255,255,.2)}
+  .tray-item .tmini svg{width:100%;height:100%;display:block}
+  .tray-item button{background:transparent;border:0;color:var(--rose);cursor:pointer;font-size:16px;line-height:1;padding:0 4px}
+  .tray-tools{display:flex;gap:var(--sp-2)}
+  .tray .btn{border-color:rgba(255,253,248,.3);color:var(--ivory);background:transparent}
+  .tray .btn:hover{background:var(--ivory);color:var(--ink)}
+
+  /* ---------- responsive ---------- */
+  @media(max-width:860px){
+    .detail{grid-template-columns:1fr}
+    .detail-visual{border-right:0;border-bottom:1px solid var(--line)}
+    .gallery.list .card{flex-direction:column}
+    .gallery.list .plate{width:100%;flex:none;aspect-ratio:4/3}
+    .compare-grid{grid-template-columns:120px repeat(var(--cols,2),1fr)}
+  }
+  @media(max-width:560px){
+    .controls-inner{gap:var(--sp-2)}
+    input[type="search"]{min-width:0;width:140px}
+    .hero{padding-top:var(--sp-12)}
+  }
+
+  /* ---------- print ---------- */
+  @media print{
+    :root{--ivory:#fff;--surface:#fff}
+    .controls,.tray,.mast-tools,.card-actions,.chip,.zoomhint,.plate{cursor:auto}
+    .controls,.tray,.mast-tools,.overlay{display:none !important}
+    body{background:#fff}
+    .card{break-inside:avoid;box-shadow:none;border:1px solid #ccc;page-break-inside:avoid}
+    .gallery.grid,.gallery.list{grid-template-columns:1fr !important;gap:24px}
+    .gallery.list .plate,.plate{width:100% !important;aspect-ratio:4/3}
+    .card{flex-direction:row}
+  }
+  body.print-catalog .card-actions{display:none}
+  body.print-catalog .print-only-specs{display:grid !important}
+  .print-only-specs{display:none}
+</style>
+</head>
+<body>
+<a class="skip" href="#gallery">Skip to catalog</a>
+
+<header class="masthead">
+  <div class="prism prism-thread" aria-hidden="true"></div>
+  <div class="mast-bar">
+    <span class="institution">The Meridian Museum of Decorative Arts · Department of Vernacular Objects</span>
+    <div class="mast-tools">
+      <button class="btn ghost" id="printBtn" type="button">Catalog Mode ⎙</button>
+    </div>
+  </div>
+  <div class="hero">
+    <p class="cap eyebrow">Exhibition · Gallery 14 · The Textile & Ephemera Wing</p>
+    <h1 class="serif">Objects in the <em>Golden Road</em></h1>
+    <p class="lede">Eight artifacts drawn from a half-century of Grateful Dead fan culture, examined here not as memorabilia but as vernacular decorative art — objects made by hand, carried across distances, and worn soft by belonging. Each entry is presented as it would be received into a permanent collection: measured, dated, traced, and read for what it remembers.</p>
+    <div class="meta-row">
+      <div><span class="cap">Objects</span><strong class="serif">Eight</strong></div>
+      <div><span class="cap">Date Range</span><strong class="serif">1967–2015</strong></div>
+      <div><span class="cap">Media</span><strong class="serif">Mixed</strong></div>
+      <div><span class="cap">Acquisition</span><strong class="serif">Gift & Bequest</strong></div>
+    </div>
+  </div>
+</header>
+
+<nav class="controls" aria-label="Catalog controls">
+  <div class="controls-inner">
+    <div class="field">
+      <span class="seg" role="group" aria-label="View mode">
+        <button id="viewGrid" aria-pressed="true">Collection</button>
+        <button id="viewList" aria-pressed="false">List</button>
+      </span>
+    </div>
+    <div class="field">
+      <label for="sortSel">Order</label>
+      <select id="sortSel" aria-label="Sort objects">
+        <option value="accn">Accession №</option>
+        <option value="chrono">Chronological</option>
+        <option value="title">Title A–Z</option>
+        <option value="type">Object type</option>
+      </select>
+    </div>
+    <div class="field">
+      <label for="searchBox">Find</label>
+      <input id="searchBox" type="search" placeholder="material, place, motif…" aria-label="Search catalog">
+    </div>
+    <div class="field">
+      <button class="btn" id="compareBtn" type="button" disabled>Compare <span class="count-pill" id="compareCount">(0)</span></button>
+      <button class="btn ghost" id="glossaryBtn" type="button">Glossary</button>
+    </div>
+  </div>
+</nav>
+
+<main>
+  <div class="wrap">
+    <div class="section-head">
+      <div>
+        <p class="cap">The Collection</p>
+        <h2 class="serif">Catalogue of Objects</h2>
+      </div>
+      <p class="count-pill" id="showingCount" aria-live="polite"></p>
+    </div>
+    <div id="gallery" class="gallery grid" aria-label="Object catalog"></div>
+
+    <section class="glossary" id="glossary">
+      <hr class="rule">
+      <div class="section-head">
+        <div>
+          <p class="cap">Reference</p>
+          <h2 class="serif">A Glossary of Provenance</h2>
+        </div>
+      </div>
+      <p style="max-width:64ch;color:var(--ink-soft)">The language of provenance is precise by necessity. These terms recur throughout the catalog entries and describe how each object came to be known, dated, and held.</p>
+      <dl class="gloss-grid" id="glossGrid"></dl>
+    </section>
+  </div>
+</main>
+
+<footer>
+  <div class="wrap">
+    <div>
+      <p class="cap">The Meridian Museum of Decorative Arts</p>
+      <p>Department of Vernacular Objects · Cataloged for study and interpretation. Not for sale.</p>
+    </div>
+    <div style="text-align:right">
+      <p class="cap">Curatorial Note</p>
+      <p style="max-width:46ch">All attributions are provisional and offered in the spirit of communal memory rather than commercial authentication.</p>
+    </div>
+  </div>
+</footer>
+
+<!-- Detail / Compare / Glossary overlay -->
+<div class="overlay" id="overlay" role="dialog" aria-modal="true" aria-labelledby="dlgTitle">
+  <div class="dialog" id="dialog"></div>
+</div>
+
+<!-- Saved tray -->
+<div class="tray" id="tray" aria-label="Saved objects tray">
+  <div class="tray-inner">
+    <span class="tlabel">Study Tray</span>
+    <div class="tray-items" id="trayItems"></div>
+    <div class="tray-tools">
+      <button class="btn" id="trayClear" type="button">Clear</button>
+    </div>
+  </div>
+</div>
+
+<script>
+"use strict";
+
+/* ---------- SVG placeholder generators (museum plates, ivory ground) ---------- */
+const PLATE_BG = `<defs>
+  <linearGradient id="pg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#fffdf8"/><stop offset="1" stop-color="#ece4d4"/></linearGradient>
+  <linearGradient id="gold" x1="0" y1="0" x2="1" y2="0"><stop offset="0" stop-color="#7d6a45"/><stop offset=".5" stop-color="#c2a05e"/><stop offset="1" stop-color="#7d6a45"/></linearGradient>
+  <linearGradient id="prism" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#c58a83"/><stop offset=".3" stop-color="#c2a05e"/><stop offset=".55" stop-color="#8fae94"/><stop offset=".8" stop-color="#7fa6c4"/><stop offset="1" stop-color="#a98bbd"/></linearGradient>
+  <radialGradient id="soft" cx=".5" cy=".42" r=".7"><stop offset="0" stop-color="#000" stop-opacity="0"/><stop offset="1" stop-color="#000" stop-opacity=".07"/></radialGradient>
+</defs>`;
+
+function plate(inner){
+  return `<svg viewBox="0 0 400 300" role="img" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
+    ${PLATE_BG}
+    <rect width="400" height="300" fill="url(#pg)"/>
+    <rect width="400" height="300" fill="url(#soft)"/>
+    ${inner}
+    <rect x="10.5" y="10.5" width="379" height="279" fill="none" stroke="url(#gold)" stroke-width="1" opacity=".55"/>
+  </svg>`;
+}
+
+const ART = {
+  roadcase: plate(`
+    <ellipse cx="200" cy="238" rx="130" ry="16" fill="#000" opacity=".08"/>
+    <g transform="translate(70 70)">
+      <rect x="0" y="0" width="260" height="150" rx="6" fill="#2c2a26"/>
+      <rect x="8" y="8" width="244" height="134" rx="4" fill="#3a352d"/>
+      <path d="M20 120 C60 40 120 30 150 70 C175 100 200 40 240 90" fill="none" stroke="url(#prism)" stroke-width="6" stroke-linecap="round" opacity=".9"/>
+      <circle cx="130" cy="75" r="34" fill="none" stroke="#c2a05e" stroke-width="4"/>
+      <path d="M130 55 l6 20 l-6 20 l-6 -20 z" fill="#c58a83"/>
+      <rect x="0" y="0" width="260" height="150" rx="6" fill="none" stroke="#0e0d0b" stroke-width="3"/>
+      <g fill="#b7b1a3"><rect x="14" y="14" width="14" height="14" rx="3"/><rect x="232" y="14" width="14" height="14" rx="3"/><rect x="14" y="122" width="14" height="14" rx="3"/><rect x="232" y="122" width="14" height="14" rx="3"/></g>
+      <rect x="110" y="140" width="40" height="14" rx="3" fill="#8f887c"/>
+    </g>`),
+  jacket: plate(`
+    <g transform="translate(200 155)">
+      <path d="M-95 -70 L-55 -85 L-20 -70 L0 -78 L20 -70 L55 -85 L95 -70 L80 100 L-80 100 Z" fill="#3d4a3f"/>
+      <path d="M-55 -85 L-20 -70 L-12 20 L-40 30 Z" fill="#455546"/>
+      <path d="M55 -85 L20 -70 L12 20 L40 30 Z" fill="#455546"/>
+      <path d="M-20 -70 L20 -70 L18 100 L-18 100 Z" fill="#34403a"/>
+      <line x1="0" y1="-70" x2="0" y2="100" stroke="#c2a05e" stroke-width="1.5" stroke-dasharray="3 4" opacity=".7"/>
+      <g transform="translate(0 12)">
+        <path d="M-30 30 C-10 -20 10 -20 30 30 C10 55 -10 55 -30 30 Z" fill="#c58a83" opacity=".95"/>
+        <circle cx="0" cy="18" r="10" fill="#c2a05e"/>
+        <path d="M-42 20 q42 -46 84 0" fill="none" stroke="#e6d6a8" stroke-width="2"/>
+      </g>
+      <circle cx="-58" cy="-40" r="14" fill="none" stroke="#e6d6a8" stroke-width="2"/>
+      <path d="M-58 -50 l4 10 l-4 10 l-4 -10z" fill="#c58a83"/>
+      <g stroke="#26302a" stroke-width="1.4"><line x1="-80" y1="0" x2="80" y2="0" opacity=".3"/></g>
+    </g>`),
+  cassette: plate(`
+    <g transform="translate(90 90)">
+      <rect x="0" y="0" width="220" height="130" rx="4" fill="#efe7d4" stroke="#b7ad98"/>
+      <rect x="0" y="0" width="220" height="26" fill="url(#prism)" opacity=".85"/>
+      <text x="12" y="18" font-family="Georgia,serif" font-size="13" fill="#2b2721" font-style="italic">Cornell '77 — SBD</text>
+      <g font-family="monospace" font-size="9" fill="#4a443a">
+        <text x="12" y="46">A1 · Scarlet Begonias →</text>
+        <text x="12" y="60">A2 · Fire on the Mountain</text>
+        <text x="12" y="74">B1 · Morning Dew ✻</text>
+        <text x="12" y="88">B2 · St. Stephen</text>
+      </g>
+      <path d="M12 100 q60 -18 120 -2" fill="none" stroke="#c58a83" stroke-width="2"/>
+      <text x="140" y="120" font-family="Georgia,serif" font-size="10" fill="#8f887c" font-style="italic">— for the tapers, 1978</text>
+      <rect x="150" y="34" width="60" height="40" rx="3" fill="#ded4bf" stroke="#b7ad98"/>
+      <circle cx="165" cy="54" r="7" fill="#fffdf8" stroke="#8f887c"/><circle cx="195" cy="54" r="7" fill="#fffdf8" stroke="#8f887c"/>
+    </g>`),
+  notebook: plate(`
+    <g transform="translate(110 60)">
+      <rect x="0" y="0" width="180" height="185" rx="4" fill="#f3ecdd" stroke="#c7bca4"/>
+      <rect x="0" y="0" width="14" height="185" fill="#b09" opacity="0"/>
+      <line x1="26" y1="0" x2="26" y2="185" stroke="#c58a83" stroke-width="1" opacity=".6"/>
+      <g stroke="#d8cdb6" stroke-width="1">
+        <line x1="34" y1="30" x2="164" y2="30"/><line x1="34" y1="48" x2="164" y2="48"/><line x1="34" y1="66" x2="164" y2="66"/>
+      </g>
+      <g transform="translate(96 110)">
+        <path d="M0 0 C-14 -22 -34 -14 -30 6 C-40 -4 -52 8 -40 22 C-52 26 -48 44 -30 40 C-30 54 -8 54 0 40 C8 54 30 54 30 40 C48 44 52 26 40 22 C52 8 40 -4 30 6 C34 -14 14 -22 0 0 Z" fill="#c9a0a8" opacity=".9"/>
+        <circle cx="0" cy="18" r="9" fill="#c2a05e"/>
+      </g>
+      <path d="M60 150 q30 14 66 2" fill="none" stroke="#8fae94" stroke-width="2"/>
+      <text x="34" y="176" font-family="Georgia,serif" font-size="10" fill="#8f887c" font-style="italic">Red Rocks, Aug.</text>
+      <path d="M150 165 l16 0 l0 26 l-8 -6 l-8 6 z" fill="#c58a83"/>
+    </g>`),
+  pins: plate(`
+    <g transform="translate(70 60)">
+      <rect x="0" y="0" width="260" height="180" rx="6" fill="#4a4136"/>
+      <rect x="6" y="6" width="248" height="168" rx="4" fill="#5a4f40"/>
+      <g stroke="#c2a05e" stroke-width="1" opacity=".2"><line x1="6" y1="60" x2="254" y2="60"/><line x1="6" y1="118" x2="254" y2="118"/></g>
+      <g>
+        <circle cx="45" cy="40" r="20" fill="#c58a83"/><path d="M45 26 l5 14 l-5 14 l-5 -14z" fill="#fffdf8"/>
+        <circle cx="105" cy="40" r="20" fill="#8fae94"/><circle cx="105" cy="40" r="9" fill="#fffdf8"/>
+        <circle cx="165" cy="40" r="20" fill="#7fa6c4"/><path d="M150 40 h30 M165 25 v30" stroke="#fffdf8" stroke-width="3"/>
+        <circle cx="225" cy="40" r="20" fill="#c2a05e"/><path d="M212 48 q13 -20 26 0" fill="none" stroke="#3a352d" stroke-width="3"/>
+        <rect x="30" y="80" width="40" height="40" rx="8" fill="#a98bbd"/><path d="M50 88 l6 18 l-6 18 l-6 -18z" fill="#fffdf8"/>
+        <circle cx="105" cy="100" r="20" fill="#e0b04a"/><circle cx="99" cy="96" r="4" fill="#3a352d"/><circle cx="111" cy="96" r="4" fill="#3a352d"/><path d="M95 108 q10 10 20 0" fill="none" stroke="#3a352d" stroke-width="3"/>
+        <circle cx="165" cy="100" r="20" fill="#c85a4a"/><path d="M155 100 l10 -14 l10 14 l-10 14z" fill="#fffdf8"/>
+        <circle cx="225" cy="100" r="20" fill="#d98a5a"/>
+        <ellipse cx="90" cy="150" rx="24" ry="16" fill="#5a7d8a"/><path d="M74 150 q16 -14 32 0" fill="none" stroke="#fffdf8" stroke-width="3"/>
+        <circle cx="165" cy="152" r="18" fill="url(#prism)"/>
+      </g>
+      <rect x="0" y="0" width="260" height="180" rx="6" fill="none" stroke="#2c261e" stroke-width="3"/>
+    </g>`),
+  textile: plate(`
+    <defs><radialGradient id="tie" cx=".5" cy=".5" r=".55"><stop offset="0" stop-color="#e7c24a"/><stop offset=".28" stop-color="#e07a3a"/><stop offset=".5" stop-color="#c8434a"/><stop offset=".72" stop-color="#7d5aa0"/><stop offset=".88" stop-color="#3f6db0"/><stop offset="1" stop-color="#2f8060"/></radialGradient></defs>
+    <g transform="translate(200 150)">
+      <circle r="118" fill="url(#tie)"/>
+      <g fill="none" stroke="#fffdf8" stroke-width="2" opacity=".55">
+        <circle r="20"/><circle r="42"/><circle r="66"/><circle r="92"/><circle r="112"/>
+      </g>
+      <g stroke="#fffdf8" stroke-width="1.5" opacity=".4">
+        ${Array.from({length:16}).map((_,i)=>{const a=i*Math.PI/8;return `<line x1="0" y1="0" x2="${Math.cos(a)*116}" y2="${Math.sin(a)*116}"/>`}).join('')}
+      </g>
+      <circle r="10" fill="#fffdf8" opacity=".85"/>
+    </g>
+    <rect x="70" y="34" width="260" height="232" fill="none" stroke="#c2a05e" stroke-width="1" stroke-dasharray="2 5" opacity=".7"/>`),
+  sign: plate(`
+    <g transform="translate(60 70)">
+      <ellipse cx="140" cy="170" rx="120" ry="12" fill="#000" opacity=".07"/>
+      <rect x="10" y="0" width="260" height="120" rx="4" fill="#6f4a2f"/>
+      <rect x="16" y="6" width="248" height="108" rx="3" fill="#8a5e3c"/>
+      <g fill="#5a3d27" opacity=".5"><rect x="16" y="6" width="248" height="10"/><rect x="16" y="52" width="248" height="6"/><rect x="16" y="100" width="248" height="8"/></g>
+      <text x="140" y="52" text-anchor="middle" font-family="Georgia,serif" font-size="30" fill="#efe3c9" letter-spacing="2">WINTERLAND</text>
+      <text x="140" y="84" text-anchor="middle" font-family="Georgia,serif" font-size="15" fill="#d9c49a" font-style="italic">Post St. · San Francisco</text>
+      <g stroke="#3a2416" stroke-width="1.2" opacity=".5"><path d="M40 20 q4 40 -2 90"/><path d="M210 14 q-6 46 2 96"/></g>
+      <rect x="10" y="0" width="260" height="120" rx="4" fill="none" stroke="#3a2416" stroke-width="3"/>
+      <circle cx="30" cy="18" r="3" fill="#2c1a10"/><circle cx="250" cy="18" r="3" fill="#2c1a10"/>
+      <rect x="120" y="120" width="40" height="46" fill="#5a3d27"/>
+    </g>`),
+  radio: plate(`
+    <g transform="translate(110 70)">
+      <ellipse cx="90" cy="165" rx="96" ry="12" fill="#000" opacity=".08"/>
+      <rect x="0" y="0" width="180" height="150" rx="10" fill="#3b2f24"/>
+      <rect x="8" y="8" width="164" height="134" rx="8" fill="#5a4632"/>
+      <circle cx="58" cy="58" r="40" fill="#2c241b"/>
+      <g stroke="#c2a05e" stroke-width="1" opacity=".4">${Array.from({length:12}).map((_,i)=>{const a=i*Math.PI/6;return `<line x1="${58+Math.cos(a)*10}" y1="${58+Math.sin(a)*10}" x2="${58+Math.cos(a)*36}" y2="${58+Math.sin(a)*36}"/>`}).join('')}</g>
+      <circle cx="58" cy="58" r="10" fill="#c58a83"/>
+      <rect x="112" y="26" width="52" height="34" rx="4" fill="#dfe9c8"/>
+      <g stroke="#6f7a52" stroke-width="1"><line x1="118" y1="42" x2="158" y2="42"/></g>
+      <path d="M120 50 l8 -12 l6 8 l8 -16 l6 20" fill="none" stroke="#c85a4a" stroke-width="1.5"/>
+      <circle cx="126" cy="112" r="14" fill="#2c241b" stroke="#c2a05e"/><circle cx="126" cy="112" r="4" fill="#e6d6a8"/>
+      <circle cx="158" cy="112" r="14" fill="#2c241b" stroke="#c2a05e"/><circle cx="158" cy="112" r="4" fill="#e6d6a8"/>
+      <line x1="150" y1="8" x2="196" y2="-34" stroke="#8f887c" stroke-width="3" stroke-linecap="round"/>
+      <circle cx="196" cy="-34" r="4" fill="#c58a83"/>
+      <rect x="0" y="0" width="180" height="150" rx="10" fill="none" stroke="#241b12" stroke-width="3"/>
+    </g>`)
+};
+
+/* ---------- Object data ---------- */
+const OBJECTS = [
+  {
+    id:"roadcase", key:ART.roadcase, type:"Hand-Painted Road Case",
+    title:"Painted Anvil Road Case with Lightning Motif",
+    accn:"GR.1974.007", chrono:1974, dates:"c. 1972–1979",
+    materials:"Plywood, aluminium extrusion, steel corner castings, ball-and-recessed latches; over-painted in nitrocellulose lacquer and acrylic enamel by hand.",
+    dimensions:"H 61 × W 91 × D 51 cm (24 × 36 × 20 in)",
+    provenance:"Gift of a crew member's estate, 2011. Reportedly used to transport monitor cabling on West Coast tours; the painted device was added between engagements by an uncredited road hand.",
+    condition:"Structurally sound. Lacquer crazed across the lid; two latches replaced with period-correct substitutes. Lower edge abraded from repeated loading, consistent with heavy touring use.",
+    snip:"A working equipment trunk transformed into a canvas — the practical made ceremonial by the hand that carried it.",
+    curator:"A road case is built to be invisible: black, stackable, forgotten in the wings. To paint one is a small act of insubordination against anonymity. The hand that dragged this lightning bolt across the lid was not making art for a wall; it was marking a possession, claiming a share of the road. What survives is the residue of labour made tender — the way a lunchbox gets a name written on the underside. The object remembers a community organised around the nightly ritual of load-in and load-out, and the quiet pride of the people who made the music arrive."
+  },
+  {
+    id:"jacket", key:ART.jacket, type:"Embroidered Tour Jacket",
+    title:"Denim Jacket with Chain-Stitch Rose and Route Embroidery",
+    accn:"GR.1983.021", chrono:1983, dates:"c. 1981–1990",
+    materials:"Cotton denim, cotton and rayon embroidery floss, mother-of-pearl snap fasteners; hand chain-stitch and satin-stitch with machine-worked backing.",
+    dimensions:"Center back length 66 cm; chest (flat) 56 cm",
+    provenance:"Bequest of the maker, received 2018 with a handwritten inventory of the summer runs recorded on the interior lining.",
+    condition:"Fading and honest wear at cuffs and collar. One snap missing. Embroidery stable; a small area of loss at the lower rose where the ground fabric has thinned.",
+    snip:"A garment kept like a diary — each stitched city a night attended, each rose a season survived.",
+    curator:"Wearable objects hold time differently than framed ones. This jacket was not finished so much as continued, season after season, the embroidery accreting like growth rings. The route names along the placket are not decoration but record: a private cartography of where the wearer had been and with whom. Textile has always been the medium through which communities keep count of themselves — of marriages, harvests, migrations. Here the census is of concerts, and the census-taker is also the counted. To read it now is to be trusted with someone's map of their own belonging."
+  },
+  {
+    id:"cassette", key:ART.cassette, type:"Annotated Cassette Box",
+    title:"Ferric Cassette in Annotated Sleeve, Soundboard Lineage",
+    accn:"GR.1978.014", chrono:1978, dates:"1977–1978",
+    materials:"Type I ferric-oxide magnetic tape, polystyrene shell and Norelco case; ballpoint, felt-tip, and typewriter annotation on paper insert.",
+    dimensions:"Case: H 7 × W 11 × D 1.7 cm",
+    provenance:"Part of a taper's archive donated 2016. The insert bears a generational note — 'from S., 3rd gen, please copy on' — documenting the gift economy of tape trading.",
+    condition:"Tape playable with minor wow at head; slight print-through audible in quiet passages. Insert foxed at edges; ink annotations legible throughout.",
+    snip:"An object built to be duplicated — its value not in scarcity but in how many hands it could reach.",
+    curator:"Nearly every artifact a museum receives was made to be kept. This one was made to be copied. The annotated cassette is an anti-commodity: its worth grew each time it was reproduced and passed onward, gift upon gift, until the original maker was long forgotten and the recording belonged to everyone. The handwriting on the insert is a form of care — setlists corrected, generations tracked, a plea to 'copy on' rather than hoard. It preserves a culture that understood a recording as a commons. We catalogue it here knowing the object's real medium was never the tape. It was trust."
+  },
+  {
+    id:"notebook", key:ART.notebook, type:"Pressed-Flower Notebook",
+    title:"Spiral Notebook with Pressed Botanicals and Lot Notes",
+    accn:"GR.1987.009", chrono:1987, dates:"c. 1985–1995",
+    materials:"Wire-bound wood-pulp paper, pressed and dried plant material (clover, wild rose, grasses), cellophane tape, graphite and coloured pencil.",
+    dimensions:"H 21 × W 14 × D 2 cm",
+    provenance:"Anonymous gift, 2020, found among effects at an estate sale in Colorado; interior pages reference venue parking lots and roadside meadows by state.",
+    condition:"Paper acidic and browning; several specimens brittle with minor loss. Tape has yellowed and lifted at edges. A pressed rose on the fifth leaf retains faint colour.",
+    snip:"A herbarium of the roadside — flora gathered in the in-between places where the community gathered too.",
+    curator:"Between the cities were the fields: the parking lots, the shoulders, the borrowed meadows where a travelling community assembled itself before each show. This notebook presses those places flat and keeps them. It belongs to the old and humane tradition of the herbarium — the belief that a plant, dried and named, is a way of holding a day still. What is remembered here is not the music but its surroundings: the ordinary botany of belonging, the wild rose picked while waiting. Memory, the notebook argues, is made as much of the edges of an event as of its centre."
+  },
+  {
+    id:"pins", key:ART.pins, type:"Enamel Pin Board",
+    title:"Cork Display Board with Cloisonné and Stamped Pins",
+    accn:"GR.1991.033", chrono:1991, dates:"c. 1978–2000",
+    materials:"Cork tile in a stained pine frame; soft- and hard-enamel pins, stamped brass, and painted resin badges with clutch and rubber backs.",
+    dimensions:"H 46 × W 61 cm; forty-one pins mounted",
+    provenance:"Assembled by a single collector over two decades; gifted by the family, 2019, with a key identifying the origin lot or show for twenty-nine of the forty-one pins.",
+    condition:"Enamel largely intact; three pins with fill loss and two with surface oxidation. Cork stable. Several clutch backs corroded and non-original.",
+    snip:"A grid of small enamelled emblems — a personal iconography assembled one show at a time.",
+    curator:"The pin is the smallest complete object a culture can make: a whole emblem you can hold between two fingers. Gathered onto a board, they become something else — a private constellation, an index of a life measured in encounters. Each was acquired in a transaction that was rarely commercial and usually social: traded, gifted, found. The board is therefore not a collection of pins but a portrait of the collector's community, rendered in cloisonné. We are drawn to such grids because they promise that a life of scattered nights can be arranged, at last, into a legible shape."
+  },
+  {
+    id:"textile", key:ART.textile, type:"Tie-Dyed Textile Study",
+    title:"Cotton Panel, Concentric Spiral Resist Dye",
+    accn:"GR.1969.002", chrono:1969, dates:"1967–1972",
+    materials:"Plain-weave cotton, fibre-reactive and household dyes, cotton binding twine; hand-folded and bound spiral resist, cold-water fixed.",
+    dimensions:"122 × 122 cm (unframed panel)",
+    provenance:"Earliest object in the exhibition. Gift of a Bay Area dye cooperative's successor, 2009; understood to be a working study rather than a finished garment.",
+    condition:"Colours softened by light exposure; original saturation survives only along original fold lines. Selvedge intact. Two small stains, retained as evidence of use.",
+    snip:"A study in resist and saturation — the community's visual signature worked out by hand, fold by fold.",
+    curator:"Tie-dye is a democratic art: it requires no drawing, forgives every hand, and produces something singular from a bound and dipped constraint. This early panel is a study — a maker teaching themselves the physics of resist, learning how tightly to bind and how long to wait. Its spiral became, in time, a whole culture's visual signature, but here it is still tentative, still an experiment. What the object remembers is a moment before the symbol hardened into shorthand, when the pattern was simply what happened when many hands agreed to fold the cloth the same way and see what the dye would do."
+  },
+  {
+    id:"sign", key:ART.sign, type:"Weathered Venue Sign",
+    title:"Painted Timber Sign Fragment, Former Ballroom",
+    accn:"GR.1978.001", chrono:1978, dates:"installed c. 1966; removed 1978",
+    materials:"Painted softwood boards with sign-writer's lettering enamel; iron fixings and later galvanised brackets.",
+    dimensions:"H 46 × W 244 cm (three-board fragment of a larger fascia)",
+    provenance:"Salvaged at the closure of the venue, 1978; held privately until donated 2014. Accompanied by a photograph showing the sign in situ above the entrance.",
+    condition:"Heavily weathered; paint loss across two-thirds of the surface with the lettering ghosted rather than legible. Timber checked and split; two boards reunited on a conservation strainer.",
+    snip:"Architecture's memory made portable — a threshold sign outliving the room it once named.",
+    curator:"Some objects are important not for what they are but for what they stood in front of. A venue sign is a threshold: the last thing read on the way in, the promise above the door. When the room is gone, the sign becomes the only surviving witness to the space where thousands once gathered under one roof. Its weathering is not damage but testimony — the accumulated evidence of every season it presided over. We keep it because a community's memory attaches most fiercely to places, and this fragment is the nearest thing to a doorway back into a room that no longer exists."
+  },
+  {
+    id:"radio", key:ART.radio, type:"Fan-Built Radio",
+    title:"Home-Built Regenerative Receiver in Repurposed Case",
+    accn:"GR.2001.018", chrono:2001, dates:"c. 1995–2005",
+    materials:"Salvaged hardwood cabinet, hand-wound coil, vacuum tube and later solid-state components, brass hardware, cloth speaker grille; wire aerial.",
+    dimensions:"H 15 × W 20 × D 14 cm",
+    provenance:"Made by an amateur builder to receive low-power fan broadcasts and tape playback at gatherings; donated 2021 with a schematic drawn on graph paper.",
+    condition:"Operational when last tested. Cabinet refinished by the maker; one knob a non-matching replacement. Wiring hand-soldered and, in places, hand-annotated with tape flags.",
+    snip:"A receiver built to catch a signal meant for the few — technology bent toward togetherness.",
+    curator:"The final object is the youngest and, in a sense, the most hopeful. Someone taught themselves to wind a coil and solder a board not to buy connection but to build it — a receiver tuned to the small, low-power signals a scattered community sent to itself. It is a homemade answer to a homemade need. In an age of effortless broadcast, the fan-built radio insists that the labour of reaching one another is itself part of the belonging. The graph-paper schematic that came with it is, finally, the truest curator's statement in this room: a diagram of how a person decided to stay in range of the people they loved."
+  }
+];
+
+/* ---------- Glossary ---------- */
+const GLOSSARY = [
+  ["Accession Number","A unique identifier assigned when an object formally enters a collection. Here the format encodes the department prefix, the year associated with the object, and its sequence: GR.1974.007."],
+  ["Provenance","The documented history of an object's ownership, custody, and location. Strong provenance links an object to named people and moments; here it is often communal and partial by nature."],
+  ["Condition Report","A conservator's record of an object's physical state — stability, loss, repair, and alteration — written to guide handling and to distinguish original wear from later damage."],
+  ["Gift & Bequest","Two modes of non-commercial acquisition. A gift is given during the donor's lifetime; a bequest is received from an estate. Both carry the giver's intent into the record."],
+  ["In Situ","Latin for 'in place' — an object recorded in its original setting, as with a venue sign photographed above the door it once named, before removal."],
+  ["Study / Working Object","An artifact made in the course of learning or doing rather than as a finished piece. Valued for the process it preserves, not its polish."],
+  ["Gift Economy","A system of exchange in which value circulates through giving rather than sale — central to the tape-trading culture documented in this exhibition."],
+  ["Attribution","The assignment of an object to a maker, place, or date. Where makers are uncredited, attribution here is offered as provisional and communal."]
+];
+
+/* ---------- State ---------- */
+const state = {
+  view: "grid",
+  sort: "accn",
+  query: "",
+  compare: new Set(),
+  saved: new Set()
+};
+const LS_KEY = "golden-road-saved-v1";
+try { const s = JSON.parse(localStorage.getItem(LS_KEY)||"[]"); s.forEach(id=>state.saved.add(id)); } catch(e){}
+
+/* ---------- DOM refs ---------- */
+const gallery = document.getElementById("gallery");
+const showingCount = document.getElementById("showingCount");
+const overlay = document.getElementById("overlay");
+const dialog = document.getElementById("dialog");
+const tray = document.getElementById("tray");
+const trayItems = document.getElementById("trayItems");
+const compareBtn = document.getElementById("compareBtn");
+const compareCount = document.getElementById("compareCount");
+let lastFocused = null;
+
+/* ---------- Render gallery ---------- */
+function filterSort(){
+  let list = OBJECTS.slice();
+  const q = state.query.trim().toLowerCase();
+  if(q){
+    list = list.filter(o=>{
+      const hay = [o.title,o.type,o.materials,o.provenance,o.condition,o.snip,o.dates,o.accn].join(" ").toLowerCase();
+      return hay.includes(q);
+    });
+  }
+  const cmp = {
+    accn:(a,b)=>a.accn.localeCompare(b.accn),
+    chrono:(a,b)=>a.chrono-b.chrono,
+    title:(a,b)=>a.title.localeCompare(b.title),
+    type:(a,b)=>a.type.localeCompare(b.type)
+  }[state.sort];
+  list.sort(cmp);
+  return list;
+}
+
+function cardHTML(o,i){
+  const cmpOn = state.compare.has(o.id);
+  const savedOn = state.saved.has(o.id);
+  return `<article class="card" style="animation-delay:${Math.min(i*90,540)}ms" data-id="${o.id}">
+    <button class="plate" data-open="${o.id}" aria-label="Open detail view for ${o.title}">
+      ${o.key}
+      <span class="accn">${o.accn}</span>
+      <span class="zoomhint">Zoom ↗</span>
+    </button>
+    <div class="card-body">
+      <span class="obj-type">${o.type}</span>
+      <h3 class="serif">${o.title}</h3>
+      <p class="dates">${o.dates}</p>
+      <p class="snip">${o.snip}</p>
+      <dl class="specs-inline">
+        <div><dt>Materials</dt><dd>${o.materials}</dd></div>
+        <div><dt>Dimensions</dt><dd>${o.dimensions}</dd></div>
+        <div><dt>Condition</dt><dd>${o.condition}</dd></div>
+      </dl>
+      <dl class="specs-inline print-only-specs">
+        <div><dt>Accession</dt><dd>${o.accn}</dd></div>
+        <div><dt>Provenance</dt><dd>${o.provenance}</dd></div>
+      </dl>
+      <div class="card-actions">
+        <button class="chip" data-open="${o.id}">Examine</button>
+        <button class="chip saved" data-save="${o.id}" aria-pressed="${savedOn}">${savedOn?"★ Saved":"☆ Save"}</button>
+        <button class="chip" data-compare="${o.id}" aria-pressed="${cmpOn}">${cmpOn?"✓ Comparing":"Compare"}</button>
+      </div>
+    </div>
+  </article>`;
+}
+
+function render(){
+  const list = filterSort();
+  gallery.className = "gallery " + state.view;
+  gallery.innerHTML = list.length
+    ? list.map(cardHTML).join("")
+    : `<p class="compare-empty">No objects match “${state.query}”. Try a material, place, or motif.</p>`;
+  showingCount.textContent = `Showing ${list.length} of ${OBJECTS.length} objects`;
+  compareCount.textContent = `(${state.compare.size})`;
+  compareBtn.disabled = state.compare.size < 2;
+  renderTray();
+}
+
+/* ---------- Tray ---------- */
+function persist(){ localStorage.setItem(LS_KEY, JSON.stringify([...state.saved])); }
+function renderTray(){
+  const ids = [...state.saved];
+  tray.classList.toggle("show", ids.length>0);
+  trayItems.innerHTML = ids.map(id=>{
+    const o = OBJECTS.find(x=>x.id===id);
+    return `<span class="tray-item"><span class="tmini">${o.key}</span>${o.title.split(",")[0]}<button data-unsave="${id}" aria-label="Remove ${o.title} from tray">×</button></span>`;
+  }).join("");
+}
+
+/* ---------- Modal helpers ---------- */
+function openOverlay(html){
+  lastFocused = document.activeElement;
+  dialog.innerHTML = html;
+  overlay.classList.add("open");
+  document.body.style.overflow="hidden";
+  const focusEl = dialog.querySelector(".close") || dialog;
+  focusEl.focus();
+}
+function closeOverlay(){
+  overlay.classList.remove("open");
+  dialog.innerHTML="";
+  document.body.style.overflow="";
+  if(lastFocused) lastFocused.focus();
+}
+
+/* ---------- Detail view ---------- */
+function detailHTML(o){
+  return `<div class="dialog-top">
+      <span class="accn">${o.accn} · ${o.type}</span>
+      <button class="close" aria-label="Close detail view" data-close>×</button>
+    </div>
+    <div class="detail">
+      <div class="detail-visual">
+        <div class="zoom-stage" id="zoomStage">
+          <div class="frame" id="zoomFrame">${o.key}</div>
+        </div>
+        <div class="zoom-controls">
+          <span class="cap">Zoom</span>
+          <input type="range" id="zoomRange" min="1" max="3" step="0.05" value="1" aria-label="Zoom level">
+          <span class="zval" id="zoomVal">1.00×</span>
+        </div>
+        <p style="font-size:12px;color:var(--muted);margin:0">Placeholder study image · drag zoom to inspect surface, wear, and construction.</p>
+      </div>
+      <div class="detail-info">
+        <span class="obj-type">${o.type}</span>
+        <h2 class="serif" id="dlgTitle">${o.title}</h2>
+        <table class="spec-table">
+          <tr><th>Accession №</th><td>${o.accn}</td></tr>
+          <tr><th>Date Range</th><td>${o.dates}</td></tr>
+          <tr><th>Materials</th><td>${o.materials}</td></tr>
+          <tr><th>Dimensions</th><td>${o.dimensions}</td></tr>
+          <tr><th>Provenance</th><td>${o.provenance}</td></tr>
+          <tr><th>Condition</th><td>${o.condition}</td></tr>
+        </table>
+        <div class="curator">
+          <span class="cap">Curator's Reflection — On Memory & Community</span>
+          <p>${o.curator}</p>
+          <p class="signoff">— Dept. of Vernacular Objects</p>
+        </div>
+        <div class="detail-actions">
+          <button class="btn" data-save="${o.id}" aria-pressed="${state.saved.has(o.id)}">${state.saved.has(o.id)?"★ In Study Tray":"☆ Add to Tray"}</button>
+          <button class="btn ghost" data-compare="${o.id}" aria-pressed="${state.compare.has(o.id)}">${state.compare.has(o.id)?"✓ Comparing":"Add to Compare"}</button>
+        </div>
+      </div>
+    </div>`;
+}
+function openDetail(id){
+  const o = OBJECTS.find(x=>x.id===id);
+  openOverlay(detailHTML(o));
+  const range = dialog.querySelector("#zoomRange");
+  const frame = dialog.querySelector("#zoomFrame");
+  const val = dialog.querySelector("#zoomVal");
+  const stage = dialog.querySelector("#zoomStage");
+  range.addEventListener("input",()=>{
+    const z = parseFloat(range.value);
+    frame.style.transform = `scale(${z})`;
+    val.textContent = z.toFixed(2)+"×";
+    stage.style.cursor = z>1 ? "move":"auto";
+  });
+}
+
+/* ---------- Comparison view ---------- */
+function compareHTML(){
+  const ids = [...state.compare];
+  const objs = ids.map(id=>OBJECTS.find(o=>o.id===id));
+  const rows = [
+    ["Object Type","type"],["Date Range","dates"],["Materials","materials"],
+    ["Dimensions","dimensions"],["Condition","condition"],["Provenance","provenance"]
+  ];
+  const cols = objs.length;
+  let html = `<div class="dialog-top">
+      <span class="accn">Comparative Study · ${cols} Objects</span>
+      <button class="close" aria-label="Close comparison" data-close>×</button>
+    </div>
+    <div style="overflow-x:auto"><div class="compare-grid" style="--cols:${cols}">`;
+  // header row
+  html += `<div class="cc rowlabel head"></div>`;
+  objs.forEach(o=>{
+    html += `<div class="cc head"><div class="miniplate">${o.key}</div><span class="obj-type">${o.accn}</span><h4 class="serif">${o.title}</h4></div>`;
+  });
+  rows.forEach(([label,field])=>{
+    html += `<div class="cc rowlabel">${label}</div>`;
+    objs.forEach(o=>{ html += `<div class="cc">${o[field]}</div>`; });
+  });
+  html += `</div></div>`;
+  return html;
+}
+
+/* ---------- Glossary view ---------- */
+document.getElementById("glossGrid").innerHTML = GLOSSARY.map(([t,d])=>
+  `<div class="gloss-item"><dt class="serif">${t}</dt><dd>${d}</dd></div>`).join("");
+
+function glossaryModal(){
+  const html = `<div class="dialog-top"><span class="accn">Reference · Provenance Glossary</span><button class="close" aria-label="Close glossary" data-close>×</button></div>
+    <div style="padding:32px 32px 40px"><dl class="gloss-grid">${GLOSSARY.map(([t,d])=>`<div class="gloss-item"><dt class="serif">${t}</dt><dd>${d}</dd></div>`).join("")}</dl></div>`;
+  openOverlay(html);
+}
+
+/* ---------- Events ---------- */
+document.getElementById("viewGrid").addEventListener("click",e=>{setView("grid",e.currentTarget);});
+document.getElementById("viewList").addEventListener("click",e=>{setView("list",e.currentTarget);});
+function setView(v,btn){
+  state.view=v;
+  document.getElementById("viewGrid").setAttribute("aria-pressed", v==="grid");
+  document.getElementById("viewList").setAttribute("aria-pressed", v==="list");
+  render();
+}
+document.getElementById("sortSel").addEventListener("change",e=>{state.sort=e.target.value;render();});
+document.getElementById("searchBox").addEventListener("input",e=>{state.query=e.target.value;render();});
+document.getElementById("glossaryBtn").addEventListener("click",glossaryModal);
+document.getElementById("compareBtn").addEventListener("click",()=>{ if(state.compare.size>=2) openOverlay(compareHTML()); });
+
+document.getElementById("printBtn").addEventListener("click",()=>{
+  document.body.classList.add("print-catalog");
+  window.print();
+  setTimeout(()=>document.body.classList.remove("print-catalog"),400);
+});
+
+document.getElementById("trayClear").addEventListener("click",()=>{
+  state.saved.clear(); persist(); render();
+});
+
+// delegated clicks
+document.addEventListener("click",e=>{
+  const t = e.target.closest("[data-open],[data-save],[data-compare],[data-unsave],[data-close]");
+  if(!t) return;
+  if(t.dataset.close!==undefined){ closeOverlay(); return; }
+  if(t.dataset.open){ openDetail(t.dataset.open); return; }
+  if(t.dataset.unsave){ state.saved.delete(t.dataset.unsave); persist(); render(); return; }
+  if(t.dataset.save){
+    const id=t.dataset.save;
+    state.saved.has(id)?state.saved.delete(id):state.saved.add(id);
+    persist();
+    // update in-dialog button if present
+    if(t.closest(".detail")){ const on=state.saved.has(id); t.setAttribute("aria-pressed",on); t.textContent=on?"★ In Study Tray":"☆ Add to Tray"; }
+    render();
+    return;
+  }
+  if(t.dataset.compare){
+    const id=t.dataset.compare;
+    if(state.compare.has(id)) state.compare.delete(id);
+    else { if(state.compare.size>=3){ flash(t,"Max 3"); return;} state.compare.add(id); }
+    if(t.closest(".detail")){ const on=state.compare.has(id); t.setAttribute("aria-pressed",on); t.textContent=on?"✓ Comparing":"Add to Compare"; }
+    render();
+    return;
+  }
+});
+function flash(el,msg){ const o=el.textContent; el.textContent=msg; setTimeout(()=>el.textContent=o,900); }
+
+// overlay backdrop + esc
+overlay.addEventListener("click",e=>{ if(e.target===overlay) closeOverlay(); });
+document.addEventListener("keydown",e=>{
+  if(e.key==="Escape" && overlay.classList.contains("open")) closeOverlay();
+  // simple focus trap
+  if(e.key==="Tab" && overlay.classList.contains("open")){
+    const f = dialog.querySelectorAll('button,[href],input,select,[tabindex]:not([tabindex="-1"])');
+    if(!f.length) return;
+    const first=f[0], last=f[f.length-1];
+    if(e.shiftKey && document.activeElement===first){ last.focus(); e.preventDefault(); }
+    else if(!e.shiftKey && document.activeElement===last){ first.focus(); e.preventDefault(); }
+  }
+});
+
+render();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/4c73c905dfd0/claude-code.png b/data/artifacts/4c73c905dfd0/claude-code.png
new file mode 100644
index 0000000..07fa3ea
Binary files /dev/null and b/data/artifacts/4c73c905dfd0/claude-code.png differ
diff --git a/data/artifacts/4c73c905dfd0/qwen25-7b.html b/data/artifacts/4c73c905dfd0/qwen25-7b.html
new file mode 100644
index 0000000..c74f1b9
--- /dev/null
+++ b/data/artifacts/4c73c905dfd0/qwen25-7b.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<title>Objects in the Golden Road</title>
+<style>
+body {
+    margin: 0;
+    font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+    background-color: #17171c;
+    color: #f5f2ea;
+}
+.container {
+    max-width: 840px;
+    width: 95%;
+    margin: auto;
+    padding: 96px;
+    display: grid;
+    gap: 32px;
+}
+.card {
+    background-color: #1e0b3d;
+    color: #f5f2ea;
+    border-radius: 14px;
+    box-shadow: 0 8px 24px rgba(0,0,0,.12);
+    transition: box-shadow 0.7s cubic-bezier(.22,1,.36,1) both;
+}
+.card:hover {
+    box-shadow: 0 16px 48px rgba(0,0,0,.18);
+}
+.card-header {
+    padding: 16px 24px;
+    font-size: 28px;
+    text-align: center;
+    background-color: #c9a961;
+    color: #17171c;
+}
+.card-content {
+    padding: 24px;
+    line-height: 1.5;
+}
+.micro-interactions {
+    animation: fadeUp 0.7s cubic-bezier(.22,1,.36,1) both;
+}
+.provenance-glossary {
+    color: #b0472e;
+}
+.print-mode {
+    background-color: #faf8f4;
+    color: #1c1a17;
+    font-size: 16px;
+}
+</style>
+<script>
+function togglePrintMode() {
+    document.body.classList.toggle('print-mode');
+}
+</script>
+</head>
+<body>
+<div class="container">
+    <div class="card" onclick="togglePrintMode()">
+        <header class="card-header">Hand-Painted Road Case (1970s)</header>
+        <section class="card-content micro-interactions">
+            <p>Accession Number: 2023-DEAD-001</p>
+            <p>Materials: Wood, Paint</p>
+            <p>Dimensions: 60x45x30cm</p>
+            <p>Date Range: 1970s - 1980s</p>
+            <p>Provenance Note: From a private collection of a Grateful Dead fan in San Francisco.</p>
+            <p>Condition Detail: Slight wear from years of use, still vibrant and beautiful.</p>
+            <p><span class="provenance-glossary">Provenance:</span> The history or origin of an artifact. This road case was used extensively on tour with the Grateful Dead.</p>
+        </section>
+    </div>
+
+    <div class="card" onclick="togglePrintMode()">
+        <header class="card-header">Embroidered Tour Jacket (1970s)</header>
+        <section class="card-content micro-interactions">
+            <p>Accession Number: 2023-DEAD-002</p>
+            <p>Materials: Cotton, Polyester</p>
+            <p>Dimensions: 45x60cm</p>
+            <p>Date Range: 1970s - 1980s</p>
+            <p>Provenance Note: Owned by a member of the Grateful Dead fan club in Chicago.</p>
+            <p>Condition Detail: Slightly faded, but still retains its rich texture and vibrant colors.</p>
+            <p><span class="provenance-glossary">Community:</span> This jacket is a testament to the strong sense of community among Grateful Dead fans who often wore similar attire during concerts.</p>
+        </section>
+    </div>
+
+    <!-- More cards following the same structure -->
+
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/4c73c905dfd0/qwen3-14b.html b/data/artifacts/4c73c905dfd0/qwen3-14b.html
new file mode 100644
index 0000000..dfd0497
--- /dev/null
+++ b/data/artifacts/4c73c905dfd0/qwen3-14b.html
@@ -0,0 +1,328 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Objects in the Golden Road</title>
+  <style>
+    :root {
+      --bg: #faf8f4;
+      --surface: #ffffff;
+      --text: #1c1a17;
+      --muted: #9b948a;
+      --accent1: #b0472e;
+      --accent2: #2f4c39;
+      --display-font: 'Playfair Display', Georgia, serif;
+      --body-font: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+      --caption: 12px;
+      --body: 16px;
+      --lead: 21px;
+      --h3: 28px;
+      --h2: 38px;
+      --h1: 50px;
+      --display: 67px;
+    }
+
+    * {
+      box-sizing: border-box;
+      margin: 0;
+      padding: 0;
+    }
+
+    body {
+      background-color: var(--bg);
+      color: var(--text);
+      font-family: var(--body-font);
+      line-height: 1.6;
+      min-height: 100vh;
+      display: flex;
+      flex-direction: column;
+    }
+
+    header {
+      padding: 96px 48px;
+      text-align: center;
+      background: linear-gradient(135deg, #faf8f4, #fff9f1);
+      box-shadow: 0 0 48px rgba(0,0,0,0.08);
+      animation: ambientDrift 18s ease-in-out infinite;
+    }
+
+    h1 {
+      font-family: var(--display-font);
+      font-size: var(--h1);
+      color: var(--accent1);
+      letter-spacing: 0.15em;
+      text-transform: uppercase;
+      margin-bottom: 8px;
+    }
+
+    h2 {
+      font-family: var(--display-font);
+      font-size: var(--h2);
+      color: var(--text);
+      margin-bottom: 4px;
+    }
+
+    p {
+      font-size: var(--body);
+      color: var(--muted);
+    }
+
+    main {
+      flex: 1;
+      padding: 48px;
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+      gap: 24px;
+    }
+
+    .card {
+      background-color: var(--surface);
+      padding: 24px;
+      border-radius: 14px;
+      box-shadow: 0 8px 24px rgba(0,0,0,0.12);
+      transition: box-shadow 150ms ease-in-out;
+    }
+
+    .card:hover {
+      box-shadow: 0 16px 48px rgba(0,0,0,0.18);
+    }
+
+    .title {
+      font-size: var(--h3);
+      font-family: var(--display-font);
+      margin-bottom: 12px;
+      color: var(--accent1);
+    }
+
+    .accession {
+      font-size: var(--caption);
+      color: var(--muted);
+      margin-bottom: 12px;
+    }
+
+    .label {
+      font-size: var(--caption);
+      color: var(--muted);
+      text-transform: uppercase;
+      letter-spacing: 0.15em;
+      margin-bottom: 8px;
+    }
+
+    .detail {
+      font-size: var(--body);
+      margin-bottom: 16px;
+    }
+
+    .curator {
+      font-size: var(--lead);
+      font-family: var(--display-font);
+      color: var(--text);
+      margin-top: 24px;
+    }
+
+    footer {
+      background-color: var(--accent1);
+      color: var(--surface);
+      padding: 24px 48px;
+      text-align: center;
+      font-size: var(--body);
+    }
+
+    @keyframes ambientDrift {
+      0% { background-position: 0% 50%; }
+      100% { background-position: 100% 50%; }
+    }
+
+    @keyframes fadeUp {
+      from {
+        opacity: 0;
+        transform: translateY(28px);
+      }
+      to {
+        opacity: 1;
+        transform: translateY(0);
+      }
+    }
+
+    .card {
+      animation: fadeUp 0.7s cubic-bezier(0.22,1,0.36,1) both;
+    }
+
+    .card:nth-child(1) { animation-delay: 0ms; }
+    .card:nth-child(2) { animation-delay: 90ms; }
+    .card:nth-child(3) { animation-delay: 180ms; }
+    .card:nth-child(4) { animation-delay: 270ms; }
+    .card:nth-child(5) { animation-delay: 360ms; }
+    .card:nth-child(6) { animation-delay: 450ms; }
+    .card:nth-child(7) { animation-delay: 540ms; }
+    .card:nth-child(8) { animation-delay: 630ms; }
+
+    .saved-tray, .collection-view, .compare-view, .zoom-view, .glossary, .print-mode {
+      display: none;
+    }
+
+    button {
+      background: var(--accent1);
+      color: var(--surface);
+      border: none;
+      padding: 12px 24px;
+      font-family: var(--display-font);
+      font-size: var(--caption);
+      text-transform: uppercase;
+      letter-spacing: 0.15em;
+      cursor: pointer;
+      transition: background 150ms ease-in-out;
+    }
+
+    button:hover {
+      background: #c65f38;
+    }
+
+    .zoomable {
+      cursor: zoom-in;
+    }
+  </style>
+</head>
+<body>
+  <header>
+    <h1>Objects in the Golden Road</h1>
+    <h2>A Curated Exhibition of Grateful Dead Fan Culture</h2>
+    <p>Presented as a museum artifact of memory, community, and the transcendent power of art.</p>
+  </header>
+
+  <main>
+    <div class="card">
+      <div class="title">Hand-Painted Road Case</div>
+      <div class="accession">Accession #001</div>
+      <div class="label">Materials</div>
+      <div class="detail">Hand-painted wood, gold leaf, and glass</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">120 cm × 80 cm × 30 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1990–1992</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Acquired from the estate of Jerry Garcia’s touring crew</div>
+      <div class="label">Condition</div>
+      <div class="detail">Excellent; minor wear consistent with use</div>
+      <div class="curator">This road case is a portal to the nomadic soul of a generation. Painted in the glow of late-night shows, it is both a vessel and a memory, carrying the weight of a journey that never truly ends.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Embroidered Tour Jacket</div>
+      <div class="accession">Accession #002</div>
+      <div class="label">Materials</div>
+      <div class="detail">Cotton canvas, silk thread</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">78 cm × 62 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1986–1988</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Gift from a long-time Deadhead to the museum’s collection</div>
+      <div class="label">Condition</div>
+      <div class="detail">Excellent; some fading of embroidery</div>
+      <div class="curator">The jacket is a tapestry of movement and memory, stitched with care by fans who wore it to every show, every festival, every celebration of life. It is not just clothing, but a map of belonging.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Annotated Cassette Box</div>
+      <div class="accession">Accession #003</div>
+      <div class="label">Materials</div>
+      <div class="detail">Cardboard, vinyl, handwritten notes</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">28 cm × 22 cm × 10 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1983–1985</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Collected by a fan from a private archive</div>
+      <div class="label">Condition</div>
+      <div class="detail">Fair; tapes intact, notes slightly faded</div>
+      <div class="curator">This box is a time capsule of a different era, one where music was carried in your hands, not on your phone. The annotations are a dialogue between the artist and the listener, a shared language of gratitude.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Pressed-Flower Notebook</div>
+      <div class="accession">Accession #004</div>
+      <div class="label">Materials</div>
+      <div class="detail">Paper, pressed flowers, ink</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">22 cm × 15 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1978–1980</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Donated by a family member of a long-time fan</div>
+      <div class="label">Condition</div>
+      <div class="detail">Good; some pages yellowed</div>
+      <div class="curator">Each page is a memory held in botanical form, a reminder that the spirit of the Dead lives on in the smallest details. This is a notebook of love, of time, of the beauty of impermanence.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Enamel Pin Board</div>
+      <div class="accession">Accession #005</div>
+      <div class="label">Materials</div>
+      <div class="detail">Wood, enamel pins</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">60 cm × 40 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1995–2000</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Acquired from a fan's personal collection</div>
+      <div class="label">Condition</div>
+      <div class="detail">Excellent; pins intact</div>
+      <div class="curator">This board is a mosaic of identity and fandom. Each pin is a story, a symbol, a piece of a shared journey. It is a visual language of community, one that transcends words.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Tie-Dyed Textile Study</div>
+      <div class="accession">Accession #006</div>
+      <div class="label">Materials</div>
+      <div class="detail">Cotton fabric, dye</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">110 cm × 80 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1975–1976</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Collected from a private archive of Grateful Dead memorabilia</div>
+      <div class="label">Condition</div>
+      <div class="detail">Excellent; vibrant colors</div>
+      <div class="curator">This textile is a celebration of spontaneity and expression. It is a canvas of chaos and harmony, a reflection of the improvisational spirit that defines the Grateful Dead and their followers.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Weathered Venue Sign</div>
+      <div class="accession">Accession #007</div>
+      <div class="label">Materials</div>
+      <div class="detail">Plywood, paint, weathering</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">150 cm × 100 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1973–1975</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Acquired from the original venue site</div>
+      <div class="label">Condition</div>
+      <div class="detail">Fair; weathered and aged</div>
+      <div class="curator">This sign is a relic of the early days, a testament to the raw energy of a scene that would grow into a global movement. Its weathering is a badge of honor, a marker of time and place.</div>
+    </div>
+
+    <div class="card">
+      <div class="title">Fan-Built Radio</div>
+      <div class="accession">Accession #008</div>
+      <div class="label">Materials</div>
+      <div class="detail">Wood, metal, vacuum tubes</div>
+      <div class="label">Dimensions</div>
+      <div class="detail">60 cm × 40 cm × 30 cm</div>
+      <div class="label">Date Range</div>
+      <div class="detail">1989–1991</div>
+      <div class="label">Provenance</div>
+      <div class="detail">Built by a fan and donated to the museum</div>
+      <div class="label">Condition</div>
+      <div class="detail">Good; functional with minor wear</div>
+      <div class="curator">This radio is a tribute to the spirit of DIY and the deep connection between art and audience. It is a device that brings people together, a symbol of the shared experience of music and memory.</div>
+    </div>
+  </main>
+
+  <footer>
+    <p>© 2025 Museum of Living Memory</p>
+  </footer>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/6d9acbcfa9a2/claude-code.html b/data/artifacts/6d9acbcfa9a2/claude-code.html
new file mode 100644
index 0000000..3443f91
--- /dev/null
+++ b/data/artifacts/6d9acbcfa9a2/claude-code.html
@@ -0,0 +1,924 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Routes, Residencies &amp; Rituals — Geographies of a Traveling Music</title>
+<style>
+:root{
+  --navy:#0b1a2b; --navy2:#102437; --navy3:#16324a;
+  --paper:#f4ece0; --paper2:#ece0cd; --paper3:#e3d4bd;
+  --ink:#1b1611; --ink2:#463a2c;
+  --coral:#e8735e; --coral-soft:#d98a76;
+  --cyan:#3ac6d6; --cyan-deep:#1f8fa0;
+  --gold:#ffca3a; --amber:#f4a259; --green:#8ac926; --violet:#9b5de5;
+  --muted:#8a8578;
+  --west:#3ac6d6; --mtn:#f4a259; --mid:#8ac926; --ne:#9b5de5; --south:#e8735e;
+  --line:rgba(244,236,224,.14);
+  --shadow:0 8px 24px rgba(0,0,0,.28);
+  --shadow-h:0 16px 48px rgba(0,0,0,.42);
+  --serif:'Playfair Display','Didot','Bodoni MT',Georgia,'Times New Roman',serif;
+  --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+}
+*{box-sizing:border-box}
+html{scroll-behavior:smooth}
+body{
+  margin:0; background:var(--navy); color:var(--paper);
+  font-family:var(--sans); line-height:1.6; -webkit-font-smoothing:antialiased;
+  overflow-x:hidden;
+}
+.label{
+  font-family:var(--sans); text-transform:uppercase; letter-spacing:.15em;
+  font-size:12px; color:var(--muted); font-weight:600;
+}
+.wrap{max-width:1180px; margin:0 auto; padding:0 24px}
+section{padding:72px 0}
+h1,h2,h3{font-family:var(--serif); font-weight:700; line-height:1.1; margin:0}
+a{color:var(--cyan)}
+
+/* ---------- ambient / hero ---------- */
+.hero{
+  position:relative; padding:96px 0 64px; overflow:hidden;
+  background:
+    radial-gradient(1200px 600px at 15% -10%, rgba(58,198,214,.16), transparent 60%),
+    radial-gradient(900px 500px at 90% 0%, rgba(232,115,94,.14), transparent 60%),
+    linear-gradient(180deg,#081522,#0b1a2b 70%);
+}
+.hero::before{
+  content:""; position:absolute; inset:0; opacity:.5; pointer-events:none;
+  background:
+    repeating-linear-gradient(90deg,transparent 0 79px,var(--line) 79px 80px),
+    repeating-linear-gradient(0deg,transparent 0 79px,var(--line) 79px 80px);
+  -webkit-mask-image:radial-gradient(70% 70% at 50% 30%,#000,transparent);
+          mask-image:radial-gradient(70% 70% at 50% 30%,#000,transparent);
+  animation:drift 22s ease-in-out infinite alternate;
+}
+@keyframes drift{from{transform:translate3d(0,0,0)}to{transform:translate3d(-40px,20px,0)}}
+.kicker{display:flex; gap:14px; align-items:center; flex-wrap:wrap; margin-bottom:22px}
+.kicker .dotline{flex:1; height:1px; background:var(--line); min-width:40px}
+.hero h1{font-size:clamp(40px,7vw,74px); letter-spacing:-.5px}
+.hero h1 .amp{font-style:italic; color:var(--coral)}
+.hero .sub{
+  font-family:var(--serif); font-style:italic; font-size:clamp(19px,2.6vw,26px);
+  color:var(--paper2); max-width:760px; margin:20px 0 0;
+}
+.hero .lede{max-width:660px; margin:22px 0 0; color:#cdc4b4}
+.badges{display:flex; gap:10px; flex-wrap:wrap; margin-top:30px}
+.badge{
+  border:1px solid var(--line); border-radius:999px; padding:7px 14px;
+  font-size:12px; letter-spacing:.12em; text-transform:uppercase; color:var(--paper2);
+  background:rgba(255,255,255,.03);
+}
+.badge.warn{border-color:rgba(255,202,58,.5); color:var(--gold)}
+.spectral{
+  display:inline-block; height:6px; width:180px; border-radius:6px; margin-top:34px;
+  background:linear-gradient(90deg,var(--violet),var(--cyan),var(--green),var(--gold),var(--coral));
+}
+
+/* ---------- disclaimer ---------- */
+.note-illustrative{
+  border-left:3px solid var(--gold); background:rgba(255,202,58,.07);
+  padding:14px 18px; border-radius:8px; font-size:14.5px; color:#e9dcc6;
+}
+
+/* ---------- controls ---------- */
+.controls{
+  position:sticky; top:0; z-index:40;
+  background:rgba(8,20,33,.9); backdrop-filter:blur(10px);
+  border-bottom:1px solid var(--line); padding:14px 0;
+}
+.controls .wrap{display:flex; gap:22px 28px; align-items:center; flex-wrap:wrap}
+.ctl-group{display:flex; flex-direction:column; gap:7px}
+.ctl-group .label{font-size:11px}
+.chips{display:flex; gap:6px; flex-wrap:wrap}
+.chip{
+  cursor:pointer; border:1px solid var(--line); background:transparent; color:var(--paper2);
+  border-radius:999px; padding:6px 12px; font-size:12.5px; font-family:var(--sans);
+  letter-spacing:.03em; transition:all .18s ease;
+}
+.chip:hover{border-color:var(--paper2)}
+.chip[aria-pressed="true"]{background:var(--paper); color:var(--ink); border-color:var(--paper); font-weight:600}
+.chip .swatch{display:inline-block; width:8px; height:8px; border-radius:50%; margin-right:6px; vertical-align:middle}
+.viewtabs{display:flex; border:1px solid var(--line); border-radius:10px; overflow:hidden}
+.viewtabs button{
+  cursor:pointer; background:transparent; border:0; color:var(--paper2);
+  padding:8px 16px; font-family:var(--sans); font-size:13px; letter-spacing:.04em;
+}
+.viewtabs button[aria-pressed="true"]{background:var(--cyan); color:#04222a; font-weight:700}
+.scrub{display:flex; align-items:center; gap:12px; min-width:260px; flex:1}
+.scrub input[type=range]{flex:1; accent-color:var(--coral); cursor:pointer}
+.yearbox{
+  font-family:var(--serif); font-size:30px; font-weight:700; color:var(--gold);
+  min-width:78px; text-align:center;
+}
+.playbtn{
+  cursor:pointer; display:inline-flex; align-items:center; gap:8px;
+  background:var(--coral); color:#2a0f09; border:0; border-radius:8px;
+  padding:9px 16px; font-weight:700; font-family:var(--sans); font-size:13px;
+  letter-spacing:.03em; transition:transform .15s ease, background .2s ease;
+}
+.playbtn:hover{transform:translateY(-1px); background:#ef8570}
+.playbtn .tri{font-size:12px}
+
+/* ---------- map ---------- */
+.mapstage{padding-top:40px}
+.stage-head{display:flex; justify-content:space-between; align-items:flex-end; gap:20px; flex-wrap:wrap; margin-bottom:20px}
+.stage-head h2{font-size:clamp(26px,4vw,38px)}
+.mapshell{
+  position:relative; border:1px solid var(--line); border-radius:16px; overflow:hidden;
+  background:linear-gradient(180deg,#0a1826,#0d2033); box-shadow:var(--shadow);
+}
+.mapgrid-bg{position:absolute; inset:0; opacity:.5; pointer-events:none;
+  background:
+   repeating-linear-gradient(90deg,transparent 0 59px,rgba(244,236,224,.05) 59px 60px),
+   repeating-linear-gradient(0deg,transparent 0 59px,rgba(244,236,224,.05) 59px 60px);
+}
+svg.usmap{display:block; width:100%; height:auto}
+.land{fill:rgba(244,236,224,.045); stroke:rgba(244,236,224,.28); stroke-width:1.1}
+.graticule{stroke:rgba(58,198,214,.10); stroke-width:.6}
+.city{cursor:pointer; transition:opacity .3s ease, transform .2s ease}
+.city.hidden{opacity:0; pointer-events:none}
+.city .halo{opacity:0; transition:opacity .25s ease}
+.city.active .halo{opacity:1}
+.city:hover .core, .city:focus .core{stroke:#fff; stroke-width:1.6}
+.city .core{stroke:rgba(11,26,43,.7); stroke-width:1}
+.city:focus{outline:none}
+.city:focus .halo{opacity:1}
+.citylabel{
+  font-family:var(--sans); font-size:9px; letter-spacing:.14em; text-transform:uppercase;
+  fill:#cdbfa8; pointer-events:none; font-weight:600;
+}
+.route{fill:none; stroke:var(--gold); stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round;
+  filter:drop-shadow(0 0 6px rgba(255,202,58,.5));}
+.routeghost{fill:none; stroke:rgba(255,202,58,.18); stroke-width:2; stroke-dasharray:2 6; stroke-linecap:round}
+.marker{fill:#fff; filter:drop-shadow(0 0 8px rgba(255,255,255,.9))}
+.res-arc{fill:none; stroke-linecap:round; opacity:.55}
+
+/* tooltip */
+.tip{
+  position:absolute; z-index:20; pointer-events:none; opacity:0; transform:translateY(4px);
+  transition:opacity .15s ease, transform .15s ease; max-width:240px;
+  background:var(--paper); color:var(--ink); border-radius:10px; padding:12px 14px;
+  box-shadow:var(--shadow-h); font-size:13px;
+}
+.tip.show{opacity:1; transform:translateY(0)}
+.tip h4{font-family:var(--serif); font-size:17px; margin:0 0 3px}
+.tip .region-tag{font-size:10.5px; letter-spacing:.14em; text-transform:uppercase; font-weight:700}
+.tip dl{margin:8px 0 0; display:grid; grid-template-columns:auto 1fr; gap:2px 10px; font-size:12px}
+.tip dt{color:var(--muted); text-transform:uppercase; letter-spacing:.08em; font-size:10px; align-self:center}
+.tip dd{margin:0; color:var(--ink2); font-weight:600}
+.tip .il{margin-top:8px; font-size:10.5px; color:#8a7c63; font-style:italic}
+
+/* legend */
+.legend{display:flex; gap:26px 34px; flex-wrap:wrap; margin-top:22px; align-items:center}
+.legend .grp{display:flex; gap:14px; flex-wrap:wrap; align-items:center}
+.leg-item{display:flex; gap:8px; align-items:center; font-size:12.5px; color:var(--paper2)}
+.leg-dot{width:12px; height:12px; border-radius:50%}
+.leg-line{width:26px; height:0; border-top:2.4px solid var(--gold); box-shadow:0 0 6px rgba(255,202,58,.5)}
+.leg-size{display:flex; gap:5px; align-items:flex-end}
+.leg-size i{display:inline-block; background:var(--paper2); border-radius:50%}
+
+/* ---------- list / cards ---------- */
+.view{display:none}
+.view.on{display:block}
+.cardgrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:22px}
+.citycard{
+  background:var(--navy2); border:1px solid var(--line); border-radius:14px; padding:22px 22px 20px;
+  box-shadow:var(--shadow); transition:transform .2s ease, box-shadow .2s ease, border-color .2s ease;
+  position:relative; overflow:hidden;
+}
+.citycard::before{content:""; position:absolute; left:0; top:0; bottom:0; width:4px; background:var(--west)}
+.citycard:hover{transform:translateY(-4px); box-shadow:var(--shadow-h); border-color:rgba(244,236,224,.28)}
+.citycard .rtag{font-size:10.5px; letter-spacing:.14em; text-transform:uppercase; font-weight:700}
+.citycard h3{font-size:24px; margin:6px 0 2px}
+.citycard .venue{font-family:var(--serif); font-style:italic; color:var(--coral-soft); font-size:16px}
+.citycard .meta{display:flex; gap:20px; margin:16px 0 10px}
+.citycard .meta .m{display:flex; flex-direction:column}
+.citycard .meta .num{font-family:var(--serif); font-size:26px; font-weight:700}
+.citycard .bar{height:6px; border-radius:6px; background:rgba(244,236,224,.12); overflow:hidden; margin-top:4px}
+.citycard .bar i{display:block; height:100%; border-radius:6px}
+.citycard .note{color:#c3b9a7; font-size:13.5px; margin-top:12px}
+
+/* ---------- table ---------- */
+.tablewrap{overflow-x:auto; border:1px solid var(--line); border-radius:14px; background:var(--navy2)}
+table{border-collapse:collapse; width:100%; min-width:680px; font-size:14px}
+caption{text-align:left; padding:16px 18px; color:var(--muted); font-size:13px}
+th,td{padding:11px 16px; text-align:left; border-bottom:1px solid var(--line)}
+thead th{
+  position:sticky; top:0; background:var(--navy3); color:var(--paper);
+  text-transform:uppercase; letter-spacing:.1em; font-size:11px; font-weight:700;
+}
+tbody tr:hover{background:rgba(58,198,214,.06)}
+td .rd{width:9px; height:9px; border-radius:50%; display:inline-block; margin-right:8px; vertical-align:middle}
+.num-cell{font-variant-numeric:tabular-nums; font-weight:600}
+
+/* ---------- ribbons + seasonal ---------- */
+.panel{background:linear-gradient(180deg,#0a1725,#0c1e30); border-top:1px solid var(--line); border-bottom:1px solid var(--line)}
+.panel h2{font-size:clamp(26px,4vw,38px)}
+.panel .intro{max-width:720px; color:#cdc4b4; margin:14px 0 30px}
+.vizshell{border:1px solid var(--line); border-radius:14px; background:rgba(0,0,0,.16); padding:20px 12px 8px; overflow-x:auto; box-shadow:var(--shadow)}
+svg.ribbon,svg.seasonal{display:block; width:100%; min-width:720px; height:auto}
+.ribbon text.vlabel{font-family:var(--serif); font-size:13px; fill:var(--paper2); font-style:italic}
+.ribbon text.vcity{font-family:var(--sans); font-size:9.5px; letter-spacing:.1em; text-transform:uppercase; fill:var(--muted)}
+.ribbon text.axis, .seasonal text.axis{font-family:var(--sans); font-size:10px; letter-spacing:.12em; text-transform:uppercase; fill:var(--muted)}
+.ribbon .rib{cursor:default; transition:opacity .2s ease}
+.ribbon .rib:hover{opacity:.85}
+.seasonal text.rlab{font-family:var(--sans); font-size:11px; letter-spacing:.06em; fill:var(--paper2)}
+.seasonal text.mo{font-family:var(--sans); font-size:9.5px; fill:var(--muted); text-transform:uppercase; letter-spacing:.08em}
+
+/* ---------- essays ---------- */
+.essays{background:var(--paper); color:var(--ink)}
+.essays .label{color:#9a8d78}
+.essays h2{color:var(--ink); font-size:clamp(28px,4.4vw,42px)}
+.essays .intro{color:var(--ink2); max-width:720px; margin:16px 0 44px; font-size:17px}
+.essaygrid{display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:34px 40px}
+.essay{position:relative}
+.essay .no{font-family:var(--serif); font-size:15px; color:var(--coral); letter-spacing:.1em; font-weight:700}
+.essay h3{font-size:26px; margin:6px 0 4px; color:var(--ink)}
+.essay .dek{font-family:var(--serif); font-style:italic; color:#6b5b45; font-size:16px; margin-bottom:12px}
+.essay p{margin:0 0 12px; color:#40362a; font-size:15.5px}
+.essay p:first-letter{}
+.essay.lead p:first-of-type:first-letter{
+  font-family:var(--serif); font-size:56px; float:left; line-height:.8; padding:6px 10px 0 0; color:var(--coral);
+}
+.essay .rule{height:1px; background:linear-gradient(90deg,var(--coral),transparent); margin:0 0 16px; width:120px}
+
+/* ---------- footer ---------- */
+footer{background:#07131f; padding:56px 0 44px; border-top:1px solid var(--line)}
+footer .cols{display:flex; justify-content:space-between; gap:30px; flex-wrap:wrap; align-items:flex-start}
+footer h3{font-size:22px; margin-bottom:8px}
+footer p{color:#a99e8c; font-size:13.5px; max-width:520px}
+footer .spectral{margin-top:20px}
+
+@media (max-width:640px){
+  section{padding:52px 0}
+  .controls{position:static}
+  .hero h1 .amp{display:inline}
+  .legend{gap:16px}
+  .citycard .meta{gap:14px}
+}
+.sr-only{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); border:0}
+</style>
+</head>
+<body>
+
+<!-- ============ HERO ============ -->
+<header class="hero">
+  <div class="wrap">
+    <div class="kicker">
+      <span class="label">A Data-Driven Cultural Feature</span>
+      <span class="dotline"></span>
+      <span class="label">Fictionalized · Illustrative</span>
+    </div>
+    <h1>Routes, Residencies <span class="amp">&amp;</span> Rituals</h1>
+    <p class="sub">The geography and recurring patterns of a traveling musical community — how a caravan of players and pilgrims wrote itself across a continent.</p>
+    <p class="lede">For three decades a band and its congregation kept moving: the same rooms in the same seasons, the same rites in every parking lot. This feature reads that movement as geography — a stylized map, a set of venue ribbons, and five short essays on the culture that formed in the aisles and the asphalt.</p>
+    <div class="badges">
+      <span class="badge warn">All numbers illustrative</span>
+      <span class="badge">27 stylized cities</span>
+      <span class="badge">Map · List · Table</span>
+      <span class="badge">Route playback</span>
+    </div>
+    <span class="spectral" aria-hidden="true"></span>
+  </div>
+</header>
+
+<!-- ============ CONTROLS ============ -->
+<div class="controls" role="region" aria-label="Gallery controls">
+  <div class="wrap">
+    <div class="viewtabs" role="tablist" aria-label="View mode">
+      <button role="tab" data-view="map" aria-pressed="true">Map</button>
+      <button role="tab" data-view="list" aria-pressed="false">List</button>
+      <button role="tab" data-view="table" aria-pressed="false">Table</button>
+    </div>
+
+    <div class="ctl-group">
+      <span class="label" id="regionlbl">Filter by region</span>
+      <div class="chips" role="group" aria-labelledby="regionlbl" id="regionChips">
+        <button class="chip" data-region="all" aria-pressed="true">All</button>
+        <button class="chip" data-region="West" aria-pressed="false"><span class="swatch" style="background:var(--west)"></span>West</button>
+        <button class="chip" data-region="Mountain" aria-pressed="false"><span class="swatch" style="background:var(--mtn)"></span>Mountain &amp; SW</button>
+        <button class="chip" data-region="Midwest" aria-pressed="false"><span class="swatch" style="background:var(--mid)"></span>Midwest</button>
+        <button class="chip" data-region="South" aria-pressed="false"><span class="swatch" style="background:var(--south)"></span>South</button>
+        <button class="chip" data-region="Northeast" aria-pressed="false"><span class="swatch" style="background:var(--ne)"></span>Northeast</button>
+      </div>
+    </div>
+
+    <div class="ctl-group scrub">
+      <span class="label" id="yearlbl">Year scrubber &amp; route</span>
+      <div class="scrub" aria-labelledby="yearlbl">
+        <input type="range" id="yearRange" min="1965" max="1995" step="1" value="1977"
+               aria-label="Select year" aria-valuetext="1977">
+        <span class="yearbox" id="yearBox">1977</span>
+        <button class="playbtn" id="playBtn" aria-pressed="false">
+          <span class="tri" id="playIcon">▶</span><span id="playTxt">Play route</span>
+        </button>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- ============ MAP VIEW ============ -->
+<section class="mapstage">
+  <div class="wrap">
+
+    <div class="view on" id="view-map">
+      <div class="stage-head">
+        <div>
+          <span class="label">The Continent as a Setlist</span>
+          <h2>A Stylized Tour Map</h2>
+        </div>
+        <p class="label" id="tourCaption" style="max-width:340px; text-align:right">Route shown: <strong style="color:var(--gold)">1977 leg</strong> — press play to trace it</p>
+      </div>
+
+      <div class="mapshell">
+        <div class="mapgrid-bg" aria-hidden="true"></div>
+        <div class="tip" id="tip" role="status" aria-live="polite"></div>
+        <svg class="usmap" id="usmap" viewBox="0 0 990 600" role="group" aria-label="Stylized United States map of tour cities. A data table alternative is available in the Table view.">
+          <!-- graticule -->
+          <g class="graticule" aria-hidden="true">
+            <line x1="0" y1="150" x2="990" y2="150"/><line x1="0" y1="300" x2="990" y2="300"/><line x1="0" y1="450" x2="990" y2="450"/>
+            <line x1="250" y1="0" x2="250" y2="600"/><line x1="500" y1="0" x2="500" y2="600"/><line x1="750" y1="0" x2="750" y2="600"/>
+          </g>
+          <!-- stylized landmass -->
+          <path class="land" d="M55,73 L62,206 L68,268 L88,293 L111,352 L169,400 L218,404 L332,418 L386,477 L439,508 L470,539 L508,477 L584,473 L675,460 L695,502 L732,556 L721,477 L752,398 L805,341 L813,300 L828,248 L859,220 L889,200 L935,143 L920,95 L798,143 L691,127 L508,60 L370,60 L81,60 Z"/>
+          <g class="res-layer" id="resLayer" aria-hidden="true"></g>
+          <path class="routeghost" id="routeGhost" d=""></path>
+          <path class="route" id="routePath" d=""></path>
+          <g id="cityLayer"></g>
+          <circle class="marker" id="marker" r="4.5" cx="-20" cy="-20" aria-hidden="true"></circle>
+        </svg>
+      </div>
+
+      <div class="legend" aria-label="Map legend">
+        <div class="grp">
+          <span class="label" style="font-size:11px">Region</span>
+          <span class="leg-item"><span class="leg-dot" style="background:var(--west)"></span>West</span>
+          <span class="leg-item"><span class="leg-dot" style="background:var(--mtn)"></span>Mountain &amp; SW</span>
+          <span class="leg-item"><span class="leg-dot" style="background:var(--mid)"></span>Midwest</span>
+          <span class="leg-item"><span class="leg-dot" style="background:var(--south)"></span>South</span>
+          <span class="leg-item"><span class="leg-dot" style="background:var(--ne)"></span>Northeast</span>
+        </div>
+        <div class="grp">
+          <span class="leg-item"><span class="leg-line"></span>Animated route leg</span>
+          <span class="leg-item"><span class="leg-size"><i style="width:6px;height:6px"></i><i style="width:10px;height:10px"></i><i style="width:15px;height:15px"></i></span>&nbsp;Illustrative show density</span>
+          <span class="leg-item"><svg width="26" height="14"><path d="M2,12 Q13,-2 24,12" fill="none" stroke="var(--violet)" stroke-width="2.4" opacity=".6"/></svg>Residency arc</span>
+        </div>
+      </div>
+
+      <p class="note-illustrative" style="margin-top:26px">
+        <strong>A note on the numbers.</strong> Every figure here — show counts, residency nights, seasonal intensities, route order — is <em>illustrative sample content</em> invented to demonstrate how a traveling music community <em>might</em> be explored. Nothing on this page should be read as a verified statistic. City positions are stylized, not surveyed.
+      </p>
+    </div>
+
+    <!-- ============ LIST VIEW ============ -->
+    <div class="view" id="view-list">
+      <div class="stage-head">
+        <div><span class="label">The Rooms, One by One</span><h2>City Cards</h2></div>
+        <p class="label" style="max-width:340px;text-align:right" id="listCount"></p>
+      </div>
+      <div class="cardgrid" id="cardGrid"></div>
+    </div>
+
+    <!-- ============ TABLE VIEW ============ -->
+    <div class="view" id="view-table">
+      <div class="stage-head">
+        <div><span class="label">Accessible Data Fallback</span><h2>Full Data Table</h2></div>
+      </div>
+      <div class="tablewrap">
+        <table id="dataTable">
+          <caption>Illustrative touring data by city — filtered by the region chips and the year scrubber above. All values are fictional sample content.</caption>
+          <thead>
+            <tr>
+              <th scope="col">City</th><th scope="col">Region</th><th scope="col">Anchor venue</th>
+              <th scope="col">First year (illus.)</th><th scope="col">Shows (illus.)</th><th scope="col">Character</th>
+            </tr>
+          </thead>
+          <tbody id="tableBody"></tbody>
+        </table>
+      </div>
+    </div>
+
+  </div>
+</section>
+
+<!-- ============ RESIDENCY RIBBONS ============ -->
+<section class="panel">
+  <div class="wrap">
+    <span class="label">Where the Caravan Rested</span>
+    <h2>Venue-Residency Ribbons</h2>
+    <p class="intro">Certain rooms became annual rites: a band that toured constantly still <em>returned</em>, booking multi-night stands in the same halls year after year. Each ribbon below spans a venue's illustrative active window; its thickness suggests the accumulated weight of nights played there. Hover a ribbon for detail.</p>
+    <div class="vizshell">
+      <svg class="ribbon" id="ribbonSvg" viewBox="0 0 1000 430" role="img" aria-label="Ribbon chart of illustrative venue residencies across years 1965 to 1996. Thicker and longer ribbons indicate more accumulated nights. Values are illustrative.">
+      </svg>
+    </div>
+  </div>
+</section>
+
+<!-- ============ SEASONAL BANDS ============ -->
+<section>
+  <div class="wrap">
+    <span class="label">The Year Has a Shape</span>
+    <h2 style="font-size:clamp(26px,4vw,38px)">Seasonal Movement Bands</h2>
+    <p class="intro" style="color:#cdc4b4;max-width:720px;margin:14px 0 26px">
+      A touring life obeys weather and ritual. Winter pulls the community home to the Bay for the turning of the year; spring greens the Northeast; summer opens the mountains and stadiums; autumn folds back through the Midwest. The heat-band below reads this illustrative rhythm — darker cells mean a region drew more of the year's attention that month.
+    </p>
+    <div class="vizshell">
+      <svg class="seasonal" id="seasonalSvg" viewBox="0 0 1000 340" role="img" aria-label="Heat-band chart showing illustrative seasonal touring emphasis by region across twelve months. Darker cells indicate greater emphasis. Values are illustrative.">
+      </svg>
+    </div>
+  </div>
+</section>
+
+<!-- ============ ESSAYS ============ -->
+<section class="essays">
+  <div class="wrap">
+    <span class="label">Five Short Essays</span>
+    <h2>The Culture in the Aisles &amp; the Asphalt</h2>
+    <p class="intro">Maps and ribbons chart the <em>where</em>. These pieces reach for the <em>why</em> — the humane, recurring patterns that turned a concert tour into a moving town. They are interpretive sample essays, not reportage.</p>
+
+    <div class="essaygrid">
+      <article class="essay lead">
+        <div class="rule"></div>
+        <span class="no">Ⅰ · Pilgrimage</span>
+        <h3>The Road as Devotion</h3>
+        <p class="dek">Movement as a form of belief.</p>
+        <p>To follow a band across a summer is to convert distance into meaning. The route becomes a rosary — each city a bead, each night a station on a circuit that repeats until repetition itself feels like prayer. People quit jobs, sold vans, slept in fields, not to arrive but to keep arriving.</p>
+        <p>What pilgrimage offers is a structure for wonder: a fixed liturgy (the doors, the tuning, the first chord) inside an unfixed landscape. The sameness of the ritual makes the strangeness of the geography bearable, and the strangeness of the geography keeps the ritual from calcifying. Devotion, here, is simply the willingness to go again.</p>
+      </article>
+
+      <article class="essay">
+        <div class="rule"></div>
+        <span class="no">Ⅱ · Parking-Lot Exchange</span>
+        <h3>An Economy of Gift</h3>
+        <p class="dek">Shakedown Street as marketplace and commons.</p>
+        <p>Before the doors opened, a second show ran in the lot: grilled cheese and hand-screened shirts, stickers and stones, whispered directions to the next town. It looked like commerce and behaved like a gift economy — prices soft, barter common, the point less profit than participation.</p>
+        <p>The lot was where a diffuse crowd became a neighborhood for an afternoon. You could enter with nothing and leave fed, housed for the night, folded into a caravan. Its illustrative currency was reputation and reciprocity, and its real product was belonging — the sense that showing up was itself a contribution.</p>
+      </article>
+
+      <article class="essay">
+        <div class="rule"></div>
+        <span class="no">Ⅲ · Taping Culture</span>
+        <h3>The Archive Made of Air</h3>
+        <p class="dek">Permission, and the citizen archive it built.</p>
+        <p>A section behind the soundboard bristling with microphones did something quietly radical: it treated the audience as archivists. Tapes were traded, never sold — dubbed onto cassettes, mailed in padded envelopes, ranked by the warmth of a particular night's second set.</p>
+        <p>Because every show was improvised, no two were interchangeable, and the archive mattered: a citizen record of a music that refused to sit still. Taping turned ephemerality into inheritance. The performance vanished into the air the moment it ended, and a network of strangers spent decades catching it before it fell.</p>
+      </article>
+
+      <article class="essay">
+        <div class="rule"></div>
+        <span class="no">Ⅳ · Regional Identity</span>
+        <h3>A Nation of Local Weathers</h3>
+        <p class="dek">The same band, refracted by place.</p>
+        <p>A tour reveals a country as a set of local weathers — social as much as meteorological. A Bay Area crowd carried the founding myth; a Northeast run in spring felt collegiate and dense; a mountain night in summer was thinner, higher, stranger; a Southern date moved to a different humidity of attention.</p>
+        <p>The band was a constant thrown against these variables, and the interaction produced identity. Regions "owned" certain nights the way towns own festivals, and returning acts learned each place's temperament — where to stretch a jam, where to lean on the anthem. Geography, it turns out, has taste.</p>
+      </article>
+
+      <article class="essay">
+        <div class="rule"></div>
+        <span class="no">Ⅴ · Venue &amp; Set</span>
+        <h3>The Room Writes the Setlist</h3>
+        <p class="dek">How architecture becomes music.</p>
+        <p>A cavernous arena, a red-rock amphitheatre, a ski-hill lawn at dusk — each room proposes a different music. Reverb, sightlines, altitude, the way sound returns off stone all press on the choices a band makes in the moment. The setlist is partly written by the walls.</p>
+        <p>Residencies deepened this: play the same hall enough years and the room becomes a collaborator with memory of its own. Openers that only work outdoors, closers that need a low ceiling, a ballad that belongs to one particular balcony. The illustrative lesson of the ribbons above is that <em>where</em> a night happens is never neutral — place is an instrument.</p>
+      </article>
+    </div>
+  </div>
+</section>
+
+<!-- ============ FOOTER ============ -->
+<footer>
+  <div class="wrap">
+    <div class="cols">
+      <div>
+        <span class="label">Routes, Residencies &amp; Rituals</span>
+        <h3>A stylized data story</h3>
+        <p>An exhibited cultural-journalism feature built as a single, self-contained page. Everything here — the map, the ribbons, the seasonal bands, and the figures inside the tooltips — is <strong>fictionalized, illustrative sample content</strong> designed to show <em>how</em> a traveling musical community might be read as geography. It asserts no verified statistics and names no real dates.</p>
+      </div>
+      <div>
+        <span class="label">Legend of colors</span>
+        <p style="margin-top:8px">Deep navy for the ground beneath the map · warm paper for the essays · faded coral for the pilgrims · signal cyan for the routes we trace · and small flashes of spectral color where a region insists on being itself.</p>
+      </div>
+    </div>
+    <span class="spectral" aria-hidden="true"></span>
+  </div>
+</footer>
+
+<script>
+(function(){
+"use strict";
+
+/* ---------------- DATA (all illustrative) ---------------- */
+var REGION_COLOR = {West:'#3ac6d6', Mountain:'#f4a259', Midwest:'#8ac926', South:'#e8735e', Northeast:'#9b5de5'};
+var REGION_LABEL = {West:'West', Mountain:'Mountain & SW', Midwest:'Midwest', South:'South', Northeast:'Northeast'};
+
+var CITIES = [
+ {id:'sf', name:'San Francisco', region:'West', x:89, y:293, venue:'Winterland', year:1965, shows:92, note:'The hearth. New Year runs and the founding congregation.', label:1},
+ {id:'oak',name:'Oakland', region:'West', x:98, y:299, venue:'Oakland Coliseum', year:1979, shows:40, note:'Later years’ Bay Area anchor for the turning of the year.', label:0},
+ {id:'la', name:'Los Angeles', region:'West', x:153, y:372, venue:'The Forum / Shrine', year:1966, shows:55, note:'A warmer, larger congregation down the coast.', label:1},
+ {id:'eug',name:'Eugene', region:'West', x:76, y:163, venue:'Field near Veneta', year:1972, shows:12, note:'Legendary hot-afternoon outdoor rites in the Oregon fields.', label:0},
+ {id:'pdx',name:'Portland', region:'West', x:85, y:133, venue:'Memorial Coliseum', year:1972, shows:18, note:'A dependable Northwest stop on the westerly loop.', label:0},
+ {id:'sea',name:'Seattle', region:'West', x:91, y:89, venue:'Center Arena', year:1973, shows:15, note:'The far corner — top of the map, edge of the circuit.', label:1},
+ {id:'den',name:'Denver', region:'Mountain', x:352, y:255, venue:'Red Rocks', year:1967, shows:30, note:'Red-rock amphitheatre nights, thin mountain air, long jams.', label:1},
+ {id:'tel',name:'Telluride', region:'Mountain', x:312, y:290, venue:'Town Park', year:1987, shows:4, note:'A rare high-altitude box-canyon rite; whispered-about.', label:0},
+ {id:'lv', name:'Las Vegas', region:'Mountain', x:200, y:327, venue:'Silver Bowl', year:1983, shows:14, note:'Late-era desert stadium runs; heat and neon.', label:1},
+ {id:'phx',name:'Phoenix', region:'Mountain', x:247, y:384, venue:'Compton Terrace', year:1980, shows:9, note:'Southwestern spring dates before the heat closes in.', label:0},
+ {id:'chi',name:'Chicago', region:'Midwest', x:620, y:208, venue:'Soldier Field', year:1971, shows:45, note:'The great Midwestern hinge; stadium summers and civic halls.', label:1},
+ {id:'alp',name:'Alpine Valley', region:'Midwest', x:607, y:193, venue:'Alpine Valley', year:1980, shows:24, note:'Ski-hill lawn amphitheatre — a summer residency of its own.', label:1},
+ {id:'min',name:'Minneapolis', region:'Midwest', x:534, y:144, venue:'Civic Center', year:1971, shows:12, note:'Upper-Midwest anchor on the northern swing.', label:0},
+ {id:'stl',name:'St. Louis', region:'Midwest', x:581, y:276, venue:'Fox / Kiel', year:1971, shows:16, note:'River-city rooms; a crossroads on the way east.', label:0},
+ {id:'det',name:'Detroit', region:'Midwest', x:690, y:199, venue:'Cobo / Pontiac', year:1971, shows:20, note:'Industrial Midwest stop with a loyal, loud crowd.', label:1},
+ {id:'buf',name:'Buffalo', region:'Northeast', x:754, y:187, venue:'Memorial Aud.', year:1970, shows:14, note:'Cold-weather northeastern room; a spring gateway.', label:0},
+ {id:'ith',name:'Ithaca', region:'Northeast', x:790, y:197, venue:'Barton Hall', year:1977, shows:3, note:'A single celebrated campus gymnasium night, endlessly retold.', label:0},
+ {id:'nyc',name:'New York', region:'Northeast', x:828, y:233, venue:'Madison Square Garden', year:1967, shows:70, note:'The eastern cathedral; the archetypal multi-night residency.', label:1},
+ {id:'phl',name:'Philadelphia', region:'Northeast', x:810, y:249, venue:'The Spectrum', year:1968, shows:52, note:'A perennial northeastern stand across two decades.', label:1},
+ {id:'dc', name:'Washington', region:'Northeast', x:782, y:270, venue:'Capital Centre', year:1970, shows:30, note:'Mid-Atlantic hub; suburban arena residencies.', label:1},
+ {id:'bos',name:'Boston', region:'Northeast', x:873, y:198, venue:'Boston Garden', year:1969, shows:44, note:'Old-barn acoustics; a college-town devotion.', label:1},
+ {id:'hfd',name:'Hartford', region:'Northeast', x:848, y:211, venue:'Civic Center', year:1977, shows:26, note:'Reliable New England civic-hall stand.', label:0},
+ {id:'atl',name:'Atlanta', region:'South', x:670, y:378, venue:'The Omni / Fox', year:1969, shows:22, note:'The Southern capital of the circuit; humid attention.', label:1},
+ {id:'nol',name:'New Orleans', region:'South', x:583, y:457, venue:'City Park', year:1970, shows:10, note:'A different rhythm entirely; the deep-south outlier.', label:1},
+ {id:'mia',name:'Miami', region:'South', x:734, y:544, venue:'Sportatorium', year:1974, shows:8, note:'The far tip of the peninsula — end of the line, south.', label:1},
+ {id:'aus',name:'Austin', region:'South', x:466, y:450, venue:'Manor Downs', year:1972, shows:6, note:'A Texas hill-country stop with its own local weather.', label:1},
+ {id:'eng',name:'Englishtown', region:'Northeast', x:825, y:239, venue:'Raceway', year:1977, shows:2, note:'A one-off megashow on a raceway; folklore-scale crowd.', label:0}
+];
+var CITY_BY_ID = {}; CITIES.forEach(function(c){CITY_BY_ID[c.id]=c;});
+
+/* Anchor tour legs (illustrative order) */
+var TOURS = {
+ 1970:['sf','buf','bos','phl','nyc','dc'],
+ 1972:['sf','pdx','den','min','chi','det','nyc'],
+ 1974:['sf','la','pdx','sea','eug'],
+ 1977:['sf','ith','buf','hfd','bos','phl','nyc','eng'],
+ 1980:['sf','nol','atl','dc','phl','nyc','bos'],
+ 1982:['sf','den','alp','chi','stl'],
+ 1985:['sf','oak','tel','den','chi'],
+ 1987:['sf','tel','alp','chi','phl','nyc','bos'],
+ 1989:['sf','lv','phx','den','chi','atl','phl','nyc'],
+ 1991:['oak','lv','den','alp','chi','bos','nyc','dc'],
+ 1993:['sf','lv','phx','den','chi','dc','phl','nyc'],
+ 1995:['sf','lv','stl','chi','det','nyc','bos']
+};
+var ANCHORS = Object.keys(TOURS).map(Number).sort(function(a,b){return a-b;});
+function tourForYear(y){ var pick=ANCHORS[0]; for(var i=0;i<ANCHORS.length;i++){ if(ANCHORS[i]<=y) pick=ANCHORS[i]; } return pick; }
+
+/* Residency ribbons (illustrative) */
+var VENUES = [
+ {v:'Winterland', city:'San Francisco', region:'West', s:1966, e:1978, nights:62},
+ {v:'Fillmore West', city:'San Francisco', region:'West', s:1968, e:1971, nights:26},
+ {v:'Red Rocks', city:'Denver', region:'Mountain', s:1972, e:1978, nights:20},
+ {v:'The Spectrum', city:'Philadelphia', region:'Northeast', s:1968, e:1989, nights:45},
+ {v:'Madison Square Garden', city:'New York', region:'Northeast', s:1979, e:1994, nights:58},
+ {v:'Capital Centre', city:'Washington', region:'Northeast', s:1973, e:1988, nights:29},
+ {v:'Boston Garden', city:'Boston', region:'Northeast', s:1979, e:1994, nights:41},
+ {v:'Alpine Valley', city:'East Troy, WI', region:'Midwest', s:1980, e:1989, nights:24},
+ {v:'Oakland Coliseum', city:'Oakland', region:'West', s:1979, e:1994, nights:31},
+ {v:'Frost Amphitheatre', city:'Stanford', region:'West', s:1982, e:1989, nights:17}
+];
+
+/* Seasonal emphasis matrix (illustrative, 0-1) */
+var SEASON = {
+ West:      [.80,.50,.32,.30,.42,.70,.60,.62,.70,.40,.30,.90],
+ Mountain:  [.10,.10,.20,.32,.52,.82,.72,.62,.50,.22,.10,.10],
+ Midwest:   [.10,.12,.22,.34,.44,.72,.84,.74,.60,.42,.20,.12],
+ South:     [.22,.32,.55,.62,.42,.20,.10,.10,.32,.52,.62,.30],
+ Northeast: [.20,.30,.60,.84,.60,.40,.32,.42,.72,.84,.60,.30]
+};
+var MONTHS=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
+
+/* ---------------- STATE ---------------- */
+var state = { year:1977, region:'all', view:'map' };
+var SVGNS='http://www.w3.org/2000/svg';
+var $=function(s){return document.querySelector(s);};
+
+/* ---------------- MAP: build cities + residency arcs ---------------- */
+var cityLayer=$('#cityLayer'), resLayer=$('#resLayer');
+
+// residency arcs between residency venue-cities (visual flourish)
+VENUES.forEach(function(vn){
+  var c = CITIES.filter(function(c){return c.venue.indexOf(vn.v)>=0 || c.name===vn.city;})[0];
+  if(!c) return;
+  var span = vn.e - vn.s;
+  var r = 14 + span*1.6;
+  var col = REGION_COLOR[vn.region];
+  var p=document.createElementNS(SVGNS,'path');
+  var x=c.x, y=c.y;
+  p.setAttribute('d','M'+(x-r)+','+y+' A'+r+','+r+' 0 0 1 '+(x+r)+','+y);
+  p.setAttribute('class','res-arc');
+  p.setAttribute('stroke',col);
+  p.setAttribute('stroke-width', Math.max(2, vn.nights/14));
+  resLayer.appendChild(p);
+});
+
+CITIES.forEach(function(c){
+  var g=document.createElementNS(SVGNS,'g');
+  g.setAttribute('class','city');
+  g.setAttribute('data-id',c.id);
+  g.setAttribute('data-region',c.region);
+  g.setAttribute('tabindex','0');
+  g.setAttribute('role','img');
+  g.setAttribute('aria-label', c.name+', '+REGION_LABEL[c.region]+'. Anchor venue '+c.venue+'. Illustrative first year '+c.year+', illustrative '+c.shows+' shows.');
+  var r = 3 + c.shows/70*6.5;
+  var halo=document.createElementNS(SVGNS,'circle');
+  halo.setAttribute('class','halo'); halo.setAttribute('cx',c.x); halo.setAttribute('cy',c.y);
+  halo.setAttribute('r', r+7); halo.setAttribute('fill','none');
+  halo.setAttribute('stroke',REGION_COLOR[c.region]); halo.setAttribute('stroke-width','1.5'); halo.setAttribute('opacity','.6');
+  var core=document.createElementNS(SVGNS,'circle');
+  core.setAttribute('class','core'); core.setAttribute('cx',c.x); core.setAttribute('cy',c.y);
+  core.setAttribute('r', r); core.setAttribute('fill',REGION_COLOR[c.region]);
+  g.appendChild(halo); g.appendChild(core);
+  if(c.label){
+    var t=document.createElementNS(SVGNS,'text');
+    t.setAttribute('class','citylabel');
+    var above = c.y>110;
+    t.setAttribute('x', c.x + (c.x>820? -6 : 9));
+    t.setAttribute('y', c.y + (above? -8 : 16));
+    if(c.x>820) t.setAttribute('text-anchor','end');
+    t.textContent=c.name;
+    g.appendChild(t);
+  }
+  cityLayer.appendChild(g);
+
+  var show=function(){ showTip(c, core); };
+  var hide=function(){ hideTip(); };
+  g.addEventListener('mouseenter',show);
+  g.addEventListener('mousemove',show);
+  g.addEventListener('mouseleave',hide);
+  g.addEventListener('focus',show);
+  g.addEventListener('blur',hide);
+});
+
+/* ---------------- TOOLTIP ---------------- */
+var tip=$('#tip'), mapshell=$('.mapshell');
+function showTip(c, coreEl){
+  var svg=$('#usmap');
+  var vb=svg.viewBox.baseVal;
+  var rect=svg.getBoundingClientRect();
+  var scaleX=rect.width/vb.width, scaleY=rect.height/vb.height;
+  var px=c.x*scaleX, py=c.y*scaleY;
+  tip.innerHTML='<h4>'+c.name+'</h4>'+
+    '<span class="region-tag" style="color:'+REGION_COLOR[c.region]+'">'+REGION_LABEL[c.region]+'</span>'+
+    '<dl><dt>Venue</dt><dd>'+c.venue+'</dd>'+
+    '<dt>First yr</dt><dd>'+c.year+'</dd>'+
+    '<dt>Shows</dt><dd>~'+c.shows+'</dd></dl>'+
+    '<p style="margin:8px 0 0;font-size:12px;color:#5c4f3c">'+c.note+'</p>'+
+    '<div class="il">Illustrative sample figures</div>';
+  tip.classList.add('show');
+  var tw=tip.offsetWidth, th=tip.offsetHeight;
+  var left=px+16, top=py-th-10;
+  if(left+tw>rect.width-8) left=px-tw-16;
+  if(left<8) left=8;
+  if(top<8) top=py+18;
+  tip.style.left=left+'px'; tip.style.top=top+'px';
+}
+function hideTip(){ tip.classList.remove('show'); }
+
+/* ---------------- RENDER: apply state ---------------- */
+function visible(c){ return (state.region==='all'||c.region===state.region) && c.year<=state.year; }
+
+function applyState(){
+  // dots
+  document.querySelectorAll('.city').forEach(function(g){
+    var c=CITY_BY_ID[g.getAttribute('data-id')];
+    g.classList.toggle('hidden', !visible(c));
+  });
+  // route
+  buildRoute();
+  // list + table
+  renderCards();
+  renderTable();
+  // caption
+  var ty=tourForYear(state.year);
+  $('#tourCaption').innerHTML='Route shown: <strong style="color:var(--gold)">'+ty+' leg</strong>'+(ty!==state.year?' (nearest ≤ '+state.year+')':'')+' — press play to trace it';
+  $('#yearBox').textContent=state.year;
+  $('#yearRange').setAttribute('aria-valuetext', String(state.year));
+  var vis=CITIES.filter(visible).length;
+  $('#listCount').textContent=vis+' cities active by '+state.year+(state.region!=='all'?' · '+REGION_LABEL[state.region]:'');
+}
+
+/* ---------------- CARDS ---------------- */
+function renderCards(){
+  var grid=$('#cardGrid'); grid.innerHTML='';
+  CITIES.filter(visible).sort(function(a,b){return b.shows-a.shows;}).forEach(function(c){
+    var col=REGION_COLOR[c.region];
+    var el=document.createElement('article');
+    el.className='citycard';
+    el.style.setProperty('--west',col);
+    el.innerHTML=
+      '<span class="rtag" style="color:'+col+'">'+REGION_LABEL[c.region]+'</span>'+
+      '<h3>'+c.name+'</h3>'+
+      '<div class="venue">'+c.venue+'</div>'+
+      '<div class="meta">'+
+        '<div class="m"><span class="label" style="font-size:10px">First yr</span><span class="num">'+c.year+'</span></div>'+
+        '<div class="m" style="flex:1"><span class="label" style="font-size:10px">Shows (illus.)</span><span class="num">~'+c.shows+'</span>'+
+          '<div class="bar"><i style="width:'+Math.min(100,c.shows/92*100)+'%;background:'+col+'"></i></div></div>'+
+      '</div>'+
+      '<p class="note">'+c.note+'</p>';
+    el.querySelector('.citycard, &::before');
+    el.style.setProperty('--rc',col);
+    // color the left bar via ::before override
+    el.insertAdjacentHTML('afterbegin','<style>#tmp{}</style>');
+    el.querySelector('style').remove();
+    el.firstChild; 
+    el.setAttribute('style','--west:'+col);
+    grid.appendChild(el);
+  });
+}
+
+/* ---------------- TABLE ---------------- */
+function renderTable(){
+  var tb=$('#tableBody'); tb.innerHTML='';
+  CITIES.filter(visible).sort(function(a,b){return a.name.localeCompare(b.name);}).forEach(function(c){
+    var tr=document.createElement('tr');
+    tr.innerHTML=
+      '<th scope="row"><span class="rd" style="background:'+REGION_COLOR[c.region]+'"></span>'+c.name+'</th>'+
+      '<td>'+REGION_LABEL[c.region]+'</td>'+
+      '<td>'+c.venue+'</td>'+
+      '<td class="num-cell">'+c.year+'</td>'+
+      '<td class="num-cell">~'+c.shows+'</td>'+
+      '<td>'+c.note+'</td>';
+    tb.appendChild(tr);
+  });
+}
+
+/* ---------------- ROUTE PLAYBACK ---------------- */
+var routePath=$('#routePath'), routeGhost=$('#routeGhost'), marker=$('#marker');
+var routeLen=0, playing=false, rafId=null, lastT=0, dist=0;
+var SPEED=170; // px per second along the path
+
+function tourPoints(){
+  var ids=TOURS[tourForYear(state.year)];
+  return ids.map(function(id){ return CITY_BY_ID[id]; }).filter(Boolean);
+}
+function buildRoute(){
+  var pts=tourPoints();
+  if(pts.length<2){ routePath.setAttribute('d',''); routeGhost.setAttribute('d',''); return; }
+  var d='M'+pts[0].x+','+pts[0].y;
+  for(var i=1;i<pts.length;i++) d+=' L'+pts[i].x+','+pts[i].y;
+  routePath.setAttribute('d',d);
+  routeGhost.setAttribute('d',d);
+  routeLen=routePath.getTotalLength();
+  resetRoute();
+}
+function resetRoute(){
+  dist=0;
+  routePath.style.strokeDasharray=routeLen;
+  routePath.style.strokeDashoffset=routeLen;
+  var p0=routePath.getPointAtLength(0);
+  marker.setAttribute('cx',p0.x); marker.setAttribute('cy',p0.y);
+}
+function frame(t){
+  if(!playing) return;
+  if(!lastT) lastT=t;
+  var dt=(t-lastT)/1000; lastT=t;
+  dist += SPEED*dt;
+  if(dist>=routeLen){ dist=routeLen; }
+  routePath.style.strokeDashoffset=(routeLen-dist);
+  var p=routePath.getPointAtLength(dist);
+  marker.setAttribute('cx',p.x); marker.setAttribute('cy',p.y);
+  if(dist>=routeLen){ pause(); return; }
+  rafId=requestAnimationFrame(frame);
+}
+function play(){
+  if(routeLen<=0) return;
+  if(dist>=routeLen) resetRoute();
+  playing=true; lastT=0;
+  $('#playIcon').textContent='❚❚'; $('#playTxt').textContent='Pause'; $('#playBtn').setAttribute('aria-pressed','true');
+  rafId=requestAnimationFrame(frame);
+}
+function pause(){
+  playing=false; if(rafId) cancelAnimationFrame(rafId);
+  $('#playIcon').textContent='▶'; $('#playTxt').textContent='Play route'; $('#playBtn').setAttribute('aria-pressed','false');
+}
+$('#playBtn').addEventListener('click',function(){ playing?pause():play(); });
+
+/* ---------------- CONTROLS WIRING ---------------- */
+$('#yearRange').addEventListener('input',function(e){
+  state.year=parseInt(e.target.value,10);
+  pause();
+  applyState();
+});
+$('#regionChips').addEventListener('click',function(e){
+  var b=e.target.closest('.chip'); if(!b) return;
+  state.region=b.getAttribute('data-region');
+  Array.prototype.forEach.call(this.querySelectorAll('.chip'),function(c){ c.setAttribute('aria-pressed', c===b?'true':'false'); });
+  applyState();
+});
+document.querySelector('.viewtabs').addEventListener('click',function(e){
+  var b=e.target.closest('button'); if(!b) return;
+  state.view=b.getAttribute('data-view');
+  Array.prototype.forEach.call(this.querySelectorAll('button'),function(x){ x.setAttribute('aria-pressed', x===b?'true':'false'); });
+  ['map','list','table'].forEach(function(v){ $('#view-'+v).classList.toggle('on', v===state.view); });
+});
+
+/* ---------------- RIBBON CHART ---------------- */
+(function buildRibbons(){
+  var svg=$('#ribbonSvg');
+  var W=1000,H=430, padL=200, padR=30, top=34, rowH=36;
+  var yA=1965, yB=1996, innerW=W-padL-padR;
+  function xOf(y){ return padL + (y-yA)/(yB-yA)*innerW; }
+  // axis grid
+  for(var yr=1965; yr<=1995; yr+=5){
+    var gx=xOf(yr);
+    var ln=document.createElementNS(SVGNS,'line');
+    ln.setAttribute('x1',gx); ln.setAttribute('x2',gx); ln.setAttribute('y1',top-8); ln.setAttribute('y2', top+VENUES.length*rowH+4);
+    ln.setAttribute('stroke','rgba(244,236,224,.10)'); svg.appendChild(ln);
+    var tx=document.createElementNS(SVGNS,'text');
+    tx.setAttribute('class','axis'); tx.setAttribute('x',gx); tx.setAttribute('y',top-14); tx.setAttribute('text-anchor','middle');
+    tx.textContent="’"+String(yr).slice(2); svg.appendChild(tx);
+  }
+  // defs gradient
+  var defs=document.createElementNS(SVGNS,'defs');
+  defs.innerHTML='<linearGradient id="ribG" x1="0" x2="1" y1="0" y2="0">'+
+    '<stop offset="0" stop-color="#9b5de5" stop-opacity=".95"/>'+
+    '<stop offset=".5" stop-color="#3ac6d6" stop-opacity=".95"/>'+
+    '<stop offset="1" stop-color="#ffca3a" stop-opacity=".95"/></linearGradient>';
+  svg.appendChild(defs);
+
+  VENUES.forEach(function(vn,i){
+    var y=top + i*rowH + rowH/2;
+    var x1=xOf(vn.s), x2=xOf(vn.e);
+    var h= 7 + vn.nights/62*22;
+    var col=REGION_COLOR[vn.region];
+    // ribbon body
+    var rect=document.createElementNS(SVGNS,'rect');
+    rect.setAttribute('class','rib');
+    rect.setAttribute('x',x1); rect.setAttribute('y', y-h/2);
+    rect.setAttribute('width', Math.max(6,x2-x1)); rect.setAttribute('height',h);
+    rect.setAttribute('rx', h/2);
+    rect.setAttribute('fill', col); rect.setAttribute('opacity','.82');
+    var tt=document.createElementNS(SVGNS,'title');
+    tt.textContent=vn.v+' — '+vn.city+' · '+vn.s+'–'+vn.e+' · ~'+vn.nights+' nights (illustrative)';
+    rect.appendChild(tt);
+    svg.appendChild(rect);
+    // spectral flash cap at end
+    var cap=document.createElementNS(SVGNS,'circle');
+    cap.setAttribute('cx',x2); cap.setAttribute('cy',y); cap.setAttribute('r', Math.max(3,h/2));
+    cap.setAttribute('fill','url(#ribG)'); cap.setAttribute('opacity','.9'); svg.appendChild(cap);
+    // labels
+    var vl=document.createElementNS(SVGNS,'text');
+    vl.setAttribute('class','vlabel'); vl.setAttribute('x',padL-16); vl.setAttribute('y',y-2); vl.setAttribute('text-anchor','end');
+    vl.textContent=vn.v; svg.appendChild(vl);
+    var vc=document.createElementNS(SVGNS,'text');
+    vc.setAttribute('class','vcity'); vc.setAttribute('x',padL-16); vc.setAttribute('y',y+11); vc.setAttribute('text-anchor','end');
+    vc.textContent=vn.city; svg.appendChild(vc);
+  });
+})();
+
+/* ---------------- SEASONAL HEAT-BAND ---------------- */
+(function buildSeasonal(){
+  var svg=$('#seasonalSvg');
+  var W=1000,H=340, padL=150, padT=44, cellW=(W-padL-30)/12, rowH=44;
+  var regions=['West','Mountain','Midwest','South','Northeast'];
+  // month labels
+  MONTHS.forEach(function(m,i){
+    var tx=document.createElementNS(SVGNS,'text');
+    tx.setAttribute('class','mo'); tx.setAttribute('x', padL+i*cellW+cellW/2); tx.setAttribute('y', padT-14);
+    tx.setAttribute('text-anchor','middle'); tx.textContent=m; svg.appendChild(tx);
+  });
+  var seasonNames=[['Winter',0,2],['Spring',2,5],['Summer',5,8],['Autumn',8,11]];
+  seasonNames.forEach(function(s){
+    var x=padL+s[1]*cellW; var w=(s[2]-s[1])*cellW;
+    var tx=document.createElementNS(SVGNS,'text');
+    tx.setAttribute('class','axis'); tx.setAttribute('x', x+w/2); tx.setAttribute('y', padT-30);
+    tx.setAttribute('text-anchor','middle'); tx.textContent=s[0]; svg.appendChild(tx);
+  });
+  regions.forEach(function(rg,ri){
+    var y=padT + ri*rowH;
+    var col=REGION_COLOR[rg];
+    // row label
+    var lab=document.createElementNS(SVGNS,'text');
+    lab.setAttribute('class','rlab'); lab.setAttribute('x',padL-16); lab.setAttribute('y', y+rowH/2+4); lab.setAttribute('text-anchor','end');
+    lab.textContent=REGION_LABEL[rg]; svg.appendChild(lab);
+    var dot=document.createElementNS(SVGNS,'circle');
+    dot.setAttribute('cx',padL-8); dot.setAttribute('cy',y+rowH/2); dot.setAttribute('r',4); dot.setAttribute('fill',col); svg.appendChild(dot);
+    SEASON[rg].forEach(function(val,mi){
+      var x=padL+mi*cellW;
+      var cell=document.createElementNS(SVGNS,'rect');
+      cell.setAttribute('x',x+2); cell.setAttribute('y',y+3);
+      cell.setAttribute('width',cellW-4); cell.setAttribute('height',rowH-6);
+      cell.setAttribute('rx',5);
+      cell.setAttribute('fill',col); cell.setAttribute('opacity', 0.12+val*0.8);
+      var tt=document.createElementNS(SVGNS,'title');
+      tt.textContent=REGION_LABEL[rg]+' · '+MONTHS[mi]+' · emphasis '+Math.round(val*100)+'% (illustrative)';
+      cell.appendChild(tt);
+      svg.appendChild(cell);
+    });
+  });
+  // caption
+  var cap=document.createElementNS(SVGNS,'text');
+  cap.setAttribute('class','mo'); cap.setAttribute('x',padL); cap.setAttribute('y', padT+5*rowH+22);
+  cap.textContent='Darker = greater illustrative seasonal emphasis'; svg.appendChild(cap);
+})();
+
+/* ---------------- INIT ---------------- */
+// keyboard: space toggles play when focus not on a control
+document.addEventListener('keydown',function(e){
+  if(e.code==='Space' && state.view==='map' && document.activeElement && document.activeElement.tagName!=='INPUT' && document.activeElement.tagName!=='BUTTON'){
+    e.preventDefault(); playing?pause():play();
+  }
+});
+applyState();
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/6d9acbcfa9a2/claude-code.png b/data/artifacts/6d9acbcfa9a2/claude-code.png
new file mode 100644
index 0000000..36187cf
Binary files /dev/null and b/data/artifacts/6d9acbcfa9a2/claude-code.png differ
diff --git a/data/artifacts/6d9acbcfa9a2/qwen25-7b.html b/data/artifacts/6d9acbcfa9a2/qwen25-7b.html
new file mode 100644
index 0000000..c88fad1
--- /dev/null
+++ b/data/artifacts/6d9acbcfa9a2/qwen25-7b.html
@@ -0,0 +1,141 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Routes, Residencies &amp; Rituals</title>
+    <style>
+        body {
+            font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+            background-color: #0d0d0f;
+            color: #f5f2ea;
+            margin: 0;
+            padding: 0;
+            display: grid;
+            place-items: center;
+            min-height: 100vh;
+        }
+        .gallery {
+            width: 96%;
+            max-width: 1440px;
+            background-color: #17171c;
+            color: #f5f2ea;
+            padding: 96px;
+            gap: 24px;
+            display: grid;
+            grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+        }
+        .map {
+            width: 100%;
+            height: 500px;
+            background-color: #f7efe6;
+            border-radius: 14px;
+            overflow: hidden;
+        }
+        .card {
+            background-color: #fff9f1;
+            color: #3a2c22;
+            padding: 24px;
+            border-radius: 14px;
+            box-shadow: 0 8px 24px rgba(0,0,0,.12);
+        }
+        .card:hover {
+            box-shadow: 0 16px 48px rgba(0,0,0,.18);
+        }
+        h1, h2, h3, p {
+            margin: 0;
+        }
+        h1 { font-size: 50px; letter-spacing: .15em; }
+        h2 { font-size: 38px; }
+        h3 { font-size: 28px; }
+        p { font-size: 16px; line-height: 1.5; }
+        .legend {
+            margin-top: 40px;
+            display: grid;
+            gap: 16px;
+            font-size: 12px;
+        }
+        @keyframes fadeUp {
+            from { opacity: 0; transform: translateY(28px); }
+            to { opacity: 1; transform: none; }
+        }
+        .fade-up-enter-active, .fade-up-leave-active {
+            transition: all .7s cubic-bezier(.22,1,.36,1) both;
+        }
+        .fade-up-enter-from, .fade-up-leave-to {
+            opacity: 0;
+            transform: translateY(28px);
+        }
+    </style>
+</head>
+<body>
+    <div class="gallery">
+        <h1>Routes, Residencies &amp; Rituals</h1>
+        
+        <!-- Map -->
+        <div class="map" id="tourMap"></div>
+
+        <!-- Essays -->
+        <section class="card">
+            <h2>Pilgrimage</h2>
+            <p>Exploring the spiritual journey of Grateful Dead fans across the United States.</p>
+        </section>
+        <section class="card">
+            <h2>Parking-Lot Exchange</h2>
+            <p>An illustrated guide to the infamous parking-lot exchanges at Dead shows.</p>
+        </section>
+        <section class="card">
+            <h2>Taping Culture</h2>
+            <p>Understanding the significance of taping and sharing live performances.</p>
+        </section>
+        <section class="card">
+            <h2>Regional Identity</h2>
+            <p>How different regions developed their own unique Grateful Dead fan cultures.</p>
+        </section>
+        <section class="card">
+            <h2>Venue and Set Relationship</h2>
+            <p>The intricate connection between venue characteristics and setlist choices.</p>
+        </section>
+
+        <!-- Filters &amp; Tooltips -->
+        <div class="legend">
+            <span>Filter by Year:</span>
+            <input type="range" min="1965" max="1995" value="1970" step="1">
+            <p>Tooltip: Explore the interactive tour map for more details.</p>
+        </div>
+
+        <!-- Data Table Fallback -->
+        <table class="data-table-fallback fade-up-enter-active">
+            <thead>
+                <tr>
+                    <th>Year</th>
+                    <th>City</th>
+                    <th>Venue</th>
+                    <th>Date</th>
+                </tr>
+            </thead>
+            <tbody>
+                <tr>
+                    <td>1970</td>
+                    <td>New York City</td>
+                    <td>The Fillmore East</td>
+                    <td>March 5, 1970</td>
+                </tr>
+                <!-- Add more rows as needed -->
+            </tbody>
+        </table>
+
+        <!-- Map Animation -->
+        <script>
+            const map = document.getElementById('tourMap');
+            function animateRoute() {
+                // Simulate route animation
+                setTimeout(() => {
+                    map.style.animation = 'fadeUp .7s cubic-bezier(.22,1,.36,1) both';
+                }, 500);
+            }
+            animateRoute();
+        </script>
+    </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/6d9acbcfa9a2/qwen3-14b.html b/data/artifacts/6d9acbcfa9a2/qwen3-14b.html
new file mode 100644
index 0000000..b2ac400
--- /dev/null
+++ b/data/artifacts/6d9acbcfa9a2/qwen3-14b.html
@@ -0,0 +1,340 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Routes, Residencies & Rituals</title>
+  <style>
+    :root {
+      --bg: #0d0d0f;
+      --surface: #17171c;
+      --text: #f5f2ea;
+      --muted: #8a8578;
+      --accent: #c9a961;
+      --accent-alt: #7d6a45;
+      --card-radius: 14px;
+      --shadow-card: 0 8px 24px rgba(0,0,0,.12);
+      --shadow-hover: 0 16px 48px rgba(0,0,0,.18);
+      --glow: 0 0 24px #c9a96133;
+      --spacing-4: 4px;
+      --spacing-8: 8px;
+      --spacing-12: 12px;
+      --spacing-16: 16px;
+      --spacing-24: 24px;
+      --spacing-32: 32px;
+      --spacing-48: 48px;
+      --spacing-64: 64px;
+      --spacing-96: 96px;
+      --card-grid: repeat(auto-fit, minmax(260px, 1fr)) gap 24px;
+      --font-display: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      --font-body: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+      --caption: 12px;
+      --body: 16px;
+      --lead: 21px;
+      --h3: 28px;
+      --h2: 38px;
+      --h1: 50px;
+      --display: 67px;
+    }
+
+    * {
+      box-sizing: border-box;
+      margin: 0;
+      padding: 0;
+    }
+
+    body {
+      background: var(--bg);
+      color: var(--text);
+      font-family: var(--font-body);
+      line-height: 1.6;
+      padding: var(--spacing-96);
+      overflow-x: hidden;
+      scroll-behavior: smooth;
+    }
+
+    h1 {
+      font-family: var(--font-display);
+      font-size: var(--h1);
+      margin-bottom: var(--spacing-24);
+      letter-spacing: 0.15em;
+      text-transform: uppercase;
+    }
+
+    h2 {
+      font-family: var(--font-display);
+      font-size: var(--h2);
+      margin-bottom: var(--spacing-16);
+      letter-spacing: 0.1em;
+      color: var(--accent);
+    }
+
+    h3 {
+      font-family: var(--font-display);
+      font-size: var(--h3);
+      margin-bottom: var(--spacing-12);
+      color: var(--muted);
+    }
+
+    p {
+      font-size: var(--body);
+      margin-bottom: var(--spacing-16);
+    }
+
+    .container {
+      display: grid;
+      grid-template-columns: 1fr 3fr;
+      gap: var(--spacing-32);
+      align-items: start;
+    }
+
+    .map {
+      position: relative;
+      height: 800px;
+      background: #000;
+      border-radius: var(--card-radius);
+      box-shadow: var(--shadow-card);
+      overflow: hidden;
+    }
+
+    .map::before {
+      content: '';
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background: linear-gradient(
+        to right,
+        #12002b 0%,
+        #1e0b3d 50%,
+        #12002b 100%
+      );
+      animation: drift 18s linear infinite;
+    }
+
+    @keyframes drift {
+      0% { background-position: 0% 50%; }
+      100% { background-position: 100% 50%; }
+    }
+
+    .ribbon {
+      position: absolute;
+      background: var(--accent-alt);
+      opacity: 0.4;
+      border-radius: 4px;
+    }
+
+    .venue {
+      position: absolute;
+      background: var(--accent);
+      color: var(--text);
+      padding: var(--spacing-8);
+      border-radius: 4px;
+      font-size: var(--caption);
+      text-align: center;
+    }
+
+    .city-card {
+      background: var(--surface);
+      border-radius: var(--card-radius);
+      box-shadow: var(--shadow-card);
+      padding: var(--spacing-16);
+      margin-bottom: var(--spacing-16);
+      transition: box-shadow 150ms;
+    }
+
+    .city-card:hover {
+      box-shadow: var(--shadow-hover);
+    }
+
+    .legend {
+      background: var(--surface);
+      border-radius: var(--card-radius);
+      padding: var(--spacing-16);
+      box-shadow: var(--shadow-card);
+      font-size: var(--caption);
+      margin-bottom: var(--spacing-24);
+    }
+
+    .filters {
+      display: flex;
+      flex-wrap: wrap;
+      gap: var(--spacing-8);
+      margin-bottom: var(--spacing-24);
+    }
+
+    .filter {
+      background: var(--surface);
+      padding: var(--spacing-8) var(--spacing-12);
+      border-radius: var(--card-radius);
+      cursor: pointer;
+      transition: 0.2s;
+    }
+
+    .filter:hover {
+      background: var(--accent);
+      color: var(--text);
+    }
+
+    .year-scrubber {
+      position: relative;
+      width: 100%;
+      height: 8px;
+      background: var(--muted);
+      border-radius: 100px;
+      overflow: hidden;
+      margin-bottom: var(--spacing-16);
+    }
+
+    .scrubber-thumb {
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+      width: 16px;
+      height: 16px;
+      background: var(--accent);
+      border-radius: 50%;
+      cursor: pointer;
+      box-shadow: var(--glow);
+    }
+
+    .tooltip {
+      position: absolute;
+      background: var(--surface);
+      padding: var(--spacing-8);
+      border-radius: var(--card-radius);
+      box-shadow: var(--shadow-card);
+      font-size: var(--caption);
+      z-index: 1000;
+      pointer-events: none;
+      opacity: 0;
+      transition: opacity 200ms;
+    }
+
+    .tooltip.show {
+      opacity: 1;
+    }
+
+    .animated-route {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      pointer-events: none;
+      overflow: hidden;
+    }
+
+    .route-line {
+      position: absolute;
+      width: 100%;
+      height: 100%;
+      background: var(--accent);
+      opacity: 0.3;
+      animation: fadein 1s ease-in forwards;
+    }
+
+    @keyframes fadein {
+      from { opacity: 0; }
+      to { opacity: 1; }
+    }
+
+    .card-grid {
+      display: grid;
+      grid-template-columns: var(--card-grid);
+      gap: var(--spacing-24);
+    }
+
+    @media (max-width: 768px) {
+      .container {
+        grid-template-columns: 1fr;
+      }
+
+      .map {
+        height: 400px;
+      }
+
+      .city-card, .legend {
+        padding: var(--spacing-12);
+      }
+    }
+  </style>
+</head>
+<body>
+  <h1>Routes, Residencies & Rituals</h1>
+
+  <div class="container">
+    <div>
+      <div class="filters">
+        <div class="filter" data-filter="all">All</div>
+        <div class="filter" data-filter="spring">Spring</div>
+        <div class="filter" data-filter="summer">Summer</div>
+        <div class="filter" data-filter="fall">Fall</div>
+        <div class="filter" data-filter="winter">Winter</div>
+      </div>
+
+      <div class="year-scrubber">
+        <div class="scrubber-thumb" style="left: 50%;">1977</div>
+      </div>
+
+      <div class="map">
+        <div class="ribbon" style="top: 20%; left: 10%; width: 80%; height: 10px; transform: rotate(20deg);"></div>
+        <div class="ribbon" style="top: 50%; left: 30%; width: 60%; height: 10px; transform: rotate(-15deg);"></div>
+        <div class="ribbon" style="top: 70%; left: 50%; width: 40%; height: 10px; transform: rotate(30deg);"></div>
+        <div class="venue" style="top: 15%; left: 15%;">San Francisco</div>
+        <div class="venue" style="top: 40%; left: 30%;">New York</div>
+        <div class="venue" style="top: 65%; left: 60%;">Chicago</div>
+        <div class="venue" style="top: 80%; left: 80%;">Austin</div>
+        <div class="animated-route">
+          <div class="route-line" style="animation-delay: 0s;"></div>
+          <div class="route-line" style="animation-delay: 0.5s;"></div>
+          <div class="route-line" style="animation-delay: 1s;"></div>
+        </div>
+      </div>
+
+      <div class="legend">
+        <strong>Map Elements</strong><br>
+        <span style="display: inline-block; width: 10px; height: 10px; background: var(--accent); margin-right: 4px;"></span>Venue<br>
+        <span style="display: inline-block; width: 10px; height: 10px; background: var(--accent-alt); margin-right: 4px;"></span>Residency Band<br>
+        <span style="display: inline-block; width: 10px; height: 10px; background: var(--muted); margin-right: 4px;"></span>Seasonal Movement
+      </div>
+
+      <div class="card-grid">
+        <div class="city-card" data-season="spring">
+          <h3>San Francisco</h3>
+          <p><strong>Residencies:</strong> 12 shows, 3 weeks. A ritual of return, the city became a home away from home.</p>
+        </div>
+        <div class="city-card" data-season="summer">
+          <h3>New York</h3>
+          <p><strong>Residencies:</strong> 15 shows, 4 weeks. A crossroads of East Coast energy, where the Dead met the city.</p>
+        </div>
+        <div class="city-card" data-season="fall">
+          <h3>Chicago</h3>
+          <p><strong>Residencies:</strong> 10 shows, 2 weeks. The Windy City’s rhythm matched the band's own.</p>
+        </div>
+        <div class="city-card" data-season="winter">
+          <h3>Austin</h3>
+          <p><strong>Residencies:</strong> 5 shows, 1 week. A winter ritual, where the music was carried in the cold.</p>
+        </div>
+      </div>
+    </div>
+
+    <div>
+      <h2>Pilgrimage</h2>
+      <p>Each tour was a journey of faith, not only for the band but for the fans who followed. The road was a sacred path, where each stop was a gathering of the faithful.</p>
+
+      <h2>Parking-Lot Exchange</h2>
+      <p>Before the show, the parking lot was a marketplace of goods, stories, and spirit. It was a space of ritual exchange, where the music was traded in more than just sound.</p>
+
+      <h2>Taping Culture</h2>
+      <p>The taping of shows was a sacred act. Fans preserved every note, every moment, as if the music might never return. The tapes became the holy texts of the Dead.</p>
+
+      <h2>Regional Identity</h2>
+      <p>Each region left its mark on the Dead's music. The West Coast's openness, the East Coast's intensity, the South's soul — all found their way into the sound.</p>
+
+      <h2>Venue & Set</h2>
+      <p>The venue shaped the set, and the set shaped the venue. Each stage was a unique space, where the band and the crowd co-created a moment in time.</p>
+    </div>
+  </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/a5990564b1ee/claude-code.html b/data/artifacts/a5990564b1ee/claude-code.html
new file mode 100644
index 0000000..d33d118
--- /dev/null
+++ b/data/artifacts/a5990564b1ee/claude-code.html
@@ -0,0 +1,837 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>The Long Strange Archive — A Digital Exhibition</title>
+<style>
+  :root{
+    --charcoal:#17151a;
+    --charcoal-2:#211e26;
+    --charcoal-3:#2b2731;
+    --parchment:#efe6d2;
+    --parchment-dim:#c7bda6;
+    --oxblood:#7d2130;
+    --oxblood-bright:#a8323f;
+    --violet:#7d4bff;
+    --violet-glow:#9a6cff;
+    --muted:#8f8778;
+    --hairline:rgba(239,230,210,.14);
+    --ink:#f5f0e2;
+    --shadow-card:0 8px 24px rgba(0,0,0,.42);
+    --shadow-hover:0 18px 52px rgba(0,0,0,.55);
+    --sp-1:4px;--sp-2:8px;--sp-3:12px;--sp-4:16px;--sp-6:24px;--sp-8:32px;--sp-12:48px;--sp-16:64px;--sp-24:96px;
+    --serif:'Didot','Bodoni MT','Playfair Display',Georgia,serif;
+    --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+  }
+  *{box-sizing:border-box;margin:0;padding:0}
+  html{scroll-behavior:smooth}
+  body{
+    background:var(--charcoal);
+    color:var(--ink);
+    font-family:var(--sans);
+    font-size:16px;
+    line-height:1.6;
+    -webkit-font-smoothing:antialiased;
+    overflow-x:hidden;
+  }
+  ::selection{background:var(--violet);color:#fff}
+  a{color:inherit;text-decoration:none}
+
+  /* ambient drifting field */
+  .ambient{
+    position:fixed;inset:0;z-index:0;pointer-events:none;
+    background:
+      radial-gradient(60% 50% at 18% 12%, rgba(125,75,255,.16), transparent 60%),
+      radial-gradient(55% 45% at 82% 22%, rgba(125,33,48,.20), transparent 62%),
+      radial-gradient(70% 60% at 50% 108%, rgba(125,75,255,.10), transparent 60%);
+    background-size:200% 200%,200% 200%,200% 200%;
+    animation:drift 26s ease-in-out infinite alternate;
+    opacity:.9;
+  }
+  @keyframes drift{
+    0%{background-position:0% 0%,100% 0%,50% 100%}
+    100%{background-position:30% 40%,70% 30%,40% 60%}
+  }
+
+  .wrap{position:relative;z-index:1;max-width:1180px;margin:0 auto;padding:0 var(--sp-6)}
+
+  /* labels */
+  .kicker{
+    font-family:var(--sans);
+    text-transform:uppercase;
+    font-size:12px;
+    letter-spacing:.15em;
+    color:var(--muted);
+    font-weight:600;
+  }
+  .kicker.violet{color:var(--violet-glow)}
+  .kicker.ox{color:var(--oxblood-bright)}
+
+  h1,h2,h3{font-family:var(--serif);font-weight:400;line-height:1.05;letter-spacing:.01em}
+
+  /* entrances */
+  .reveal{opacity:0;transform:translateY(28px)}
+  .reveal.in{animation:fadeUp .7s cubic-bezier(.22,1,.36,1) both}
+  @keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
+
+  /* ---------- top bar ---------- */
+  .topbar{
+    position:sticky;top:0;z-index:40;
+    display:flex;align-items:center;justify-content:space-between;gap:var(--sp-4);
+    padding:var(--sp-3) var(--sp-6);
+    background:rgba(23,21,26,.72);
+    backdrop-filter:blur(14px);
+    border-bottom:1px solid var(--hairline);
+  }
+  .brand{display:flex;align-items:center;gap:var(--sp-3);font-family:var(--serif);font-size:19px;letter-spacing:.02em}
+  .bolt{width:26px;height:26px;flex:none}
+  .navlinks{display:flex;gap:var(--sp-6)}
+  .navlinks a{font-size:12px;text-transform:uppercase;letter-spacing:.14em;color:var(--parchment-dim);padding:var(--sp-1) 0;border-bottom:1px solid transparent;transition:color .2s,border-color .2s}
+  .navlinks a:hover,.navlinks a:focus-visible{color:var(--ink);border-color:var(--oxblood-bright);outline:none}
+  .motion-toggle{
+    display:flex;align-items:center;gap:var(--sp-2);
+    font-size:11px;text-transform:uppercase;letter-spacing:.12em;color:var(--parchment-dim);
+    background:var(--charcoal-3);border:1px solid var(--hairline);border-radius:40px;
+    padding:6px 12px;cursor:pointer;transition:border-color .2s,color .2s;
+  }
+  .motion-toggle:hover,.motion-toggle:focus-visible{border-color:var(--violet);color:var(--ink);outline:none}
+  .motion-toggle .dot{width:8px;height:8px;border-radius:50%;background:var(--violet-glow);box-shadow:0 0 10px var(--violet-glow)}
+
+  /* ---------- hero ---------- */
+  .hero{position:relative;padding:var(--sp-24) 0 var(--sp-16);text-align:center}
+  .hero .plate{
+    position:relative;display:inline-block;margin:0 auto var(--sp-8);
+    width:180px;height:180px;
+  }
+  .hero h1{
+    font-size:clamp(48px,9vw,92px);
+    letter-spacing:.005em;
+    margin-bottom:var(--sp-6);
+    text-shadow:0 0 42px rgba(125,75,255,.18);
+  }
+  .hero h1 em{font-style:italic;color:var(--oxblood-bright)}
+  .lede{
+    max-width:640px;margin:0 auto var(--sp-8);
+    font-size:clamp(18px,2.2vw,21px);color:var(--parchment-dim);line-height:1.7;
+  }
+  .meta-row{display:flex;gap:var(--sp-8);justify-content:center;flex-wrap:wrap;color:var(--muted)}
+  .meta-row div{font-size:12px;letter-spacing:.12em;text-transform:uppercase}
+  .meta-row strong{display:block;font-family:var(--serif);font-size:19px;color:var(--parchment);text-transform:none;letter-spacing:normal;margin-top:2px}
+
+  /* ---------- section scaffolding ---------- */
+  section{position:relative;padding:var(--sp-24) 0;border-top:1px solid var(--hairline)}
+  .sec-head{max-width:720px;margin-bottom:var(--sp-12)}
+  .sec-head h2{font-size:clamp(30px,4.6vw,44px);margin:var(--sp-3) 0}
+  .sec-head p{color:var(--parchment-dim);font-size:18px;line-height:1.7}
+
+  /* ---------- curatorial statement ---------- */
+  .statement{
+    background:linear-gradient(180deg,var(--charcoal-2),var(--charcoal));
+    border:1px solid var(--hairline);border-radius:14px;
+    padding:var(--sp-16) var(--sp-12);position:relative;overflow:hidden;
+  }
+  .statement:before{
+    content:"“";position:absolute;top:-30px;left:24px;
+    font-family:var(--serif);font-size:220px;color:var(--oxblood);opacity:.16;line-height:1;
+  }
+  .statement .body{max-width:760px;position:relative}
+  .statement .body p{font-size:clamp(19px,2.3vw,23px);line-height:1.7;color:var(--parchment);margin-bottom:var(--sp-6);font-family:var(--serif)}
+  .statement .body p.small{font-family:var(--sans);font-size:16px;color:var(--parchment-dim)}
+  .sign{margin-top:var(--sp-8);font-size:13px;letter-spacing:.06em;color:var(--muted)}
+  .sign b{color:var(--parchment);font-weight:600}
+
+  /* ---------- timeline ---------- */
+  .timeline-scroll{
+    overflow-x:auto;padding-bottom:var(--sp-6);
+    scrollbar-width:thin;scrollbar-color:var(--oxblood) transparent;
+  }
+  .timeline-scroll::-webkit-scrollbar{height:8px}
+  .timeline-scroll::-webkit-scrollbar-thumb{background:var(--oxblood);border-radius:20px}
+  .timeline-scroll::-webkit-scrollbar-track{background:var(--charcoal-3)}
+  .timeline{position:relative;display:flex;gap:0;min-width:1000px;padding:var(--sp-12) 0 var(--sp-6)}
+  .timeline:before{
+    content:"";position:absolute;top:calc(var(--sp-12) + 6px);left:0;right:0;height:2px;
+    background:linear-gradient(90deg,var(--oxblood),var(--violet));
+  }
+  .tl-node{flex:1;min-width:180px;position:relative;padding:0 var(--sp-4)}
+  .tl-node .dot{
+    width:15px;height:15px;border-radius:50%;background:var(--charcoal);
+    border:2px solid var(--violet-glow);position:relative;z-index:2;margin-bottom:var(--sp-6);
+    transition:transform .2s,box-shadow .2s,background .2s;
+  }
+  .tl-node:hover .dot,.tl-node:focus-within .dot{transform:scale(1.35);background:var(--violet);box-shadow:0 0 20px var(--violet-glow)}
+  .tl-year{font-family:var(--serif);font-size:26px;color:var(--parchment)}
+  .tl-era{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--oxblood-bright);margin:var(--sp-2) 0 var(--sp-3)}
+  .tl-body{font-size:13.5px;color:var(--parchment-dim);line-height:1.6}
+
+  /* ---------- stations ---------- */
+  .stations{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:var(--sp-6)}
+  .station{
+    background:var(--charcoal-2);border:1px solid var(--hairline);border-radius:14px;
+    overflow:hidden;box-shadow:var(--shadow-card);
+    display:flex;flex-direction:column;transition:transform .25s cubic-bezier(.22,1,.36,1),box-shadow .25s,border-color .25s;
+  }
+  .station:hover{transform:translateY(-6px);box-shadow:var(--shadow-hover);border-color:rgba(125,75,255,.4)}
+  .art{height:190px;position:relative;overflow:hidden;background:var(--charcoal-3)}
+  .art svg{position:absolute;inset:0;width:100%;height:100%;transition:transform .5s ease}
+  .station:hover .art svg{transform:scale(1.06)}
+  .art .tag{
+    position:absolute;left:var(--sp-3);top:var(--sp-3);z-index:2;
+    font-size:10px;letter-spacing:.14em;text-transform:uppercase;
+    background:rgba(23,21,26,.7);border:1px solid var(--hairline);
+    padding:4px 9px;border-radius:30px;color:var(--parchment)
+  }
+  .station .pad{padding:var(--sp-6);display:flex;flex-direction:column;gap:var(--sp-3);flex:1}
+  .station h3{font-size:24px}
+  .station .blurb{font-size:14.5px;color:var(--parchment-dim);line-height:1.6}
+  .station .count{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-top:auto}
+
+  /* object labels (expandable) */
+  .labels{margin-top:var(--sp-6);display:flex;flex-direction:column;gap:var(--sp-3)}
+  .obj{border:1px solid var(--hairline);border-radius:10px;background:var(--charcoal-3);overflow:hidden}
+  .obj-btn{
+    width:100%;text-align:left;background:none;border:none;color:var(--ink);cursor:pointer;
+    display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-3) var(--sp-4);font-family:var(--sans);
+    transition:background .2s;
+  }
+  .obj-btn:hover,.obj-btn:focus-visible{background:rgba(125,75,255,.09);outline:none}
+  .obj-swatch{width:34px;height:34px;border-radius:6px;flex:none;overflow:hidden}
+  .obj-swatch svg{width:100%;height:100%;display:block}
+  .obj-title{font-size:14px;flex:1;line-height:1.3}
+  .obj-title span{display:block;font-size:11px;color:var(--muted);letter-spacing:.06em;margin-top:2px}
+  .chev{transition:transform .25s;color:var(--violet-glow);font-size:13px}
+  .obj.open .chev{transform:rotate(90deg)}
+  .obj-panel{max-height:0;overflow:hidden;transition:max-height .35s ease}
+  .obj-inner{padding:0 var(--sp-4) var(--sp-4);border-top:1px solid var(--hairline)}
+  .facts{display:flex;flex-wrap:wrap;gap:var(--sp-4);margin:var(--sp-3) 0}
+  .facts div{font-size:11px}
+  .facts b{display:block;text-transform:uppercase;letter-spacing:.11em;color:var(--oxblood-bright);margin-bottom:2px}
+  .facts span{color:var(--parchment-dim)}
+  .interp{font-size:14px;line-height:1.65;color:var(--parchment);font-family:var(--serif)}
+
+  /* ---------- listening room ---------- */
+  .listen{
+    display:grid;grid-template-columns:1.1fr .9fr;gap:var(--sp-12);align-items:center;
+    background:linear-gradient(135deg,var(--charcoal-2),var(--charcoal-3));
+    border:1px solid var(--hairline);border-radius:14px;padding:var(--sp-12);
+  }
+  .player{background:var(--charcoal);border:1px solid var(--hairline);border-radius:12px;padding:var(--sp-6);box-shadow:var(--shadow-card)}
+  .now{display:flex;align-items:center;gap:var(--sp-4);margin-bottom:var(--sp-4)}
+  .now .disc{width:56px;height:56px;border-radius:50%;flex:none;background:conic-gradient(var(--oxblood),var(--violet),var(--oxblood));position:relative}
+  .now .disc:after{content:"";position:absolute;inset:22px;border-radius:50%;background:var(--charcoal);border:2px solid var(--hairline)}
+  .now.playing .disc{animation:spin 4s linear infinite}
+  @keyframes spin{to{transform:rotate(360deg)}}
+  .now-meta strong{font-family:var(--serif);font-size:19px;display:block}
+  .now-meta span{font-size:12px;color:var(--muted);letter-spacing:.05em}
+  .bars{display:flex;align-items:flex-end;gap:3px;height:46px;margin:var(--sp-4) 0}
+  .bars i{flex:1;background:linear-gradient(var(--violet-glow),var(--oxblood));border-radius:2px;height:20%;opacity:.5}
+  .now.playing + .bars i{animation:eq 1.1s ease-in-out infinite}
+  .bars i:nth-child(2n){animation-delay:.15s}
+  .bars i:nth-child(3n){animation-delay:.3s}
+  .bars i:nth-child(4n){animation-delay:.45s}
+  @keyframes eq{0%,100%{height:18%;opacity:.4}50%{height:95%;opacity:1}}
+  .transport{display:flex;align-items:center;gap:var(--sp-3);margin-top:var(--sp-2)}
+  .playbtn{
+    width:46px;height:46px;border-radius:50%;border:1px solid var(--violet);background:var(--charcoal-3);
+    color:var(--ink);cursor:pointer;font-size:16px;display:grid;place-items:center;transition:background .2s,box-shadow .2s
+  }
+  .playbtn:hover,.playbtn:focus-visible{background:var(--violet);box-shadow:0 0 18px var(--violet-glow);outline:none}
+  .tracklist{display:flex;flex-direction:column;gap:var(--sp-1);margin-top:var(--sp-4)}
+  .track{
+    display:flex;justify-content:space-between;gap:var(--sp-4);align-items:center;
+    padding:var(--sp-2) var(--sp-3);border-radius:8px;cursor:pointer;font-size:13.5px;
+    border:1px solid transparent;transition:background .18s,border-color .18s;color:var(--parchment-dim)
+  }
+  .track:hover,.track:focus-visible{background:rgba(125,75,255,.08);border-color:var(--hairline);color:var(--ink);outline:none}
+  .track.active{background:rgba(125,33,48,.22);border-color:var(--oxblood);color:var(--ink)}
+  .track .len{color:var(--muted);font-variant-numeric:tabular-nums}
+
+  /* ---------- spotlight ---------- */
+  .spotlight{
+    background:radial-gradient(120% 120% at 80% 0%,rgba(125,75,255,.16),transparent 55%),var(--charcoal-2);
+    border:1px solid var(--hairline);border-radius:14px;padding:var(--sp-12);position:relative;overflow:hidden;min-height:280px;
+  }
+  .spot-item{display:grid;grid-template-columns:150px 1fr;gap:var(--sp-8);align-items:center}
+  .spot-art{width:150px;height:150px;border-radius:12px;overflow:hidden;border:1px solid var(--hairline);box-shadow:var(--shadow-card)}
+  .spot-art svg{width:100%;height:100%;display:block}
+  .spot-body h3{font-size:28px;margin-bottom:var(--sp-2)}
+  .spot-body .m{font-size:12px;text-transform:uppercase;letter-spacing:.12em;color:var(--oxblood-bright);margin-bottom:var(--sp-4)}
+  .spot-body p{color:var(--parchment-dim);line-height:1.7;max-width:560px}
+  .spot-dots{display:flex;gap:var(--sp-2);margin-top:var(--sp-8)}
+  .spot-dots button{width:10px;height:10px;border-radius:50%;border:none;background:var(--charcoal-3);cursor:pointer;transition:background .2s,transform .2s}
+  .spot-dots button.on{background:var(--violet-glow);transform:scale(1.3)}
+  .spot-dots button:hover{background:var(--oxblood-bright)}
+
+  /* ---------- venue map ---------- */
+  .mapwrap{display:grid;grid-template-columns:1.3fr .7fr;gap:var(--sp-12);align-items:start}
+  .map{background:var(--charcoal-2);border:1px solid var(--hairline);border-radius:14px;padding:var(--sp-6);box-shadow:var(--shadow-card)}
+  .map svg{width:100%;height:auto;display:block}
+  .pin{cursor:pointer}
+  .pin circle{transition:r .2s,fill .2s}
+  .pin:hover circle,.pin:focus-visible circle{fill:var(--violet-glow)}
+  .pin:focus-visible{outline:none}
+  .venue-info{background:var(--charcoal-2);border:1px solid var(--hairline);border-radius:14px;padding:var(--sp-8);min-height:220px}
+  .venue-info .kicker{margin-bottom:var(--sp-3)}
+  .venue-info h3{font-size:26px;margin-bottom:var(--sp-2)}
+  .venue-info .yr{color:var(--oxblood-bright);font-size:13px;letter-spacing:.1em;text-transform:uppercase;margin-bottom:var(--sp-4)}
+  .venue-info p{color:var(--parchment-dim);line-height:1.7;font-size:14.5px}
+  .venue-list{display:flex;flex-wrap:wrap;gap:var(--sp-2);margin-top:var(--sp-6)}
+  .venue-list button{
+    font-size:12px;padding:6px 12px;border-radius:30px;border:1px solid var(--hairline);
+    background:var(--charcoal-3);color:var(--parchment-dim);cursor:pointer;transition:all .18s
+  }
+  .venue-list button:hover,.venue-list button.on,.venue-list button:focus-visible{
+    border-color:var(--oxblood);color:var(--ink);background:rgba(125,33,48,.2);outline:none
+  }
+
+  /* ---------- footer ---------- */
+  footer{border-top:1px solid var(--hairline);padding:var(--sp-16) 0 var(--sp-12);text-align:center}
+  footer h2{font-size:clamp(26px,4vw,38px);margin-bottom:var(--sp-4)}
+  footer p{color:var(--parchment-dim);max-width:560px;margin:0 auto var(--sp-8)}
+  footer .fine{font-size:11px;color:var(--muted);letter-spacing:.06em;line-height:1.9}
+
+  /* reduced motion mode (class-driven, plus media query) */
+  body.reduced .ambient,
+  body.reduced .now.playing .disc,
+  body.reduced .bars i,
+  body.reduced .art svg{animation:none!important;transition:none!important}
+  body.reduced .reveal{opacity:1!important;transform:none!important;animation:none!important}
+  body.reduced *{scroll-behavior:auto}
+  @media (prefers-reduced-motion:reduce){
+    .ambient,.now.playing .disc,.bars i{animation:none!important}
+    .reveal{opacity:1;transform:none;animation:none}
+  }
+
+  @media(max-width:820px){
+    .navlinks{display:none}
+    .listen,.mapwrap{grid-template-columns:1fr}
+    .spot-item{grid-template-columns:1fr;text-align:left}
+    .spot-art{margin-bottom:var(--sp-4)}
+    section{padding:var(--sp-16) 0}
+    .statement{padding:var(--sp-12) var(--sp-6)}
+  }
+  .skip{position:absolute;left:-999px;top:0}
+  .skip:focus{left:var(--sp-4);top:var(--sp-4);z-index:60;background:var(--violet);color:#fff;padding:8px 14px;border-radius:8px}
+</style>
+</head>
+<body>
+<a href="#stations" class="skip">Skip to the collection</a>
+<div class="ambient" aria-hidden="true"></div>
+
+<header class="topbar">
+  <div class="brand">
+    <svg class="bolt" viewBox="0 0 100 100" aria-hidden="true">
+      <circle cx="50" cy="50" r="46" fill="none" stroke="#efe6d2" stroke-width="4"/>
+      <path d="M55 14 L34 52 H48 L44 86 L68 44 H52 Z" fill="#a8323f"/>
+    </svg>
+    <span>The&nbsp;Long&nbsp;Strange&nbsp;Archive</span>
+  </div>
+  <nav class="navlinks" aria-label="Exhibition sections">
+    <a href="#statement">Statement</a>
+    <a href="#timeline">Timeline</a>
+    <a href="#stations">Stations</a>
+    <a href="#listen">Listening Room</a>
+    <a href="#spotlight">From the Archive</a>
+    <a href="#map">Venue Map</a>
+  </nav>
+  <button class="motion-toggle" id="motionToggle" aria-pressed="false">
+    <span class="dot" id="motionDot"></span><span id="motionLabel">Full Motion</span>
+  </button>
+</header>
+
+<main>
+
+<!-- HERO -->
+<section class="hero" style="border-top:none" id="top">
+  <div class="wrap">
+    <div class="plate reveal">
+      <svg viewBox="0 0 200 200" role="img" aria-label="Psychedelic printmaking emblem: a radiant rose over a lightning field">
+        <defs>
+          <radialGradient id="halo" cx="50%" cy="50%" r="55%">
+            <stop offset="0%" stop-color="#9a6cff"/>
+            <stop offset="55%" stop-color="#7d2130"/>
+            <stop offset="100%" stop-color="#17151a"/>
+          </radialGradient>
+        </defs>
+        <circle cx="100" cy="100" r="96" fill="url(#halo)"/>
+        <g stroke="#efe6d2" stroke-width="1.4" fill="none" opacity=".55">
+          <circle cx="100" cy="100" r="82"/><circle cx="100" cy="100" r="66"/>
+        </g>
+        <g transform="translate(100,100)">
+          <g fill="none" stroke="#efe6d2" stroke-width="2">
+            <path d="M0-46 C22-30 22 30 0 46 C-22 30 -22-30 0-46Z"/>
+            <path d="M-46 0 C-30-22 30-22 46 0 C30 22 -30 22 -46 0Z"/>
+          </g>
+          <circle r="16" fill="#a8323f" stroke="#efe6d2" stroke-width="2"/>
+          <circle r="6" fill="#efe6d2"/>
+        </g>
+      </svg>
+    </div>
+    <h1 class="reveal">The Long Strange <em>Archive</em></h1>
+    <p class="lede reveal">A museum-grade exhibition tracing three decades of the Grateful Dead's visual and cultural imagination — from the mimeographed handbills of the Haight to the last stadium lights of the touring era.</p>
+    <div class="meta-row reveal">
+      <div>On View<strong>Perpetual</strong></div>
+      <div>Span<strong>1965 – 1995</strong></div>
+      <div>Objects<strong>Five Stations</strong></div>
+      <div>Gallery<strong>Hall of Ephemera</strong></div>
+    </div>
+  </div>
+</section>
+
+<!-- CURATORIAL STATEMENT -->
+<section id="statement">
+  <div class="wrap">
+    <div class="sec-head reveal">
+      <span class="kicker ox">Curatorial Opening</span>
+      <h2>What the paper remembers</h2>
+    </div>
+    <div class="statement reveal">
+      <div class="body">
+        <p>The Grateful Dead were never only a band. They were a printing press, a caravan, a rumor that traveled by hand. Long before the archive had a name, it existed as a drawer of ticket stubs, a shoebox of handbills, a jacket embroidered by someone you'd meet once and remember forever.</p>
+        <p>This exhibition gathers that scattered devotion. It reads the ephemera as a culture reads its own scripture — closely, tenderly, and with an eye for the smudge of the human hand. Each object here was made to be used up: pinned to a wall, torn at a gate, traded in a parking lot. That they survived at all is the argument the show wants to make.</p>
+        <p class="small">We have deliberately reproduced no copyrighted poster. Every graphic in these galleries is an original placeholder drawn in the <em>spirit</em> of psychedelic printmaking — the halftone bloom, the mirrored bilateral symmetry, the ink that seems to vibrate — so that the eye can study the language without mistaking it for the artifact.</p>
+        <div class="sign">Curated by <b>The Office of Ephemeral Studies</b> · Text &amp; wall labels, in-house · Reduced-motion mode available at top right</div>
+      </div>
+    </div>
+  </div>
+</section>
+
+<!-- TIMELINE -->
+<section id="timeline">
+  <div class="wrap">
+    <div class="sec-head reveal">
+      <span class="kicker violet">The Long Strange Timeline</span>
+      <h2>A caravan measured in years</h2>
+      <p>Scroll the rail to move through the eras. Each node marks a shift in how the band looked, sounded, and gathered its people.</p>
+    </div>
+  </div>
+  <div class="wrap">
+    <div class="timeline-scroll reveal" tabindex="0" aria-label="Scrollable exhibition timeline, use arrow keys">
+      <div class="timeline">
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1965</div><div class="tl-era">The Warlocks</div><div class="tl-body">A bar band in Palo Alto becomes the house sound of Ken Kesey's Acid Tests. The first handbills are typed, not designed.</div></div>
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1967</div><div class="tl-era">Haight-Ashbury</div><div class="tl-body">710 Ashbury. Free shows in the Panhandle. The dance-hall poster becomes an art form and the band its recurring subject.</div></div>
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1971</div><div class="tl-era">The Skull &amp; Roses</div><div class="tl-body">A self-titled live album gives the culture its enduring emblems and prints the address for tapers to write in.</div></div>
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1974</div><div class="tl-era">Wall of Sound</div><div class="tl-body">A cathedral of speakers turns the stage into architecture. Backstage passes grow ornate; the road crew becomes legend.</div></div>
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1977</div><div class="tl-era">The Golden Road</div><div class="tl-body">Barton Hall, Cornell. The tape trees branch outward. Fan-made objects flourish as a gift economy on the lot.</div></div>
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1987</div><div class="tl-era">In the Dark</div><div class="tl-body">A surprise hit single floods the shows with newcomers. The parking lot becomes a marketplace and a village.</div></div>
+        <div class="tl-node" tabindex="0"><div class="dot"></div><div class="tl-year">1995</div><div class="tl-era">The Last Tour</div><div class="tl-body">Soldier Field, Chicago. The road folds up. What remains is the archive — and the people keeping it.</div></div>
+      </div>
+    </div>
+  </div>
+</section>
+
+<!-- STATIONS -->
+<section id="stations">
+  <div class="wrap">
+    <div class="sec-head reveal">
+      <span class="kicker ox">Five Artifact Stations</span>
+      <h2>The collection, close up</h2>
+      <p>Five kinds of object, each with its own way of holding memory. Open any label to read its date, medium, provenance, and a curator's interpretation.</p>
+    </div>
+
+    <div class="stations" id="stationGrid"></div>
+  </div>
+</section>
+
+<!-- LISTENING ROOM -->
+<section id="listen">
+  <div class="wrap">
+    <div class="sec-head reveal">
+      <span class="kicker violet">Listening Room</span>
+      <h2>Sit a while inside the sound</h2>
+      <p>A curated bench of era-defining performances. Selections are silent placeholders — a museum bench for the ear's imagination.</p>
+    </div>
+    <div class="listen reveal">
+      <div class="player">
+        <div class="now" id="nowBox">
+          <div class="disc" aria-hidden="true"></div>
+          <div class="now-meta">
+            <strong id="nowTitle">Dark Star</strong>
+            <span id="nowSub">Live in the Hall of Ephemera · 1972 · 23:11</span>
+          </div>
+        </div>
+        <div class="bars" aria-hidden="true">
+          <i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i>
+        </div>
+        <div class="transport">
+          <button class="playbtn" id="playBtn" aria-label="Play or pause the listening-room selection">▶</button>
+          <div style="font-size:12px;color:var(--muted);letter-spacing:.05em">Ambient placeholder — no audio streamed</div>
+        </div>
+      </div>
+      <div>
+        <div class="kicker" style="margin-bottom:var(--sp-4)">The Bench Selections</div>
+        <div class="tracklist" id="trackList" role="listbox" aria-label="Listening room selections"></div>
+      </div>
+    </div>
+  </div>
+</section>
+
+<!-- SPOTLIGHT -->
+<section id="spotlight">
+  <div class="wrap">
+    <div class="sec-head reveal">
+      <span class="kicker ox">From the Archive</span>
+      <h2>A rotating spotlight</h2>
+      <p>One object at a time, pulled from the drawers and given the whole wall. It changes on its own — or advance it yourself.</p>
+    </div>
+    <div class="spotlight reveal">
+      <div class="spot-item" id="spotItem"></div>
+      <div class="spot-dots" id="spotDots" role="tablist" aria-label="Choose spotlight object"></div>
+    </div>
+  </div>
+</section>
+
+<!-- VENUE MAP -->
+<section id="map">
+  <div class="wrap">
+    <div class="sec-head reveal">
+      <span class="kicker violet">Venue Map</span>
+      <h2>Where the road went</h2>
+      <p>Select a lantern on the map, or a name below it, to read the room where a night became an object in this show.</p>
+    </div>
+    <div class="mapwrap reveal">
+      <div class="map">
+        <svg viewBox="0 0 600 340" role="img" aria-label="Stylized map of key Grateful Dead venues">
+          <rect width="600" height="340" fill="#211e26" rx="10"/>
+          <g stroke="rgba(239,230,210,.10)" stroke-width="1">
+            <path d="M0 80H600M0 160H600M0 240H600M120 0V340M300 0V340M480 0V340"/>
+          </g>
+          <path d="M40 120 Q120 60 210 110 T400 90 Q500 80 560 140 L560 260 Q460 300 360 250 T160 270 Q80 280 40 220Z"
+                fill="rgba(125,33,48,.14)" stroke="rgba(125,75,255,.35)" stroke-width="1.5"/>
+          <!-- pins -->
+          <g class="pin" tabindex="0" role="button" data-i="0" aria-label="710 Ashbury, San Francisco">
+            <circle cx="90" cy="150" r="9" fill="#a8323f" stroke="#efe6d2" stroke-width="2"/>
+            <text x="90" y="178" fill="#c7bda6" font-size="10" text-anchor="middle" font-family="var(--sans)">San Francisco</text>
+          </g>
+          <g class="pin" tabindex="0" role="button" data-i="1" aria-label="Fillmore East, New York">
+            <circle cx="500" cy="120" r="9" fill="#a8323f" stroke="#efe6d2" stroke-width="2"/>
+            <text x="500" y="148" fill="#c7bda6" font-size="10" text-anchor="middle">New York</text>
+          </g>
+          <g class="pin" tabindex="0" role="button" data-i="2" aria-label="Barton Hall, Ithaca">
+            <circle cx="430" cy="95" r="9" fill="#a8323f" stroke="#efe6d2" stroke-width="2"/>
+            <text x="430" y="80" fill="#c7bda6" font-size="10" text-anchor="middle">Ithaca</text>
+          </g>
+          <g class="pin" tabindex="0" role="button" data-i="3" aria-label="Soldier Field, Chicago">
+            <circle cx="360" cy="180" r="9" fill="#a8323f" stroke="#efe6d2" stroke-width="2"/>
+            <text x="360" y="208" fill="#c7bda6" font-size="10" text-anchor="middle">Chicago</text>
+          </g>
+          <g class="pin" tabindex="0" role="button" data-i="4" aria-label="Red Rocks, Morrison Colorado">
+            <circle cx="235" cy="200" r="9" fill="#a8323f" stroke="#efe6d2" stroke-width="2"/>
+            <text x="235" y="228" fill="#c7bda6" font-size="10" text-anchor="middle">Morrison</text>
+          </g>
+        </svg>
+        <div class="venue-list" id="venueList"></div>
+      </div>
+      <div class="venue-info" id="venueInfo"></div>
+    </div>
+  </div>
+</section>
+
+</main>
+
+<footer>
+  <div class="wrap">
+    <span class="kicker ox">End of the Golden Road</span>
+    <h2>Nothing left to do but smile</h2>
+    <p>The archive stays open because the objects keep arriving — mailed, donated, found in an attic and recognized. If you kept something, you are already a curator here.</p>
+    <div class="fine">
+      The Long Strange Archive · A digital exhibition of the Office of Ephemeral Studies<br>
+      All graphics original placeholder works in the tradition of psychedelic printmaking · No copyrighted poster reproduced<br>
+      Sample copy, dates, and provenance are illustrative and composed for this exhibition
+    </div>
+  </div>
+</footer>
+
+<script>
+(function(){
+  "use strict";
+
+  /* ---------- reduced-motion toggle ---------- */
+  var body=document.body, tog=document.getElementById('motionToggle'),
+      label=document.getElementById('motionLabel');
+  if(window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches){
+    setReduced(true);
+  }
+  function setReduced(on){
+    body.classList.toggle('reduced',on);
+    tog.setAttribute('aria-pressed',String(on));
+    label.textContent=on?'Reduced Motion':'Full Motion';
+  }
+  tog.addEventListener('click',function(){ setReduced(!body.classList.contains('reduced')); });
+
+  /* ---------- reusable placeholder print SVGs ---------- */
+  function art(seed,pal){
+    pal=pal||['#7d4bff','#a8323f','#efe6d2'];
+    var g='g'+seed;
+    return '<svg viewBox="0 0 300 300" preserveAspectRatio="xMidYMid slice" aria-hidden="true">'+
+      '<defs><radialGradient id="'+g+'" cx="50%" cy="42%" r="65%">'+
+      '<stop offset="0%" stop-color="'+pal[0]+'"/><stop offset="55%" stop-color="'+pal[1]+'"/>'+
+      '<stop offset="100%" stop-color="#17151a"/></radialGradient>'+
+      '<pattern id="dot'+g+'" width="9" height="9" patternUnits="userSpaceOnUse">'+
+      '<circle cx="2" cy="2" r="1.3" fill="'+pal[2]+'" opacity=".18"/></pattern></defs>'+
+      '<rect width="300" height="300" fill="url(#'+g+')"/>'+
+      '<rect width="300" height="300" fill="url(#dot'+g+')"/>'+
+      shape(seed,pal)+'</svg>';
+  }
+  function shape(s,pal){
+    var t='translate(150,150)';
+    if(s%5===0) // radiating rose
+      return '<g transform="'+t+'" fill="none" stroke="'+pal[2]+'" stroke-width="2" opacity=".85">'+
+        petals(10,70)+'<circle r="20" fill="'+pal[1]+'" stroke="'+pal[2]+'"/><circle r="7" fill="'+pal[2]+'"/></g>';
+    if(s%5===1) // lightning fan
+      return '<g transform="'+t+'" stroke="'+pal[2]+'" stroke-width="2" fill="none" opacity=".8">'+
+        bolts(9,95)+'</g>';
+    if(s%5===2) // concentric mirror
+      return '<g transform="'+t+'" fill="none" stroke="'+pal[2]+'" stroke-width="2" opacity=".7">'+
+        '<circle r="90"/><circle r="66"/><circle r="42"/><circle r="18"/>'+
+        '<path d="M-100 0H100M0-100V100" stroke="'+pal[1]+'"/></g>';
+    if(s%5===3) // wave lattice
+      return '<g transform="'+t+'" stroke="'+pal[2]+'" stroke-width="2" fill="none" opacity=".75">'+
+        waves(6)+'</g>';
+    // skull-ish emblem
+    return '<g transform="'+t+'" fill="none" stroke="'+pal[2]+'" stroke-width="2.4" opacity=".85">'+
+      '<circle r="62" stroke="'+pal[1]+'" stroke-width="4"/>'+
+      '<path d="M-30-10 a30 30 0 0 1 60 0 q0 34 -30 40 q-30-6-30-40Z"/>'+
+      '<circle cx="-13" cy="0" r="8" fill="'+pal[1]+'"/><circle cx="13" cy="0" r="8" fill="'+pal[1]+'"/>'+
+      '<path d="M-8 22 l8-10 8 10"/></g>';
+  }
+  function petals(n,r){var o='',i,a;for(i=0;i<n;i++){a=(360/n)*i;o+='<path transform="rotate('+a+')" d="M0 0 C18 -'+(r*0.5)+' 18 -'+r+' 0 -'+(r+8)+' C-18 -'+r+' -18 -'+(r*0.5)+' 0 0Z"/>';}return o;}
+  function bolts(n,r){var o='',i,a,x,y;for(i=0;i<n;i++){a=(360/n)*i*Math.PI/180;x=Math.cos(a)*r;y=Math.sin(a)*r;o+='<path d="M0 0 L'+(x*0.4)+' '+(y*0.4)+' L'+(x*0.55)+' '+(y*0.35)+' L'+x+' '+y+'"/>';}return o;}
+  function waves(n){var o='',i,y;for(i=0;i<n;i++){y=-70+i*28;o+='<path d="M-110 '+y+' q27 -18 55 0 t55 0 t55 0 t55 0"/>';}return o;}
+
+  /* ---------- STATIONS DATA ---------- */
+  var stations=[
+    {tag:'Print', title:'Handbills', pal:['#7d4bff','#a8323f','#efe6d2'],
+     blurb:'The disposable poster — pressed cheap, pinned fast, meant to survive a week and instead surviving a movement.',
+     count:'2 objects on view',
+     objs:[
+      {t:'Panhandle Free Show handbill', sub:'"Bring your own dance"', date:'June 1967', med:'Two-color letterpress on newsprint, 8½ × 11 in.', prov:'Gift of a former Diggers volunteer; pulled from a Haight Street kiosk the morning after.',
+       interp:'The type is set by feel, not by rule, and that is the point. This handbill sells nothing but presence — a free afternoon, an address, a promise. Its vibrating red-on-violet is the whole aesthetic in miniature: information that wants to be felt.'},
+      {t:'Winterland ballroom handbill', sub:'New Year\'s run', date:'December 1971', med:'Offset lithograph, halftone bloom, 7 × 10 in.', prov:'From the estate of a ballroom door manager; annotated with the night\'s door count in pencil.',
+       interp:'By the seventies the handbill has learned to shimmer. The halftone dots — reproduced here in an original placeholder — turn flat ink into something that seems to breathe. It is advertising that aspires to the condition of the light show it advertises.'}
+     ]},
+    {tag:'Passage', title:'Ticket Stubs', pal:['#a8323f','#7d4bff','#efe6d2'],
+     blurb:'The torn half you kept. Proof you were in the room, softened by years in a wallet.',
+     count:'2 objects on view',
+     objs:[
+      {t:'Barton Hall stub, torn at the gate', sub:'"5/8/77 — GA"', date:'May 8, 1977', med:'Thermal-printed cardstock, hand-torn edge, 2 × 4 in.', prov:'Donated by the original ticket-holder, kept flat in a dictionary for forty years.',
+       interp:'A ticket is an object designed to be destroyed at the threshold, which is exactly why the surviving half carries such weight. The tear is not damage; it is the signature of a body that passed through a door on a specific night the culture would never stop talking about.'},
+      {t:'Mail-order envelope with custom art', sub:'Fan-decorated request', date:'Spring 1989', med:'Ink and marker on stamped envelope, 4 × 9 in.', prov:'Recovered from a returned batch; the artwork exceeded the band office\'s wall space.',
+       interp:'To get a ticket you drew for it. Fans covered their request envelopes in original art, hoping beauty might tip the lottery. Whether it worked or not, it produced a folk archive of thousands of hand-made objects — devotion measured by the envelope.'}
+     ]},
+    {tag:'Access', title:'Backstage Ephemera', pal:['#7d4bff','#efe6d2','#a8323f'],
+     blurb:'Laminates, crew notes, set-list scraps — the paperwork of a machine that toured like a small nation.',
+     count:'2 objects on view',
+     objs:[
+      {t:'Wall of Sound crew laminate', sub:'"ACCESS ALL AREAS"', date:'Summer 1974', med:'Laminated card with foil sticker, ¼-in. grommet, 3 × 4 in.', prov:'From a monitor engineer\'s road case; edges worn to the plastic.',
+       interp:'The pass is a small painting you wear to work. As the stage grew into the Wall of Sound, the laminate grew ornate to match — a badge of belonging to the most ambitious PA ever hauled down a highway. Wear turns it from credential into relic.'},
+      {t:'Pencil set list on hotel stationery', sub:'"open w/ Bertha?"', date:'October 1980', med:'Graphite on letterhead, 5½ × 8½ in.', prov:'Left on an amp; rescued by a stagehand who understood what he was holding.',
+       interp:'Every night was argued into being on scraps like this. The crossings-out are the real document — a band deciding, in pencil, how the evening would rise and fall. It is the closest thing the archive has to a fingerprint of a working mind.'}
+     ]},
+    {tag:'Image', title:'Stage Photography', pal:['#efe6d2','#7d4bff','#a8323f'],
+     blurb:'Light, smoke, and silhouette — the show as it looked from the third row of the pit.',
+     count:'2 objects on view',
+     objs:[
+      {t:'Silhouette against the light rig', sub:'Untitled, printed later', date:'circa 1978', med:'Gelatin silver print from 35mm negative, 11 × 14 in.', prov:'From a house photographer\'s contact sheets; printed for this exhibition from the original frame.',
+       interp:'The players are barely visible and that is the truth of it — at these shows the light was a member of the band. This placeholder image keeps the figures as shadow so the eye reads the beam, the haze, the architecture of a night built out of nothing but glow.'},
+      {t:'Amps, roses, and the drummer\'s reach', sub:'Pit frame', date:'Summer 1987', med:'Chromogenic print, 16 × 20 in.', prov:'Purchased for the collection from a retiring tour photographer.',
+       interp:'Color arrives, and with it the parking-lot palette moves onstage — oxblood and violet, warm and electric at once. The gesture caught here is ordinary and total: a musician mid-reach, framed by the flowers that had become shorthand for the whole endeavor.'}
+     ]},
+    {tag:'Handmade', title:'Fan-Made Objects', pal:['#a8323f','#efe6d2','#7d4bff'],
+     blurb:'The gift economy of the lot: pins, patches, tapes, and things made only to be given away.',
+     count:'2 objects on view',
+     objs:[
+      {t:'Hand-embroidered denim patch', sub:'"stitched on the road"', date:'circa 1985', med:'Cotton floss on denim, appliqué, 4 × 5 in.', prov:'Traded on a lot in the Southeast; donor received it for a grilled-cheese sandwich.',
+       interp:'Nobody was paid to make this. The patch is pure surplus affection — hours of stitching handed to a stranger for the price of lunch. It is the exhibition\'s clearest evidence that the culture ran on generosity as much as on music.'},
+      {t:'Home-dubbed tape with inked J-card', sub:'"Cornell \'77 — first gen!"', date:'Dubbed 1990s', med:'Cassette with hand-lettered insert, 4 × 2½ in.', prov:'From a taper\'s trade tree; the third branch of a lineage traced back to the soundboard.',
+       interp:'The tape tree was an open-source archive decades ahead of its name. Each copy carried the pride of its generation — "first gen!" — and a promise to keep the signal clean for whoever came next. The object is small; the network behind it was continental.'}
+     ]}
+  ];
+
+  var grid=document.getElementById('stationGrid');
+  stations.forEach(function(s,si){
+    var card=document.createElement('article');
+    card.className='station reveal';
+    var labels=s.objs.map(function(o,oi){
+      var sw=art(si*7+oi+2,s.pal);
+      return '<div class="obj" data-obj>'+
+        '<button class="obj-btn" aria-expanded="false">'+
+          '<span class="obj-swatch">'+sw+'</span>'+
+          '<span class="obj-title">'+o.t+'<span>'+o.sub+'</span></span>'+
+          '<span class="chev">▶</span>'+
+        '</button>'+
+        '<div class="obj-panel"><div class="obj-inner">'+
+          '<div class="facts">'+
+            '<div><b>Date</b><span>'+o.date+'</span></div>'+
+            '<div><b>Medium</b><span>'+o.med+'</span></div>'+
+            '<div style="flex-basis:100%"><b>Provenance</b><span>'+o.prov+'</span></div>'+
+          '</div>'+
+          '<p class="interp">'+o.interp+'</p>'+
+        '</div></div>'+
+      '</div>';
+    }).join('');
+    card.innerHTML=
+      '<div class="art"><span class="tag">'+s.tag+'</span>'+art(si,s.pal)+'</div>'+
+      '<div class="pad">'+
+        '<h3>'+s.title+'</h3>'+
+        '<p class="blurb">'+s.blurb+'</p>'+
+        '<div class="labels">'+labels+'</div>'+
+        '<div class="count">'+s.count+'</div>'+
+      '</div>';
+    grid.appendChild(card);
+  });
+
+  /* expandable object labels (delegated) */
+  grid.addEventListener('click',function(e){
+    var btn=e.target.closest('.obj-btn'); if(!btn) return;
+    var obj=btn.parentNode, panel=obj.querySelector('.obj-panel'),
+        open=obj.classList.toggle('open');
+    btn.setAttribute('aria-expanded',String(open));
+    panel.style.maxHeight=open?panel.scrollHeight+'px':'0px';
+  });
+
+  /* ---------- LISTENING ROOM ---------- */
+  var tracks=[
+    {t:'Dark Star',            sub:'Live in the Hall of Ephemera · 1972 · 23:11', len:'23:11'},
+    {t:'Morning Dew',          sub:'Barton Hall bench recording · 1977 · 12:44', len:'12:44'},
+    {t:'Eyes of the World',    sub:'Wall of Sound era · 1974 · 14:02', len:'14:02'},
+    {t:'Scarlet › Fire',       sub:'The parking-lot years · 1985 · 18:37', len:'18:37'},
+    {t:'Ripple',               sub:'Acoustic bench · 1980 · 04:16', len:'04:16'},
+    {t:'Terrapin Station',     sub:'The last tour · 1995 · 11:29', len:'11:29'}
+  ];
+  var list=document.getElementById('trackList'),
+      nowBox=document.getElementById('nowBox'),
+      nowT=document.getElementById('nowTitle'),
+      nowS=document.getElementById('nowSub'),
+      playBtn=document.getElementById('playBtn'),
+      playing=false, cur=0;
+
+  tracks.forEach(function(tr,i){
+    var el=document.createElement('div');
+    el.className='track'+(i===0?' active':'');
+    el.setAttribute('role','option'); el.tabIndex=0;
+    el.setAttribute('aria-selected',i===0?'true':'false');
+    el.innerHTML='<span>'+tr.t+'</span><span class="len">'+tr.len+'</span>';
+    el.addEventListener('click',function(){ select(i,true); });
+    el.addEventListener('keydown',function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();select(i,true);} });
+    list.appendChild(el);
+  });
+  function select(i,startPlay){
+    cur=i;
+    Array.prototype.forEach.call(list.children,function(c,ci){
+      c.classList.toggle('active',ci===i);
+      c.setAttribute('aria-selected',ci===i?'true':'false');
+    });
+    nowT.textContent=tracks[i].t; nowS.textContent=tracks[i].sub;
+    if(startPlay){ playing=true; render(); }
+  }
+  function render(){
+    nowBox.classList.toggle('playing',playing);
+    playBtn.textContent=playing?'❚❚':'▶';
+    playBtn.setAttribute('aria-label',(playing?'Pause':'Play')+' the listening-room selection');
+  }
+  playBtn.addEventListener('click',function(){ playing=!playing; render(); });
+  render();
+
+  /* ---------- SPOTLIGHT ---------- */
+  var spots=[
+    {t:'The Skull & Roses emblem', m:'Original placeholder print · after 1971', pal:['#a8323f','#7d4bff','#efe6d2'],
+     p:'The most tattooed image in American music began as album cover shorthand and became a shared coat of arms. Rendered here as an original placeholder, it shows how a single emblem can carry a whole ethos — mortality softened by flowers, the party at the edge of the dark.'},
+    {t:'Lightning through the seam', m:'Original placeholder print · after 1974', pal:['#7d4bff','#a8323f','#efe6d2'],
+     p:'A bolt splitting a circle: energy contained but never quite. This spotlight object studies the graphic language of the light show translated to paper — the sense that the design itself is plugged in, humming, one instant from discharge.'},
+    {t:'The mirrored garden', m:'Original placeholder print · after 1977', pal:['#efe6d2','#7d4bff','#a8323f'],
+     p:'Bilateral symmetry is the deep grammar of psychedelic printmaking, and the archive is full of it. Fold this placeholder down its spine and both halves meet — a visual echo of music built on call-and-response, of a culture that mirrored kindness back to itself.'},
+    {t:'The taper\'s signal', m:'Original placeholder print · after 1985', pal:['#a8323f','#efe6d2','#7d4bff'],
+     p:'Concentric waves radiating from a still center: the diagram of a soundboard patch, of a rumor spreading, of a tape tree branching outward. It is the abstract portrait of how this music actually moved through the world — hand to hand, generation to generation.'}
+  ];
+  var spotItem=document.getElementById('spotItem'),
+      spotDots=document.getElementById('spotDots'),
+      spotIdx=0, spotTimer=null;
+  spots.forEach(function(_,i){
+    var b=document.createElement('button');
+    b.setAttribute('role','tab'); b.setAttribute('aria-label','Spotlight object '+(i+1));
+    b.addEventListener('click',function(){ showSpot(i,true); });
+    spotDots.appendChild(b);
+  });
+  function showSpot(i,manual){
+    spotIdx=i; var s=spots[i];
+    spotItem.style.opacity=0;
+    setTimeout(function(){
+      spotItem.innerHTML='<div class="spot-art">'+art(i+30,s.pal)+'</div>'+
+        '<div class="spot-body"><div class="m">'+s.m+'</div><h3>'+s.t+'</h3><p>'+s.p+'</p></div>';
+      spotItem.style.transition='opacity .5s ease'; spotItem.style.opacity=1;
+    },body.classList.contains('reduced')?0:220);
+    Array.prototype.forEach.call(spotDots.children,function(d,di){
+      d.classList.toggle('on',di===i); d.setAttribute('aria-selected',di===i?'true':'false');
+    });
+    if(manual) restartSpot();
+  }
+  function restartSpot(){
+    if(spotTimer) clearInterval(spotTimer);
+    spotTimer=setInterval(function(){ showSpot((spotIdx+1)%spots.length,false); },7000);
+  }
+  showSpot(0,false); restartSpot();
+
+  /* ---------- VENUE MAP ---------- */
+  var venues=[
+    {n:'710 Ashbury / The Panhandle', city:'San Francisco, CA', yr:'1966 – 1968',
+     d:'The communal house and the free shows in the park. This is where the band and its audience learned they were the same thing — and where the first handbills in this exhibition were pinned to kiosks up and down Haight Street.'},
+    {n:'Fillmore East', city:'New York, NY', yr:'1970 – 1971',
+     d:'A converted movie palace on the Lower East Side where the marathon show found its East Coast home. The stage photography station owes its love of the light beam to rooms shaped exactly like this one.'},
+    {n:'Barton Hall, Cornell', city:'Ithaca, NY', yr:'May 8, 1977',
+     d:'A college gym that became a pilgrimage site. The torn ticket stub in Station Two came through these doors; the tape that carried the night outward seeded a lineage still being copied decades later.'},
+    {n:'Soldier Field', city:'Chicago, IL', yr:'July 1995',
+     d:'Where the touring era closed. The stadium is the last room in the archive\'s geography — the place the caravan folded up and handed everything it had made to the people keeping it.'},
+    {n:'Red Rocks Amphitheatre', city:'Morrison, CO', yr:'1978 – 1980s',
+     d:'Sandstone monoliths for walls and the sky for a ceiling. The backstage laminates from these runs are prized for a reason: getting a crew across this terrain was its own quiet feat of engineering.'}
+  ];
+  var venueInfo=document.getElementById('venueInfo'),
+      venueList=document.getElementById('venueList'),
+      pins=document.querySelectorAll('.pin');
+
+  venues.forEach(function(v,i){
+    var b=document.createElement('button');
+    b.textContent=v.n.split(' / ')[0].split(',')[0];
+    b.addEventListener('click',function(){ showVenue(i); });
+    venueList.appendChild(b);
+  });
+  Array.prototype.forEach.call(pins,function(p){
+    var i=+p.getAttribute('data-i');
+    p.addEventListener('click',function(){ showVenue(i); });
+    p.addEventListener('keydown',function(ev){ if(ev.key==='Enter'||ev.key===' '){ev.preventDefault();showVenue(i);} });
+  });
+  function showVenue(i){
+    var v=venues[i];
+    venueInfo.innerHTML='<div class="kicker violet">Venue File</div>'+
+      '<h3>'+v.n+'</h3><div class="yr">'+v.city+' · '+v.yr+'</div><p>'+v.d+'</p>';
+    Array.prototype.forEach.call(venueList.children,function(c,ci){ c.classList.toggle('on',ci===i); });
+    Array.prototype.forEach.call(pins,function(p){
+      var pi=+p.getAttribute('data-i'), c=p.querySelector('circle');
+      c.setAttribute('r',pi===i?'12':'9');
+      c.setAttribute('fill',pi===i?'#9a6cff':'#a8323f');
+    });
+  }
+  showVenue(0);
+
+  /* ---------- scroll reveal ---------- */
+  var io=new IntersectionObserver(function(entries){
+    entries.forEach(function(en){
+      if(en.isIntersecting){ en.target.classList.add('in'); io.unobserve(en.target); }
+    });
+  },{threshold:.12});
+  document.querySelectorAll('.reveal').forEach(function(el,i){
+    el.style.animationDelay=(Math.min(i,4)*0.09)+'s';
+    io.observe(el);
+  });
+
+  /* horizontal timeline arrow-key scroll */
+  var tl=document.querySelector('.timeline-scroll');
+  tl.addEventListener('keydown',function(e){
+    if(e.key==='ArrowRight'){ tl.scrollLeft+=200; e.preventDefault(); }
+    if(e.key==='ArrowLeft'){ tl.scrollLeft-=200; e.preventDefault(); }
+  });
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/a5990564b1ee/qwen25-7b.html b/data/artifacts/a5990564b1ee/qwen25-7b.html
new file mode 100644
index 0000000..bfc35c2
--- /dev/null
+++ b/data/artifacts/a5990564b1ee/qwen25-7b.html
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>The Long Strange Archive</title>
+    <style>
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+            font-family: 'Didot', serif;
+        }
+        body {
+            background-color: #f7efe6;
+            color: #3a2c22;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            height: 100vh;
+        }
+        .container {
+            width: 90%;
+            max-width: 1440px;
+            padding: 24px;
+            background-color: #fff9f1;
+            border-radius: 14px;
+            display: flex;
+            flex-direction: column;
+            gap: 24px;
+        }
+        header {
+            text-align: center;
+            margin-bottom: 32px;
+        }
+        h1, p {
+            letter-spacing: .15em;
+        }
+        p {
+            font-size: 16px;
+            line-height: 1.5;
+        }
+        .timeline {
+            display: flex;
+            justify-content: space-between;
+            gap: 24px;
+        }
+        .artifact-stations {
+            display: grid;
+            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
+            gap: 24px;
+            margin-top: 32px;
+        }
+        .artifact-station {
+            background-color: #fff9f1;
+            border-radius: 14px;
+            padding: 24px;
+            transition: transform 0.7s cubic-bezier(.22,1,.36,1);
+        }
+        .artifact-station:hover {
+            transform: translateY(-16px);
+        }
+        .listening-room {
+            margin-top: 32px;
+            padding: 24px;
+            border-radius: 14px;
+            background-color: #fff9f1;
+        }
+        @keyframes fadeUp {
+            from { opacity: 0; transform: translateY(28px); }
+            to { opacity: 1; transform: none; }
+        }
+        .fade-up {
+            animation-name: fadeUp;
+            animation-duration: 0.7s;
+            animation-timing-function: cubic-bezier(.22,1,.36,1);
+            animation-fill-mode: both;
+        }
+    </style>
+</head>
+<body>
+    <div class="container">
+        <header>
+            <h1>The Long Strange Archive</h1>
+            <p>Tracing the Grateful Dead’s Visual and Cultural Journey from 1965 to 1995</p>
+        </header>
+        <section class="timeline">
+            <article class="event fade-up" style="--year: 1965;">1965 - Formation of The Grateful Dead</article>
+            <article class="event fade-up" style="--year: 1970;">1970 - Peak in Cultural Influence</article>
+            <article class="event fade-up" style="--year: 1980;">1980 - Transition Period with Jerry Garcia's Illness</article>
+            <article class="event fade-up" style="--year: 1990;">1990 - Final Tours and Farewell Performances</article>
+        </section>
+        <section class="artifact-stations">
+            <div class="artifact-station">
+                <h3>Handbills</h3>
+                <p>Date: January 1972, Medium: Screenprint, Provenance: Deadhead Collection<br>A vibrant poster promoting a Grateful Dead show in San Francisco.</p>
+            </div>
+            <div class="artifact-station">
+                <h3>Ticket Stubs</h3>
+                <p>Date: July 1974, Medium: Paper, Provenance: Official Ticket Office<br>Stubb's Berkeley, CA. A rare ticket stub from one of their legendary shows.</p>
+            </div>
+            <div class="artifact-station">
+                <h3>Backstage Ephemera</h3>
+                <p>Date: September 1980, Medium: Cardboard, Provenance: Band Archive<br>A backstage pass with the band's logo and date, from a pivotal tour.</p>
+            </div>
+            <div class="artifact-station">
+                <h3>Stage Photography</h3>
+                <p>Date: December 1982, Medium: Color Print, Provenance: Grateful Dead Archive<br>A candid photo capturing Jerry Garcia's electrifying performance on stage.</p>
+            </div>
+            <div class="artifact-station">
+                <h3>Fan-Made Objects</h3>
+                <p>Date: 1985, Medium: Hand-Painted T-Shirt, Provenance: Private Collection<br>A fan-made t-shirt depicting the iconic 'Wavy Gravy' symbol from a concert.</p>
+            </div>
+        </section>
+        <section class="listening-room">
+            <h3>Listening Room</h3>
+            <iframe src="https://www.youtube.com/embed/1234567890" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
+        </section>
+    </div>
+
+    <!-- Accessibility-friendly reduced-motion mode -->
+    <script>
+        document.addEventListener('DOMContentLoaded', function() {
+            if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
+                // Apply reduced motion styles here
+                document.body.classList.add('reduced-motion');
+            }
+        });
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/a5990564b1ee/qwen3-14b.html b/data/artifacts/a5990564b1ee/qwen3-14b.html
new file mode 100644
index 0000000..992e725
--- /dev/null
+++ b/data/artifacts/a5990564b1ee/qwen3-14b.html
@@ -0,0 +1,289 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>The Long Strange Archive</title>
+  <style>
+    :root {
+      --bg: #f7efe6;
+      --surface: #fff9f1;
+      --text: #3a2c22;
+      --muted: #a08c7a;
+      --accent: #c65f38;
+      --accent-alt: #e0a458;
+      --card-radius: 14px;
+      --spacing: 4px 8px 12px 16px 24px 32px 48px 64px 96px 128px;
+      --font-display: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      --font-body: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+      --scale: 12px 16px 21px 28px 38px 50px 67px;
+    }
+
+    * {
+      box-sizing: border-box;
+      margin: 0;
+      padding: 0;
+    }
+
+    body {
+      background: var(--bg);
+      color: var(--text);
+      font-family: var(--font-body);
+      line-height: 1.6;
+      overflow-x: hidden;
+      scroll-behavior: smooth;
+      min-height: 100vh;
+      display: flex;
+      flex-direction: column;
+      font-size: var(--scale-1);
+    }
+
+    h1, h2, h3 {
+      font-family: var(--font-display);
+      font-weight: normal;
+    }
+
+    h1 {
+      font-size: var(--scale-5);
+      margin-bottom: var(--spacing-4);
+    }
+
+    h2 {
+      font-size: var(--scale-4);
+      margin-bottom: var(--spacing-3);
+    }
+
+    h3 {
+      font-size: var(--scale-3);
+      margin-bottom: var(--spacing-2);
+    }
+
+    .curator {
+      padding: var(--spacing-6) var(--spacing-4);
+      background: var(--surface);
+      box-shadow: 0 8px 24px rgba(0,0,0,0.12);
+      border-radius: var(--card-radius);
+      margin-bottom: var(--spacing-6);
+    }
+
+    .timeline {
+      display: flex;
+      overflow-x: auto;
+      padding: var(--spacing-4);
+      gap: var(--spacing-4);
+      scroll-behavior: smooth;
+      -webkit-overflow-scrolling: touch;
+    }
+
+    .timeline-item {
+      flex: 0 0 auto;
+      min-width: 120px;
+      padding: var(--spacing-2);
+      background: var(--muted);
+      border-radius: var(--card-radius);
+      text-align: center;
+      transition: transform 0.2s ease-in-out, box-shadow 0.2s ease-in-out;
+    }
+
+    .timeline-item:hover {
+      transform: scale(1.05);
+      box-shadow: 0 16px 48px rgba(0,0,0,0.18);
+    }
+
+    .artifact-station {
+      display: flex;
+      flex-direction: column;
+      gap: var(--spacing-4);
+      padding: var(--spacing-4);
+    }
+
+    .artifact {
+      display: flex;
+      align-items: center;
+      gap: var(--spacing-2);
+      padding: var(--spacing-2);
+      background: var(--surface);
+      border-radius: var(--card-radius);
+      box-shadow: 0 8px 24px rgba(0,0,0,0.12);
+      transition: box-shadow 0.2s ease-in-out;
+    }
+
+    .artifact:hover {
+      box-shadow: 0 16px 48px rgba(0,0,0,0.18);
+    }
+
+    .label {
+      font-size: var(--scale-0);
+      letter-spacing: 0.15em;
+      text-transform: uppercase;
+      color: var(--muted);
+      margin-bottom: var(--spacing-2);
+    }
+
+    .label-detail {
+      font-size: var(--scale-0);
+      color: var(--text);
+    }
+
+    .listening-room {
+      background: var(--surface);
+      padding: var(--spacing-6);
+      box-shadow: 0 8px 24px rgba(0,0,0,0.12);
+      border-radius: var(--card-radius);
+      margin-bottom: var(--spacing-6);
+    }
+
+    .spotlight {
+      background: var(--accent);
+      color: var(--surface);
+      padding: var(--spacing-4);
+      border-radius: var(--card-radius);
+      margin-bottom: var(--spacing-6);
+      text-align: center;
+    }
+
+    .venue-map {
+      background: var(--surface);
+      padding: var(--spacing-4);
+      box-shadow: 0 8px 24px rgba(0,0,0,0.12);
+      border-radius: var(--card-radius);
+      margin-bottom: var(--spacing-6);
+    }
+
+    .reduce-motion {
+      animation: none !important;
+    }
+
+    .fade-up {
+      animation: fadeUp 0.7s cubic-bezier(0.22,1,0.36,1) both;
+    }
+
+    @keyframes fadeUp {
+      from {
+        opacity: 0;
+        transform: translateY(28px);
+      }
+      to {
+        opacity: 1;
+        transform: none;
+      }
+    }
+
+    @media (prefers-reduced-motion: no-preference) {
+      body {
+        background: linear-gradient(180deg, var(--accent), var(--accent-alt)) fixed;
+        background-size: 400% 400%;
+        animation: drift 18s ease-in-out infinite;
+      }
+
+      @keyframes drift {
+        0% { background-position: 0% 50%; }
+        50% { background-position: 100% 50%; }
+        100% { background-position: 0% 50%; }
+      }
+    }
+
+    @media (max-width: 768px) {
+      .timeline {
+        overflow-x: auto;
+        flex-wrap: wrap;
+      }
+
+      .timeline-item {
+        flex: 1 1 80px;
+        min-width: 80px;
+      }
+    }
+  </style>
+</head>
+<body class="fade-up">
+  <h1>The Long Strange Archive</h1>
+  <div class="curator">
+    <h2>Curatorial Statement</h2>
+    <p>This exhibition traces the Grateful Dead’s visual and cultural legacy across five decades, from the psychedelic counterculture of the 1960s to the final performances of the 1990s. Through a curated selection of rare and overlooked artifacts, this space invites reflection on the band's evolution as artists, activists, and cultural icons. It is not a museum of nostalgia, but a scholarly exploration of a band that reshaped the boundaries of music, art, and community.</p>
+  </div>
+
+  <div class="timeline">
+    <div class="timeline-item">1965</div>
+    <div class="timeline-item">1967</div>
+    <div class="timeline-item">1971</div>
+    <div class="timeline-item">1977</div>
+    <div class="timeline-item">1987</div>
+    <div class="timeline-item">1995</div>
+    <div class="timeline-item">2009</div>
+  </div>
+
+  <div class="artifact-station">
+    <h2>Artifact Stations</h2>
+    <div class="artifact">
+      <div class="label">HANDBILL</div>
+      <div class="label-detail">Date: 1967 | Medium: Screen-printed paper | Provenance: San Francisco, CA</div>
+      <div class="label-detail">A handbill from a 1967 gig at the Avalon Ballroom, featuring a psychedelic design that mimics a cosmic landscape. The poster is a relic of the era’s underground printing movement, where artists created ephemera for music, politics, and protest.</div>
+    </div>
+
+    <div class="artifact">
+      <div class="label">TICKET STUB</div>
+      <div class="label-detail">Date: 1971 | Medium: Paper | Provenance: Fillmore West, San Francisco</div>
+      <div class="label-detail">This stub from a Fillmore West show reveals the band’s growing influence and the logistical scale of their concerts. The ticket’s design reflects the era’s mix of corporate production and rock-n-roll authenticity, a paradox that defined the Dead’s touring life.</div>
+    </div>
+
+    <div class="artifact">
+      <div class="label">BACKSTAGE EPHEMERA</div>
+      <div class="label-detail">Date: 1977 | Medium: Mixed media | Provenance: San Francisco, CA</div>
+      <div class="label-detail">A backstage pass and scribbled note from a 1977 tour, showing the informal, almost ritualistic nature of the Dead’s performances. The pass is marked with a hand-drawn mandala, a symbol of the band’s deep spiritual interests and the countercultural ethos of the time.</div>
+    </div>
+
+    <div class="artifact">
+      <div class="label">STAGE PHOTOGRAPHY</div>
+      <div class="label-detail">Date: 1987 | Medium: Silver gelatin print | Provenance: The Warfield, San Francisco</div>
+      <div class="label-detail">This photograph captures the band mid-performance at The Warfield, with members in full stage regalia and a crowd in motion. The image shows the Dead in their prime, a balance of musical mastery and visual spectacle that defined their later years.</div>
+    </div>
+
+    <div class="artifact">
+      <div class="label">FAN-MADE OBJECT</div>
+      <div class="label-detail">Date: 1995 | Medium: Mixed media | Provenance: Santa Cruz, CA</div>
+      <div class="label-detail">A handcrafted "Deadhead" pin made of wood and fabric, featuring an abstract representation of the band’s logo. This object represents the deeply personal and communal relationship between the band and its fans, a legacy that continues to this day.</div>
+    </div>
+  </div>
+
+  <div class="listening-room">
+    <h2>Listening Room</h2>
+    <audio controls>
+      <source src="https://upload.wikimedia.org/wikipedia/en/3/36/GratefulDead-PlayingInTheDark.ogg" type="audio/ogg">
+      Your browser does not support the audio element.
+    </audio>
+    <p>Audio from <i>Playing in the Dark</i> (1989), a live recording that captures the band's improvisational brilliance and the emotional resonance of their performances.</p>
+  </div>
+
+  <div class="spotlight">
+    <h3>From the Archive</h3>
+    <p><strong>Artifact:</strong> 1973 "Dark Star" Poster<br><strong>Medium:</strong> Hand-drawn ink and collage<br><strong>Provenance:</strong> Portland, OR</p>
+    <p>This rare poster from a 1973 "Dark Star" show is a masterwork of psychedelic printmaking. Featuring a spiral of ink and paper collage, it reflects the band’s deep engagement with art, spirituality, and the visual language of the era.</p>
+  </div>
+
+  <div class="venue-map">
+    <h2>Venue Map</h2>
+    <p>Explore a map of the Dead’s most iconic venues, including The Fillmore, The Warfield, and the outdoor festivals of the 1970s and 1980s. Each location is marked with a small icon and a brief historical note.</p>
+  </div>
+
+  <script>
+    // Keyboard navigation: 'Tab' to navigate, 'Enter' to open artifact details
+    const artifacts = document.querySelectorAll('.artifact');
+    artifacts.forEach((artifact, index) => {
+      artifact.tabIndex = 0;
+      artifact.addEventListener('keydown', function(e) {
+        if (e.key === 'Enter') {
+          alert('Artifact ' + (index + 1) + ' details: ' + this.querySelector('.label-detail').textContent);
+        }
+      });
+    });
+
+    // Reduce motion class toggle
+    if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
+      document.body.classList.remove('reduce-motion');
+    } else {
+      document.body.classList.add('reduce-motion');
+    }
+  </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/b05597bd9f5a/claude-code.html b/data/artifacts/b05597bd9f5a/claude-code.html
new file mode 100644
index 0000000..577e213
--- /dev/null
+++ b/data/artifacts/b05597bd9f5a/claude-code.html
@@ -0,0 +1,768 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Deadhead Print Lab — A Working Poster Studio</title>
+<style>
+  :root{
+    --cream:#f2e7cf;
+    --cream-fade:#e6d7b4;
+    --midnight:#16233f;
+    --midnight-deep:#0d1526;
+    --acid:#d9322f;
+    --marigold:#e8a63a;
+    --mint:#7ec9a8;
+    --ink:#1a1a20;
+    --paper-shadow:rgba(20,18,10,.28);
+    --sp1:4px;--sp2:8px;--sp3:12px;--sp4:16px;--sp5:24px;--sp6:32px;--sp7:48px;--sp8:64px;--sp9:96px;
+    --serif:'Didot','Bodoni MT','Playfair Display',Georgia,serif;
+    --sans:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+    --radius:14px;
+    --card-shadow:0 8px 24px rgba(13,21,38,.22);
+    --hover-shadow:0 16px 48px rgba(13,21,38,.34);
+    --wall-cols:3;
+  }
+  *{box-sizing:border-box}
+  html{scroll-behavior:smooth}
+  body{
+    margin:0;
+    background:var(--midnight-deep);
+    color:var(--cream);
+    font-family:var(--sans);
+    font-size:16px;
+    line-height:1.55;
+    -webkit-font-smoothing:antialiased;
+    overflow-x:hidden;
+  }
+  /* Ambient drifting overprint field */
+  body::before{
+    content:"";
+    position:fixed;inset:0;z-index:0;pointer-events:none;
+    background:
+      radial-gradient(circle at 12% 18%, rgba(217,50,47,.14), transparent 42%),
+      radial-gradient(circle at 88% 22%, rgba(232,166,58,.13), transparent 40%),
+      radial-gradient(circle at 70% 82%, rgba(126,201,168,.12), transparent 44%),
+      radial-gradient(circle at 24% 88%, rgba(22,35,63,.5), transparent 50%);
+    background-size:180% 180%;
+    animation:drift 22s ease-in-out infinite alternate;
+    mix-blend-mode:screen;
+    opacity:.9;
+  }
+  @keyframes drift{
+    0%{background-position:0% 0%}
+    100%{background-position:100% 100%}
+  }
+  /* paper grain */
+  body::after{
+    content:"";position:fixed;inset:0;z-index:0;pointer-events:none;opacity:.06;
+    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
+  }
+  .wrap{position:relative;z-index:1}
+
+  ::selection{background:var(--acid);color:var(--cream)}
+  a{color:var(--marigold)}
+  .visually-hidden{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
+
+  .allcaps{text-transform:uppercase;letter-spacing:.15em;font-size:12px;color:var(--marigold);font-weight:600}
+
+  /* ============ HEADER / MASTHEAD ============ */
+  header.masthead{
+    position:relative;
+    padding:var(--sp8) var(--sp5) var(--sp7);
+    text-align:center;
+    border-bottom:2px solid rgba(232,166,58,.35);
+    overflow:hidden;
+  }
+  .kicker{
+    display:inline-block;
+    border:1px solid var(--mint);
+    color:var(--mint);
+    padding:6px 14px;
+    border-radius:40px;
+    font-size:11px;letter-spacing:.22em;text-transform:uppercase;font-weight:700;
+    margin-bottom:var(--sp5);
+    animation:fadeUp .7s cubic-bezier(.22,1,.36,1) both;
+  }
+  h1.logo{
+    font-family:var(--serif);
+    font-weight:400;
+    font-size:clamp(42px,9vw,86px);
+    line-height:.94;
+    margin:0 0 var(--sp4);
+    letter-spacing:-.01em;
+    position:relative;
+  }
+  /* misregistered overprint title */
+  h1.logo .a{color:var(--cream)}
+  h1.logo .b{
+    display:block;
+    color:var(--acid);
+    position:relative;
+  }
+  h1.logo .b::after{
+    content:"Print Lab";
+    position:absolute;left:3px;top:2px;
+    color:var(--mint);
+    mix-blend-mode:screen;
+    opacity:.75;
+    animation:jitter 6s ease-in-out infinite;
+  }
+  @keyframes jitter{
+    0%,100%{transform:translate(0,0)}
+    25%{transform:translate(-2px,1px)}
+    50%{transform:translate(2px,-1px)}
+    75%{transform:translate(-1px,-1px)}
+  }
+  header.masthead p.lede{
+    max-width:640px;margin:0 auto;
+    font-size:clamp(16px,2.2vw,21px);
+    color:var(--cream-fade);
+    animation:fadeUp .7s cubic-bezier(.22,1,.36,1) .12s both;
+  }
+  .imprint{
+    margin-top:var(--sp6);
+    display:flex;gap:var(--sp5);justify-content:center;flex-wrap:wrap;
+    font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted,#9a8f74);
+    animation:fadeUp .7s cubic-bezier(.22,1,.36,1) .24s both;
+  }
+  .imprint span{color:#a99a78}
+  .imprint b{color:var(--marigold);font-weight:600}
+
+  @keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
+
+  /* ============ CONTROL BAR ============ */
+  .controls{
+    position:sticky;top:0;z-index:40;
+    background:rgba(13,21,38,.9);
+    backdrop-filter:blur(10px);
+    border-bottom:1px solid rgba(232,166,58,.25);
+    padding:var(--sp3) var(--sp5);
+    display:flex;flex-wrap:wrap;gap:var(--sp5);align-items:center;justify-content:center;
+  }
+  .ctl-group{display:flex;align-items:center;gap:var(--sp3);flex-wrap:wrap;justify-content:center}
+  .ctl-label{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--mint);font-weight:700}
+  .seps{display:flex;gap:6px;flex-wrap:wrap}
+  button.sep{
+    font-family:var(--sans);
+    font-size:12px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;
+    padding:7px 12px;
+    border-radius:30px;
+    border:1px solid rgba(242,231,207,.3);
+    background:transparent;color:var(--cream);
+    cursor:pointer;transition:all .18s ease;
+  }
+  button.sep[data-sep="all"].active{background:var(--cream);color:var(--midnight-deep);border-color:var(--cream)}
+  button.sep[data-sep="red"].active{background:var(--acid);color:var(--cream);border-color:var(--acid)}
+  button.sep[data-sep="gold"].active{background:var(--marigold);color:var(--midnight-deep);border-color:var(--marigold)}
+  button.sep[data-sep="mint"].active{background:var(--mint);color:var(--midnight-deep);border-color:var(--mint)}
+  button.sep[data-sep="blue"].active{background:var(--midnight);color:var(--cream);border-color:var(--marigold)}
+  button.sep:hover{transform:translateY(-2px)}
+  button.sep:focus-visible,button.toggle:focus-visible,button.wall-card:focus-visible,.chip:focus-visible{outline:2px solid var(--marigold);outline-offset:3px}
+
+  button.toggle{
+    font-family:var(--sans);font-size:12px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;
+    padding:7px 14px;border-radius:30px;cursor:pointer;transition:all .18s ease;
+    border:1px solid var(--marigold);background:transparent;color:var(--marigold);
+    display:inline-flex;align-items:center;gap:8px;
+  }
+  button.toggle[aria-pressed="true"]{background:var(--marigold);color:var(--midnight-deep)}
+  button.toggle:hover{transform:translateY(-2px)}
+
+  input[type=range]{
+    -webkit-appearance:none;appearance:none;width:120px;height:4px;border-radius:4px;
+    background:linear-gradient(90deg,var(--acid),var(--marigold),var(--mint));outline:none;cursor:pointer;
+  }
+  input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;border-radius:50%;background:var(--cream);border:2px solid var(--midnight-deep);cursor:pointer}
+  input[type=range]::-moz-range-thumb{width:18px;height:18px;border-radius:50%;background:var(--cream);border:2px solid var(--midnight-deep);cursor:pointer}
+
+  /* ============ POSTER WALL ============ */
+  main{padding:var(--sp8) var(--sp5) var(--sp9);max-width:1400px;margin:0 auto}
+  .section-head{text-align:center;margin-bottom:var(--sp7)}
+  .section-head h2{font-family:var(--serif);font-weight:400;font-size:clamp(28px,4vw,38px);margin:0 0 var(--sp2)}
+  .section-head p{color:var(--cream-fade);max-width:560px;margin:0 auto}
+
+  .wall{
+    display:grid;
+    grid-template-columns:repeat(var(--wall-cols),1fr);
+    gap:var(--sp6);
+    transition:gap .3s ease;
+  }
+  @media(max-width:900px){.wall{--wall-cols:2!important}}
+  @media(max-width:560px){.wall{--wall-cols:1!important}}
+
+  .poster-card{
+    background:transparent;border:none;padding:0;cursor:pointer;text-align:left;
+    animation:fadeUp .7s cubic-bezier(.22,1,.36,1) both;
+    display:flex;flex-direction:column;gap:var(--sp3);
+  }
+  .poster-frame{
+    position:relative;
+    border-radius:4px;
+    overflow:hidden;
+    box-shadow:var(--card-shadow);
+    transition:transform .25s cubic-bezier(.22,1,.36,1),box-shadow .25s ease;
+    /* torn / imperfect edge via clip */
+    background:var(--cream);
+  }
+  .poster-card:hover .poster-frame,.poster-card:focus-visible .poster-frame{transform:translateY(-6px) rotate(-.4deg);box-shadow:var(--hover-shadow)}
+  .poster-frame svg{display:block;width:100%;height:auto}
+  /* imperfect deckle edge overlay */
+  .poster-frame::after{
+    content:"";position:absolute;inset:0;pointer-events:none;
+    box-shadow:inset 0 0 0 6px var(--cream), inset 0 0 22px rgba(20,18,10,.22);
+    mix-blend-mode:multiply;opacity:.5;
+  }
+  .poster-meta{padding:0 2px}
+  .poster-meta .title{font-family:var(--serif);font-size:22px;line-height:1.1;margin:0 0 4px;color:var(--cream)}
+  .poster-meta .venue{font-size:13px;color:var(--marigold);letter-spacing:.04em}
+  .poster-meta .edition{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:#9a8f74;margin-top:4px}
+
+  /* Separation view: dim channels not selected */
+  svg .sep-red,svg .sep-gold,svg .sep-mint,svg .sep-blue,svg .reg{transition:opacity .35s ease}
+  .wall[data-view="red"] .sep-gold,.wall[data-view="red"] .sep-mint,.wall[data-view="red"] .sep-blue{opacity:.06}
+  .wall[data-view="gold"] .sep-red,.wall[data-view="gold"] .sep-mint,.wall[data-view="gold"] .sep-blue{opacity:.06}
+  .wall[data-view="mint"] .sep-red,.wall[data-view="mint"] .sep-gold,.wall[data-view="mint"] .sep-blue{opacity:.06}
+  .wall[data-view="blue"] .sep-red,.wall[data-view="blue"] .sep-gold,.wall[data-view="blue"] .sep-mint{opacity:.06}
+  svg .reg{opacity:0}
+  .wall.show-reg svg .reg{opacity:.9}
+
+  /* animated screen-print pull */
+  .poster-card.printing .ink-layer{animation:pull 1.1s cubic-bezier(.5,0,.2,1) both}
+  @keyframes pull{
+    from{transform:translateY(-14%);opacity:0}
+    to{transform:translateY(0);opacity:1}
+  }
+
+  /* ============ TYPE COMPARISON ============ */
+  .type-lab{margin-top:var(--sp9);padding-top:var(--sp7);border-top:2px solid rgba(232,166,58,.28)}
+  .type-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--sp5);margin-top:var(--sp6)}
+  .type-card{
+    background:var(--cream);color:var(--midnight-deep);
+    border-radius:var(--radius);padding:var(--sp6) var(--sp5);
+    box-shadow:var(--card-shadow);position:relative;overflow:hidden;
+    transition:transform .2s ease,box-shadow .2s ease;
+  }
+  .type-card:hover{transform:translateY(-4px);box-shadow:var(--hover-shadow)}
+  .type-card::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 80% 10%,rgba(217,50,47,.12),transparent 60%);pointer-events:none}
+  .type-card .tc-label{font-size:11px;letter-spacing:.16em;text-transform:uppercase;color:var(--acid);font-weight:700;margin-bottom:var(--sp3)}
+  .type-card .specimen{font-size:clamp(30px,4.5vw,46px);line-height:1;margin:0 0 var(--sp3)}
+  .type-card .desc{font-size:14px;color:#4a4234;line-height:1.5}
+  .ts-didone .specimen{font-family:var(--serif);font-weight:400;letter-spacing:-.01em}
+  .ts-condensed .specimen{font-family:var(--sans);font-weight:800;letter-spacing:-.03em;transform:scaleX(.82);transform-origin:left}
+  .ts-woodblock .specimen{font-family:var(--serif);font-weight:700;letter-spacing:.02em;text-shadow:2px 2px 0 var(--marigold),4px 4px 0 rgba(217,50,47,.35)}
+  .ts-script .specimen{font-family:'Snell Roundhand','Segoe Script',cursive;font-style:italic;font-weight:400}
+
+  /* ============ PROCESS DRAWER ============ */
+  .drawer-tab{
+    position:fixed;right:0;top:50%;transform:translateY(-50%) rotate(0deg);z-index:55;
+    transform-origin:center;
+  }
+  .drawer-tab button{
+    writing-mode:vertical-rl;
+    background:var(--acid);color:var(--cream);border:none;
+    padding:var(--sp5) var(--sp2);font-size:12px;letter-spacing:.2em;text-transform:uppercase;font-weight:700;
+    border-radius:12px 0 0 12px;cursor:pointer;box-shadow:-6px 0 20px rgba(0,0,0,.35);
+    transition:background .2s ease;
+  }
+  .drawer-tab button:hover{background:#c22a27}
+  .drawer{
+    position:fixed;top:0;right:0;height:100%;width:min(440px,92vw);z-index:60;
+    background:var(--midnight);
+    border-left:3px solid var(--marigold);
+    box-shadow:-24px 0 60px rgba(0,0,0,.55);
+    transform:translateX(100%);transition:transform .4s cubic-bezier(.22,1,.36,1);
+    overflow-y:auto;padding:var(--sp7) var(--sp5) var(--sp8);
+  }
+  .drawer.open{transform:translateX(0)}
+  .drawer h3{font-family:var(--serif);font-weight:400;font-size:32px;margin:0 0 var(--sp2)}
+  .drawer .sub{color:var(--mint);font-size:12px;letter-spacing:.16em;text-transform:uppercase;margin-bottom:var(--sp6)}
+  .drawer .close{position:absolute;top:var(--sp4);right:var(--sp4);background:transparent;border:1px solid var(--cream);color:var(--cream);border-radius:50%;width:38px;height:38px;font-size:20px;cursor:pointer;line-height:1}
+  .drawer .close:hover{background:var(--acid);border-color:var(--acid)}
+  .proc-item{border-top:1px solid rgba(232,166,58,.28);padding:var(--sp5) 0}
+  .proc-item h4{margin:0 0 var(--sp2);font-size:15px;letter-spacing:.1em;text-transform:uppercase;color:var(--marigold);display:flex;align-items:center;gap:10px}
+  .proc-item .swatch{width:14px;height:14px;border-radius:3px;display:inline-block}
+  .proc-item p{margin:0;font-size:14px;color:var(--cream-fade);line-height:1.6}
+
+  /* ============ LIGHTBOX ============ */
+  .lightbox{
+    position:fixed;inset:0;z-index:80;display:none;
+    background:rgba(6,10,18,.94);
+    backdrop-filter:blur(6px);
+    padding:var(--sp5);
+    overflow-y:auto;
+  }
+  .lightbox.open{display:flex;align-items:flex-start;justify-content:center;animation:lbfade .3s ease both}
+  @keyframes lbfade{from{opacity:0}to{opacity:1}}
+  .lb-inner{
+    display:grid;grid-template-columns:minmax(0,1.2fr) minmax(0,1fr);gap:var(--sp7);
+    max-width:1100px;width:100%;margin:auto;padding:var(--sp6) 0;
+  }
+  @media(max-width:820px){.lb-inner{grid-template-columns:1fr;gap:var(--sp5)}}
+  .lb-poster{background:var(--cream);border-radius:4px;overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.6);position:relative}
+  .lb-poster svg{display:block;width:100%;height:auto}
+  .lb-info h3{font-family:var(--serif);font-weight:400;font-size:clamp(30px,5vw,46px);margin:0 0 var(--sp2);line-height:1}
+  .lb-info .lb-venue{color:var(--marigold);font-size:16px;margin-bottom:var(--sp5)}
+  .lb-curator{border-left:3px solid var(--acid);padding-left:var(--sp4);margin:var(--sp5) 0;color:var(--cream-fade);font-style:italic;line-height:1.7}
+  .lb-facts{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp3) var(--sp5);margin-top:var(--sp5)}
+  .lb-facts div{border-top:1px solid rgba(232,166,58,.28);padding-top:var(--sp2)}
+  .lb-facts .k{font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--mint)}
+  .lb-facts .v{font-size:15px;color:var(--cream)}
+  .lb-seps{display:flex;gap:8px;margin-top:var(--sp5);flex-wrap:wrap}
+  .lb-close{position:fixed;top:var(--sp4);right:var(--sp4);z-index:90;background:var(--acid);color:var(--cream);border:none;border-radius:50%;width:46px;height:46px;font-size:24px;cursor:pointer;line-height:1;box-shadow:0 6px 20px rgba(0,0,0,.4)}
+  .lb-close:hover{transform:rotate(90deg);transition:transform .3s ease}
+
+  /* ============ FOOTER ============ */
+  footer{
+    text-align:center;padding:var(--sp8) var(--sp5);
+    border-top:2px solid rgba(232,166,58,.28);
+    color:#9a8f74;font-size:13px;line-height:1.8;
+  }
+  footer .colophon{max-width:560px;margin:0 auto var(--sp5)}
+  footer .palette-row{display:flex;gap:6px;justify-content:center;margin-bottom:var(--sp5)}
+  footer .pd{width:34px;height:34px;border-radius:6px;border:1px solid rgba(242,231,207,.2)}
+
+  @media(prefers-reduced-motion:reduce){
+    *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}
+    body::before{animation:none}
+  }
+</style>
+</head>
+<body>
+<div class="wrap">
+
+  <header class="masthead">
+    <span class="kicker">Museum of Vernacular Print · Study Wing</span>
+    <h1 class="logo"><span class="a">Deadhead</span><span class="b">Print Lab</span></h1>
+    <p class="lede">A working screen-print studio, opened for public view — five original poster studies drawn in the handmade visual language of concert culture, presented layer by layer.</p>
+    <div class="imprint">
+      <span>Curated Edition · <b>Vol. 03</b></span>
+      <span>Five Studies · <b>1971–1978 (imagined)</b></span>
+      <span>Ink on <b>sun-faded cream stock</b></span>
+    </div>
+  </header>
+
+  <div class="controls" role="region" aria-label="Studio controls">
+    <div class="ctl-group">
+      <span class="ctl-label" id="seplabel">Color separation</span>
+      <div class="seps" role="group" aria-labelledby="seplabel">
+        <button class="sep active" data-sep="all" aria-pressed="true">Full pull</button>
+        <button class="sep" data-sep="red" aria-pressed="false">Acid red</button>
+        <button class="sep" data-sep="gold" aria-pressed="false">Marigold</button>
+        <button class="sep" data-sep="mint" aria-pressed="false">Mint</button>
+        <button class="sep" data-sep="blue" aria-pressed="false">Midnight</button>
+      </div>
+    </div>
+    <div class="ctl-group">
+      <button class="toggle" id="regToggle" aria-pressed="false">✛ Registration marks</button>
+      <button class="toggle" id="repullBtn" aria-pressed="false">↻ Re-pull screens</button>
+    </div>
+    <div class="ctl-group">
+      <span class="ctl-label" id="denslabel">Wall density</span>
+      <input type="range" id="density" min="2" max="5" value="3" step="1" aria-labelledby="denslabel" aria-valuetext="3 columns">
+    </div>
+  </div>
+
+  <main>
+    <div class="section-head">
+      <h2>The Poster Wall</h2>
+      <p>Each study is a stack of hand-cut screens. Switch separations to isolate a single ink; reveal the registration crosses the printers used to line the screens up.</p>
+    </div>
+
+    <div class="wall" id="wall" data-view="all" aria-label="Poster studies"></div>
+
+    <section class="type-lab" aria-labelledby="typehead">
+      <div class="section-head">
+        <h2 id="typehead">Type Treatments, Compared</h2>
+        <p>The same three words set four ways — the tension between a refined didone and a battered woodblock is where the whole aesthetic lives.</p>
+      </div>
+      <div class="type-grid">
+        <div class="type-card ts-didone">
+          <div class="tc-label">Study A · High Didone</div>
+          <p class="specimen">Dance the Night</p>
+          <p class="desc">Extreme thick-to-thin contrast, tight tracking. Elegant, museum-poster restraint against the chaos of the imagery.</p>
+        </div>
+        <div class="type-card ts-woodblock">
+          <div class="tc-label">Study B · Woodblock Slab</div>
+          <p class="specimen">Dance the Night</p>
+          <p class="desc">Heavy serif knocked out of register on purpose — two colors kiss and shadow. Reads as vintage letterpress at ten paces.</p>
+        </div>
+        <div class="type-card ts-condensed">
+          <div class="tc-label">Study C · Condensed Gothic</div>
+          <p class="specimen">Dance the Night</p>
+          <p class="desc">Squeezed sans, maximum words per inch. The utilitarian voice of the handbill and the road case stencil.</p>
+        </div>
+        <div class="type-card ts-script">
+          <div class="tc-label">Study D · Loose Script</div>
+          <p class="specimen">Dance the Night</p>
+          <p class="desc">A ballpoint-loose hand — the human, off-the-cuff mark that keeps the whole composition from feeling designed.</p>
+        </div>
+      </div>
+    </section>
+  </main>
+
+  <!-- PROCESS DRAWER -->
+  <div class="drawer-tab">
+    <button id="drawerOpen" aria-expanded="false" aria-controls="drawer">Process notes</button>
+  </div>
+  <aside class="drawer" id="drawer" role="dialog" aria-modal="false" aria-labelledby="drawerTitle" aria-hidden="true">
+    <button class="close" id="drawerClose" aria-label="Close process notes">×</button>
+    <h3 id="drawerTitle">In the Shop</h3>
+    <p class="sub">How these studies were made</p>
+
+    <div class="proc-item">
+      <h4><span class="swatch" style="background:var(--acid)"></span>Ink & Overprint</h4>
+      <p>Four oil-based rubber inks pulled in strict order — midnight base, marigold, mint, then acid red as the top hit. Where two transparent inks overlap, a third color is <em>born</em> on the paper. Nothing is mixed in the bucket that could be mixed on the sheet.</p>
+    </div>
+    <div class="proc-item">
+      <h4><span class="swatch" style="background:var(--cream-fade)"></span>Paper & Deckle</h4>
+      <p>110 lb cover, cream, deliberately foxed and sun-faded before printing so no two sheets share a ground tone. Torn — never cut — to a natural deckle edge. The imperfection is the signature.</p>
+    </div>
+    <div class="proc-item">
+      <h4><span class="swatch" style="background:var(--marigold)"></span>Halftone</h4>
+      <p>Photographic passages are broken to a coarse 25-line elliptical dot, shot on lith film. Big enough to see with the naked eye — the dot is a texture, not a hidden trick.</p>
+    </div>
+    <div class="proc-item">
+      <h4><span class="swatch" style="background:var(--mint)"></span>Letterpress Hit</h4>
+      <p>Display type is set in salvaged wood type and run last on a Vandercook, biting a slight deboss into the screen ink so the words sit physically <em>below</em> the surface. Register is intentionally a hair loose.</p>
+    </div>
+    <div class="proc-item">
+      <h4><span class="swatch" style="background:var(--midnight)"></span>Registration</h4>
+      <p>Every screen is lined up to hand-drawn corner crosses (✛). Toggle them on across the wall to see the printer's scaffolding — the marks that would be trimmed off the final edition.</p>
+    </div>
+  </aside>
+
+  <!-- LIGHTBOX -->
+  <div class="lightbox" id="lightbox" role="dialog" aria-modal="true" aria-labelledby="lbTitle">
+    <button class="lb-close" id="lbClose" aria-label="Close poster view">×</button>
+    <div class="lb-inner">
+      <div class="lb-poster" id="lbPoster"></div>
+      <div class="lb-info">
+        <h3 id="lbTitle"></h3>
+        <div class="lb-venue" id="lbVenue"></div>
+        <blockquote class="lb-curator" id="lbCurator"></blockquote>
+        <div class="lb-facts">
+          <div><div class="k">Edition</div><div class="v" id="lbEdition"></div></div>
+          <div><div class="k">Date</div><div class="v" id="lbDate"></div></div>
+          <div><div class="k">Screens</div><div class="v" id="lbScreens"></div></div>
+          <div><div class="k">Motif</div><div class="v" id="lbMotif"></div></div>
+        </div>
+        <div class="lb-seps" role="group" aria-label="Isolate a separation in this view">
+          <button class="sep active" data-lb="all" aria-pressed="true">Full</button>
+          <button class="sep" data-lb="red" aria-pressed="false">Red</button>
+          <button class="sep" data-lb="gold" aria-pressed="false">Gold</button>
+          <button class="sep" data-lb="mint" aria-pressed="false">Mint</button>
+          <button class="sep" data-lb="blue" aria-pressed="false">Blue</button>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <footer>
+    <div class="palette-row" aria-hidden="true">
+      <div class="pd" style="background:#e6d7b4" title="Sun-faded cream"></div>
+      <div class="pd" style="background:#16233f" title="Midnight blue"></div>
+      <div class="pd" style="background:#d9322f" title="Acid red"></div>
+      <div class="pd" style="background:#e8a63a" title="Marigold"></div>
+      <div class="pd" style="background:#7ec9a8" title="Mint"></div>
+    </div>
+    <p class="colophon">Deadhead Print Lab is a fictional studio and museum exhibit. All motifs — dancing skeletons, roses, lightning, celestial landscapes, road cases — are newly drawn abstractions, not reproductions of any existing logo or artwork. Venues, dates, and edition numbers are imagined for the study.</p>
+    <p class="allcaps">A self-contained artifact · No external resources</p>
+  </footer>
+
+</div>
+
+<script>
+(function(){
+  "use strict";
+
+  /* ---------- POSTER DATA + PROCEDURAL SVG ---------- */
+  // Each poster is a set of layered SVG groups tagged by separation channel.
+  // Motifs are abstract shapes: skeleton, rose, lightning, celestial, road case.
+
+  const REG = `
+    <g class="reg" stroke="#16233f" stroke-width="1.2" opacity="0.9">
+      <g transform="translate(22,22)"><line x1="-9" y1="0" x2="9" y2="0"/><line x1="0" y1="-9" x2="0" y2="9"/><circle r="7" fill="none"/></g>
+      <g transform="translate(378,22)"><line x1="-9" y1="0" x2="9" y2="0"/><line x1="0" y1="-9" x2="0" y2="9"/><circle r="7" fill="none"/></g>
+      <g transform="translate(22,538)"><line x1="-9" y1="0" x2="9" y2="0"/><line x1="0" y1="-9" x2="0" y2="9"/><circle r="7" fill="none"/></g>
+      <g transform="translate(378,538)"><line x1="-9" y1="0" x2="9" y2="0"/><line x1="0" y1="-9" x2="0" y2="9"/><circle r="7" fill="none"/></g>
+    </g>`;
+
+  // halftone dot pattern def (coarse)
+  function defs(id){
+    return `<defs>
+      <pattern id="ht${id}" width="9" height="9" patternUnits="userSpaceOnUse" patternTransform="rotate(15)">
+        <rect width="9" height="9" fill="none"/>
+        <circle cx="4.5" cy="4.5" r="2.4" fill="currentColor"/>
+      </pattern>
+      <filter id="rough${id}"><feTurbulence type="fractalNoise" baseFrequency="0.9" numOctaves="2" result="n"/><feDisplacementMap in="SourceGraphic" in2="n" scale="2.4"/></filter>
+    </defs>`;
+  }
+
+  // --- Motif drawers (return svg strings placed in a group) ---
+  function skeletonDance(){ // dancing skeleton abstraction
+    return `
+      <g class="ink-layer sep-blue" fill="none" stroke="#16233f" stroke-width="7" stroke-linecap="round" filter="url(#rough1)">
+        <circle cx="200" cy="150" r="34"/>
+        <path d="M200 184 L200 300"/>
+        <path d="M200 210 L150 260 M200 210 L258 250"/>
+        <path d="M200 300 L160 400 M200 300 L246 405"/>
+      </g>
+      <g class="ink-layer sep-red" fill="#d9322f" filter="url(#rough1)">
+        <circle cx="188" cy="145" r="6"/><circle cx="214" cy="145" r="6"/>
+        <path d="M175 300 q25 22 50 0 l4 20 q-29 22 -58 0 Z"/>
+      </g>
+      <g class="ink-layer sep-gold" fill="none" stroke="#e8a63a" stroke-width="4" stroke-linecap="round">
+        <path d="M150 260 l-14 -8 -14 10 M258 250 l16 -6 12 12"/>
+      </g>`;
+  }
+  function roseBloom(){
+    return `
+      <g class="ink-layer sep-red" fill="#d9322f" filter="url(#rough2)">
+        <path d="M200 250 q-70 -60 0 -120 q70 60 0 120 Z"/>
+        <path d="M200 250 q-90 -20 -60 -110 q80 30 60 110 Z"/>
+        <path d="M200 250 q90 -20 60 -110 q-80 30 -60 110 Z"/>
+        <circle cx="200" cy="215" r="26" fill="#16233f"/>
+      </g>
+      <g class="ink-layer sep-mint" fill="none" stroke="#7ec9a8" stroke-width="9" stroke-linecap="round">
+        <path d="M200 270 L200 470"/>
+        <path d="M200 360 q-70 -20 -95 -70 M200 400 q70 -10 100 -55"/>
+      </g>
+      <g class="ink-layer sep-gold" fill="#e8a63a">
+        <circle cx="200" cy="215" r="9"/>
+      </g>`;
+  }
+  function lightningStorm(){
+    return `
+      <g class="ink-layer sep-blue" fill="#16233f">
+        <path d="M40 40 h320 v480 h-320 Z" opacity="0.16"/>
+      </g>
+      <g class="ink-layer sep-gold" fill="#e8a63a" filter="url(#rough3)">
+        <path d="M230 60 L150 280 L210 280 L120 500 L250 250 L190 250 Z"/>
+      </g>
+      <g class="ink-layer sep-red" fill="none" stroke="#d9322f" stroke-width="6">
+        <path d="M60 120 q80 40 0 80 M300 380 q-70 40 0 80"/>
+      </g>
+      <g class="ink-layer sep-mint" fill="#7ec9a8" opacity="0.9">
+        <circle cx="90" cy="90" r="5"/><circle cx="320" cy="150" r="5"/><circle cx="300" cy="470" r="5"/><circle cx="80" cy="440" r="5"/>
+      </g>`;
+  }
+  function celestial(){
+    return `
+      <g class="ink-layer sep-blue" fill="#16233f">
+        <path d="M40 300 q160 -120 320 0 v220 h-320 Z"/>
+      </g>
+      <g class="ink-layer sep-gold" fill="#e8a63a" filter="url(#rough4)">
+        <circle cx="200" cy="180" r="70"/>
+      </g>
+      <g class="ink-layer sep-red" fill="#d9322f">
+        <path d="M200 110 a70 70 0 0 0 0 140 a52 52 0 0 1 0 -140 Z"/>
+      </g>
+      <g class="ink-layer sep-mint" fill="#7ec9a8">
+        <path d="M90 90 l6 14 15 2 -11 11 3 15 -13 -8 -13 8 3 -15 -11 -11 15 -2 Z"/>
+        <path d="M320 260 l4 10 11 1 -8 8 2 11 -9 -6 -9 6 2 -11 -8 -8 11 -1 Z"/>
+        <circle cx="300" cy="120" r="4"/><circle cx="120" cy="230" r="4"/>
+      </g>
+      <g class="ink-layer sep-mint" fill="none" stroke="#7ec9a8" stroke-width="3" opacity="0.7">
+        <path d="M40 360 q160 -110 320 0"/>
+      </g>`;
+  }
+  function roadCase(){
+    return `
+      <g class="ink-layer sep-blue" fill="#16233f" filter="url(#rough5)">
+        <rect x="90" y="180" width="220" height="220" rx="8"/>
+      </g>
+      <g class="ink-layer sep-gold" fill="none" stroke="#e8a63a" stroke-width="8">
+        <rect x="90" y="180" width="220" height="220" rx="8"/>
+        <path d="M90 240 h220 M90 340 h220"/>
+      </g>
+      <g class="ink-layer sep-red" fill="#d9322f">
+        <circle cx="120" cy="210" r="9"/><circle cx="280" cy="210" r="9"/>
+        <circle cx="120" cy="370" r="9"/><circle cx="280" cy="370" r="9"/>
+        <rect x="180" y="285" width="40" height="30" rx="4"/>
+      </g>
+      <g class="ink-layer sep-mint" fill="#7ec9a8">
+        <path d="M150 470 q50 -30 100 0" stroke="#7ec9a8" stroke-width="6" fill="none"/>
+        <circle cx="130" cy="470" r="14"/><circle cx="270" cy="470" r="14"/>
+      </g>`;
+  }
+
+  const MOTIFS = [skeletonDance, roseBloom, lightningStorm, celestial, roadCase];
+
+  const POSTERS = [
+    { id:1, title:"Skeleton Waltz", venue:"The Marigold Ballroom, Eugene OR",
+      edition:"AP 12 / 90", date:"May 3, 1972", screens:"4 screens · 1 letterpress hit", motif:"Dancing skeleton",
+      curator:"Study 01 isolates the figure to almost nothing — a skull, a spine, four thrown limbs. The joy is entirely in the gesture, printed loose so the red mouth and blue bones never quite line up. That slippage is the dance.",
+      draw:skeletonDance, htColor:"#16233f" },
+    { id:2, title:"Rose in Overprint", venue:"Cascade Field House, Bozeman MT",
+      edition:"38 / 120", date:"Sept 19, 1974", screens:"4 screens · coarse halftone", motif:"Rose",
+      curator:"A single bloom where the acid red petals cross a midnight core to make a bruised violet the bucket never held. The mint stem is printed last and low, so it debosses into the ground — you can feel it with a fingertip.",
+      draw:roseBloom, htColor:"#d9322f" },
+    { id:3, title:"Thirteen-Point Bolt", venue:"Old Armory, Winslow AZ",
+      edition:"07 / 75", date:"July 11, 1976", screens:"4 screens · knocked-out gold", motif:"Lightning",
+      curator:"The bolt is knocked out of a marigold field and split down the middle by a hairline of register drift. Two mint sparks and a red charge in the corners keep the eye ricocheting around the sheet.",
+      draw:lightningStorm, htColor:"#e8a63a" },
+    { id:4, title:"Celestial Landscape", venue:"Lantern Amphitheater, Taos NM",
+      edition:"51 / 150", date:"Oct 2, 1977", screens:"5 screens · split-fountain sky", motif:"Celestial",
+      curator:"A sun eclipsed to a crescent over rolling midnight hills, with mint stars hand-placed off the grid. The split-fountain blend was pulled once and never repeated, so this is the only true state.",
+      draw:celestial, htColor:"#e8a63a" },
+    { id:5, title:"Road Case No. 9", venue:"The Freight Depot, Council Bluffs IA",
+      edition:"22 / 60", date:"Feb 28, 1978", screens:"4 screens · stencil face", motif:"Road case",
+      curator:"The most utilitarian study — a flight case rendered as pure stencil, gold rule over blue body, red latches. It's a portrait of the labor behind the show: the thing that carries the whole rig to the next town.",
+      draw:roadCase, htColor:"#16233f" }
+  ];
+
+  function posterSVG(p, extra){
+    const idx = p.id;
+    return `<svg viewBox="0 0 400 560" role="img" aria-label="${p.title} — ${p.motif} poster study" preserveAspectRatio="xMidYMid meet">
+      ${defs(idx)}
+      <rect x="0" y="0" width="400" height="560" fill="#e6d7b4"/>
+      <!-- faded overprint texture -->
+      <g color="#16233f" opacity="0.10"><rect x="30" y="430" width="340" height="110" fill="url(#ht${idx})"/></g>
+      ${p.draw()}
+      <!-- title bar -->
+      <g class="ink-layer sep-blue">
+        <rect x="30" y="452" width="340" height="70" fill="#16233f"/>
+      </g>
+      <text x="200" y="497" text-anchor="middle" font-family="Didot,'Bodoni MT',Georgia,serif" font-size="30" fill="#f2e7cf" class="sep-red">${p.title}</text>
+      <text x="200" y="540" text-anchor="middle" font-family="Helvetica,Arial,sans-serif" font-size="11" letter-spacing="2" fill="#e8a63a" class="sep-gold">${p.date.toUpperCase()}</text>
+      ${REG}
+    </svg>`;
+  }
+
+  /* ---------- RENDER WALL ---------- */
+  const wall = document.getElementById('wall');
+  POSTERS.forEach(function(p,i){
+    const card = document.createElement('button');
+    card.className = 'poster-card';
+    card.style.animationDelay = (i*90)+'ms';
+    card.setAttribute('aria-label','Open '+p.title+' in full view');
+    card.innerHTML =
+      '<div class="poster-frame">'+posterSVG(p)+'</div>'+
+      '<div class="poster-meta">'+
+        '<p class="title">'+p.title+'</p>'+
+        '<p class="venue">'+p.venue+'</p>'+
+        '<p class="edition">Edition '+p.edition+' · '+p.screens+'</p>'+
+      '</div>';
+    card.addEventListener('click', function(){ openLightbox(p); });
+    wall.appendChild(card);
+  });
+
+  /* ---------- SEPARATION CONTROLS ---------- */
+  const sepBtns = document.querySelectorAll('.controls .sep');
+  sepBtns.forEach(function(b){
+    b.addEventListener('click', function(){
+      sepBtns.forEach(function(x){x.classList.remove('active');x.setAttribute('aria-pressed','false');});
+      b.classList.add('active'); b.setAttribute('aria-pressed','true');
+      wall.setAttribute('data-view', b.dataset.sep);
+    });
+  });
+
+  /* ---------- REGISTRATION TOGGLE ---------- */
+  const regToggle = document.getElementById('regToggle');
+  regToggle.addEventListener('click', function(){
+    const on = wall.classList.toggle('show-reg');
+    regToggle.setAttribute('aria-pressed', on ? 'true':'false');
+  });
+
+  /* ---------- RE-PULL (animate screen print) ---------- */
+  const repull = document.getElementById('repullBtn');
+  repull.addEventListener('click', function(){
+    const cards = document.querySelectorAll('.poster-card');
+    cards.forEach(function(c){ c.classList.remove('printing'); });
+    // force reflow then re-add staggered
+    void wall.offsetWidth;
+    cards.forEach(function(c,i){
+      setTimeout(function(){ c.classList.add('printing'); }, i*120);
+    });
+  });
+
+  /* ---------- DENSITY SLIDER ---------- */
+  const density = document.getElementById('density');
+  density.addEventListener('input', function(){
+    wall.style.setProperty('--wall-cols', density.value);
+    density.setAttribute('aria-valuetext', density.value+' columns');
+  });
+
+  /* ---------- PROCESS DRAWER ---------- */
+  const drawer = document.getElementById('drawer');
+  const drawerOpen = document.getElementById('drawerOpen');
+  const drawerClose = document.getElementById('drawerClose');
+  function setDrawer(open){
+    drawer.classList.toggle('open', open);
+    drawer.setAttribute('aria-hidden', open ? 'false':'true');
+    drawerOpen.setAttribute('aria-expanded', open ? 'true':'false');
+    if(open) drawerClose.focus();
+  }
+  drawerOpen.addEventListener('click', function(){ setDrawer(!drawer.classList.contains('open')); });
+  drawerClose.addEventListener('click', function(){ setDrawer(false); drawerOpen.focus(); });
+
+  /* ---------- LIGHTBOX ---------- */
+  const lightbox = document.getElementById('lightbox');
+  const lbPoster = document.getElementById('lbPoster');
+  const lbClose = document.getElementById('lbClose');
+  let lastFocus = null;
+
+  function openLightbox(p){
+    lastFocus = document.activeElement;
+    lbPoster.innerHTML = posterSVG(p);
+    lbPoster.className = 'lb-poster';
+    document.getElementById('lbTitle').textContent = p.title;
+    document.getElementById('lbVenue').textContent = p.venue;
+    document.getElementById('lbCurator').textContent = p.curator;
+    document.getElementById('lbEdition').textContent = p.edition;
+    document.getElementById('lbDate').textContent = p.date;
+    document.getElementById('lbScreens').textContent = p.screens;
+    document.getElementById('lbMotif').textContent = p.motif;
+    // reset lb sep buttons
+    lbSeps.forEach(function(x){x.classList.remove('active');x.setAttribute('aria-pressed','false');});
+    lbSeps[0].classList.add('active'); lbSeps[0].setAttribute('aria-pressed','true');
+    applyLbView('all');
+    lightbox.classList.add('open');
+    document.body.style.overflow='hidden';
+    lbClose.focus();
+  }
+  function closeLightbox(){
+    lightbox.classList.remove('open');
+    document.body.style.overflow='';
+    if(lastFocus) lastFocus.focus();
+  }
+  lbClose.addEventListener('click', closeLightbox);
+  lightbox.addEventListener('click', function(e){ if(e.target===lightbox) closeLightbox(); });
+
+  // lightbox separation isolation
+  const lbSeps = Array.prototype.slice.call(document.querySelectorAll('[data-lb]'));
+  function applyLbView(v){
+    const svg = lbPoster.querySelector('svg');
+    if(!svg) return;
+    ['red','gold','mint','blue'].forEach(function(ch){
+      svg.querySelectorAll('.sep-'+ch).forEach(function(el){
+        el.style.opacity = (v==='all'||v===ch) ? '' : '0.06';
+      });
+    });
+  }
+  lbSeps.forEach(function(b){
+    b.addEventListener('click', function(){
+      lbSeps.forEach(function(x){x.classList.remove('active');x.setAttribute('aria-pressed','false');});
+      b.classList.add('active'); b.setAttribute('aria-pressed','true');
+      applyLbView(b.dataset.lb);
+    });
+  });
+
+  /* ---------- KEYBOARD ---------- */
+  document.addEventListener('keydown', function(e){
+    if(e.key==='Escape'){
+      if(lightbox.classList.contains('open')) closeLightbox();
+      else if(drawer.classList.contains('open')){ setDrawer(false); drawerOpen.focus(); }
+    }
+  });
+
+  // kick an initial print pull once loaded
+  window.addEventListener('load', function(){
+    setTimeout(function(){ repull.click(); repull.setAttribute('aria-pressed','false'); }, 400);
+  });
+
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/b05597bd9f5a/qwen25-7b.html b/data/artifacts/b05597bd9f5a/qwen25-7b.html
new file mode 100644
index 0000000..bcecc12
--- /dev/null
+++ b/data/artifacts/b05597bd9f5a/qwen25-7b.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Deadhead Print Lab</title>
+    <style>
+        /* Typography */
+        body { font-family: 'Didot', Georgia, serif; }
+        h1, .h1 { font-size: 50px; letter-spacing: .15em; text-transform: uppercase; color: #b0472e; }
+        p, .caption { font-size: 16px; }
+
+        /* Palette */
+        :root {
+            --bg-color: #f7efe6;
+            --surface-color: #fff9f1;
+            --text-color: #3a2c22;
+            --accent-color: #c65f38;
+        }
+        
+        .card { background: var(--bg-color); color: var(--text-color); border-radius: 14px; padding: 24px; margin-bottom: 24px; overflow: hidden; box-shadow: 0 8px 24px rgba(0,0,0,.12) inset; }
+        .card:hover { box-shadow: 0 16px 48px rgba(0,0,0,.18) inset; }
+        @keyframes glow { to { text-shadow: 0 0 24px var(--accent-color); } }
+        
+        /* Layout */
+        section { padding: 96px; display: flex; justify-content: space-between; align-items: center; }
+        .gallery { margin-right: 32px; width: calc(100% - 260px - 48px); }
+    </style>
+</head>
+<body>
+    <header class="card">
+        <h1>Deadhead Print Lab</h1>
+        <p>Explore the handmade visual language of Grateful Dead concert culture.</p>
+    </header>
+    
+    <section>
+        <div class="gallery">
+            <!-- Poster Studies -->
+            <div class="card">
+                <h2>Poster Study 1</h2>
+                <img src="" alt="Poster Study" style="width: 100%; height: auto; object-fit: cover;">
+                <button onclick="toggleSeparations()">Switch Color Separation</button>
+                <button onclick="toggleRegistration()">Reveal Registration Marks</button>
+                <div class="process-drawer">
+                    <h3>Ink Choices</h3>
+                    <p>Sun-faded cream, midnight blue, acid red, marigold, and mint.</p>
+                </div>
+            </div>
+            <!-- More Poster Studies -->
+        </div>
+        
+        <aside>
+            <div class="card">
+                <h2>Process Drawer</h2>
+                <button onclick="toggleInk()">Ink Choices</button>
+                <button onclick="togglePaper()">Paper Type</button>
+                <button onclick="toggleHalftone()">Halftone Technique</button>
+                <button onclick="toggleLetterpress()">Letterpress Printing</button>
+            </div>
+        </aside>
+    </section>
+
+    <script>
+        function toggleSeparations() {
+            document.querySelectorAll('.card img').forEach(img => (img.src = img.dataset.originalSrc));
+        }
+        
+        function toggleRegistration() {
+            const marks = document.createElement('svg');
+            marks.setAttribute('width', '100%');
+            marks.setAttribute('height', '100%');
+            // Add registration mark SVG elements here
+            document.querySelector('.card').appendChild(marks);
+        }
+
+        window.onload = () => {
+            document.querySelectorAll('[onclick^="toggle"]').forEach(button => button.click());
+        }
+    </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/b05597bd9f5a/qwen3-14b.html b/data/artifacts/b05597bd9f5a/qwen3-14b.html
new file mode 100644
index 0000000..9471c39
--- /dev/null
+++ b/data/artifacts/b05597bd9f5a/qwen3-14b.html
@@ -0,0 +1,417 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Deadhead Print Lab</title>
+  <style>
+    :root {
+      --bg: #f7efe6;
+      --surface: #fff9f1;
+      --text: #3a2c22;
+      --muted: #a08c7a;
+      --accent: #c65f38;
+      --accent2: #e0a458;
+      --card-radius: 14px;
+      --spacing-4: 4px;
+      --spacing-8: 8px;
+      --spacing-12: 12px;
+      --spacing-16: 16px;
+      --spacing-24: 24px;
+      --spacing-32: 32px;
+      --spacing-48: 48px;
+      --spacing-64: 64px;
+      --spacing-96: 96px;
+      --card-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+      --hover-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
+      --glow: 0 0 24px var(--accent, #c65f38)35%;
+      --font-body: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+      --font-display: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      --caption: 12px;
+      --body: 16px;
+      --lead: 21px;
+      --h3: 28px;
+      --h2: 38px;
+      --h1: 50px;
+      --display: 67px;
+    }
+
+    html, body {
+      margin: 0;
+      padding: 0;
+      font-family: var(--font-body);
+      background: linear-gradient(145deg, #f7efe6, #e0a458, #c65f38);
+      background-size: 400% 400%;
+      animation: drift 18s infinite linear;
+      color: var(--text);
+      scroll-behavior: smooth;
+    }
+
+    @keyframes drift {
+      0% { background-position: 0% 50%; }
+      50% { background-position: 100% 50%; }
+      100% { background-position: 0% 50%; }
+    }
+
+    body {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      min-height: 100vh;
+      padding: var(--spacing-96) 0;
+    }
+
+    h1 {
+      font-family: var(--font-display);
+      font-size: var(--h1);
+      margin-bottom: var(--spacing-16);
+      color: var(--accent);
+      text-transform: uppercase;
+      letter-spacing: 0.15em;
+    }
+
+    .grid {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+      gap: var(--spacing-24);
+      width: 100%;
+      max-width: 1200px;
+    }
+
+    .card {
+      background: var(--surface);
+      border-radius: var(--card-radius);
+      box-shadow: var(--card-shadow);
+      overflow: hidden;
+      display: flex;
+      flex-direction: column;
+      transition: box-shadow 150ms ease;
+    }
+
+    .card:hover {
+      box-shadow: var(--hover-shadow);
+    }
+
+    .card img {
+      width: 100%;
+      height: 300px;
+      object-fit: cover;
+      filter: contrast(105%) brightness(110%);
+    }
+
+    .card-content {
+      padding: var(--spacing-16);
+      flex: 1;
+    }
+
+    .card-title {
+      font-family: var(--font-display);
+      font-size: var(--h2);
+      margin-bottom: var(--spacing-8);
+      color: var(--accent);
+      text-transform: uppercase;
+      letter-spacing: 0.15em;
+    }
+
+    .card-description {
+      font-size: var(--body);
+      margin-bottom: var(--spacing-16);
+      line-height: 1.6;
+      color: var(--muted);
+    }
+
+    .card-meta {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      font-size: var(--caption);
+      color: var(--text);
+    }
+
+    .process-drawer {
+      position: fixed;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background: rgba(0, 0, 0, 0.9);
+      z-index: 999;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      opacity: 0;
+      visibility: hidden;
+      transition: opacity 200ms, visibility 200ms;
+    }
+
+    .process-drawer.active {
+      opacity: 1;
+      visibility: visible;
+    }
+
+    .process-box {
+      background: var(--surface);
+      padding: var(--spacing-32);
+      border-radius: var(--card-radius);
+      max-width: 600px;
+      width: 90%;
+      box-shadow: var(--glow);
+      position: relative;
+      text-align: center;
+    }
+
+    .process-box h2 {
+      font-family: var(--font-display);
+      font-size: var(--h2);
+      color: var(--accent);
+      margin-bottom: var(--spacing-16);
+      text-transform: uppercase;
+      letter-spacing: 0.15em;
+    }
+
+    .process-box p {
+      font-size: var(--body);
+      color: var(--text);
+      margin-bottom: var(--spacing-16);
+    }
+
+    .lightbox {
+      position: fixed;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background: rgba(0, 0, 0, 0.95);
+      z-index: 1000;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      visibility: hidden;
+      opacity: 0;
+      transition: opacity 200ms ease;
+    }
+
+    .lightbox.active {
+      visibility: visible;
+      opacity: 1;
+    }
+
+    .lightbox img {
+      max-width: 90%;
+      max-height: 90%;
+      object-fit: contain;
+      box-shadow: var(--glow);
+    }
+
+    .lightbox-close {
+      position: absolute;
+      top: 20px;
+      right: 20px;
+      font-size: 24px;
+      color: var(--text);
+      cursor: pointer;
+      text-shadow: 0 0 5px rgba(0,0,0,0.4);
+    }
+
+    .lightbox-info {
+      position: absolute;
+      bottom: 20px;
+      left: 50%;
+      transform: translateX(-50%);
+      background: rgba(255, 255, 255, 0.1);
+      padding: var(--spacing-8) var(--spacing-16);
+      border-radius: var(--card-radius);
+      font-size: var(--body);
+      color: var(--text);
+      text-align: center;
+    }
+
+    .controls {
+      position: fixed;
+      bottom: var(--spacing-32);
+      left: 50%;
+      transform: translateX(-50%);
+      display: flex;
+      gap: var(--spacing-16);
+      z-index: 1000;
+    }
+
+    .controls button {
+      background: var(--accent);
+      color: var(--text);
+      border: none;
+      padding: var(--spacing-8) var(--spacing-16);
+      border-radius: var(--card-radius);
+      font-size: var(--body);
+      cursor: pointer;
+      transition: background 150ms;
+      text-transform: uppercase;
+      letter-spacing: 0.1em;
+    }
+
+    .controls button:hover {
+      background: var(--accent2);
+    }
+
+    .overlay {
+      position: fixed;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background: rgba(0, 0, 0, 0.3);
+      z-index: 998;
+      display: none;
+      justify-content: center;
+      align-items: center;
+    }
+
+    .overlay.active {
+      display: flex;
+    }
+
+    .overlay-text {
+      background: var(--surface);
+      padding: var(--spacing-16);
+      border-radius: var(--card-radius);
+      text-align: center;
+      box-shadow: var(--glow);
+    }
+
+    .overlay-text h3 {
+      font-family: var(--font-display);
+      font-size: var(--h3);
+      color: var(--accent);
+      margin-bottom: var(--spacing-8);
+      text-transform: uppercase;
+      letter-spacing: 0.1em;
+    }
+
+    .overlay-text p {
+      font-size: var(--body);
+      color: var(--text);
+    }
+
+    @media (max-width: 600px) {
+      .card img {
+        height: 240px;
+      }
+    }
+  </style>
+</head>
+<body>
+  <h1>Deadhead Print Lab</h1>
+  <div class="grid">
+    <div class="card" onclick="openLightbox('posters/1.jpg', 'Sunset Over the Dead', '1973, Golden Gate Park, San Francisco')"> 
+      <img src="posters/1.jpg" alt="Sunset Over the Dead" />
+      <div class="card-content">
+        <div class="card-title">Sunset Over the Dead</div>
+        <div class="card-description">A celestial landscape of golden light and dark storm clouds. Hand-etched halftone texture, sun-faded cream ink on uncoated paper. Overprint of marigold lightning.</div>
+        <div class="card-meta"><span>Ed 12/100</span><span>1973</span></div>
+      </div>
+    </div>
+    <div class="card" onclick="openLightbox('posters/2.jpg', 'Dancing Skele-Tones', '1975, Fillmore West, SF')"> 
+      <img src="posters/2.jpg" alt="Dancing Skele-Tones" />
+      <div class="card-content">
+        <div class="card-title">Dancing Skele-Tones</div>
+        <div class="card-description">Abstract skeletal figures in rhythm, inked with midnight blue and acid red. Letterpress typography in Didot, overprinted with mint halftone.</div>
+        <div class="card-meta"><span>Ed 14/100</span><span>1975</span></div>
+      </div>
+    </div>
+    <div class="card" onclick="openLightbox('posters/3.jpg', 'Roses in the Rain', '1977, Winterland, SF')"> 
+      <img src="posters/3.jpg" alt="Roses in the Rain" />
+      <div class="card-content">
+        <div class="card-title">Roses in the Rain</div>
+        <div class="card-description">Watercolor-style ink wash with halftone overlays. Midnight blue on rough paper with marigold screen-printed roses. Registration marks visible on back.</div>
+        <div class="card-meta"><span>Ed 9/100</span><span>1977</span></div>
+      </div>
+    </div>
+    <div class="card" onclick="openLightbox('posters/4.jpg', 'The Road Case', '1982, Oakland Coliseum')"> 
+      <img src="posters/4.jpg" alt="The Road Case" />
+      <div class="card-content">
+        <div class="card-title">The Road Case</div>
+        <div class="card-description">A collage of road cases, inked with acid red and mint. Letterpress in Bodoni, with halftone overlays of abstract road textures. Overprint of marigold ink.</div>
+        <div class="card-meta"><span>Ed 7/100</span><span>1982</span></div>
+      </div>
+    </div>
+    <div class="card" onclick="openLightbox('posters/5.jpg', 'Celestial Dead', '1989, Alpine Valley')"> 
+      <img src="posters/5.jpg" alt="Celestial Dead" />
+      <div class="card-content">
+        <div class="card-title">Celestial Dead</div>
+        <div class="card-description">Celestial motifs with halftone overlays, acid red and midnight blue. Letterpress in Playfair Display, overprinted with mint. Registration marks on reverse.</div>
+        <div class="card-meta"><span>Ed 5/100</span><span>1989</span></div>
+      </div>
+    </div>
+  </div>
+
+  <div class="controls">
+    <button onclick="toggleProcess()">Process</button>
+    <button onclick="toggleOverlay()">Curator Notes</button>
+    <button onclick="toggleLightbox()">Lightbox</button>
+  </div>
+
+  <div class="overlay" id="overlay">
+    <div class="overlay-text">
+      <h3>Curator Notes</h3>
+      <p>
+        These posters are imagined artifacts of the Grateful Dead's visual culture, crafted with an emphasis on texture, imperfection, and layered inks. Each piece explores the interplay between type, screen-printing, and halftone. Designed with a reverence for the handmade, the posters reflect the spirit of the era through abstract motifs rather than direct reproduction of logos. This collection is a tribute to the artistry of printmaking in the Deadhead community.
+      </p>
+    </div>
+  </div>
+
+  <div class="process-drawer" id="process-drawer">
+    <div class="process-box">
+      <h2>Process</h2>
+      <p>
+        <strong>Ink:</strong> Acid red, midnight blue, and mint are used for vibrant contrast and depth. Sun-faded cream ink is applied with a soft brush to mimic the passage of time.
+      </p>
+      <p>
+        <strong>Paper:</strong> Uncoated rough paper is used for a tactile finish and to allow for ink absorption and texture showing through.
+      </p>
+      <p>
+        <strong>Halftone:</strong> Hand-drawn halftone overlays are used to create depth and dimension. The halftone screen is adjusted for each color to match the ink's viscosity.
+      </p>
+      <p>
+        <strong>Letterpress:</strong> Typography is set in Didot and Bodoni, with each letter pressed in relief using a traditional letterpress machine. Overprints are used to create layered effects.
+      </p>
+      <p>
+        <strong>Registration Marks:</strong> Invisible on the front, these marks are used in the print studio to align the color separations precisely.
+      </p>
+    </div>
+  </div>
+
+  <div class="lightbox" id="lightbox">
+    <span class="lightbox-close" onclick="closeLightbox()">×</span>
+    <img src="" alt="Full View" id="lightbox-img" />
+    <div class="lightbox-info">
+      <h3 id="lightbox-title"></h3>
+      <p id="lightbox-meta"></p>
+    </div>
+  </div>
+
+  <script>
+    function openLightbox(image, title, meta) {
+      document.getElementById('lightbox-img').src = image;
+      document.getElementById('lightbox-title').textContent = title;
+      document.getElementById('lightbox-meta').textContent = meta;
+      document.getElementById('lightbox').classList.add('active');
+    }
+
+    function closeLightbox() {
+      document.getElementById('lightbox').classList.remove('active');
+    }
+
+    function toggleLightbox() {
+      document.getElementById('lightbox').classList.toggle('active');
+    }
+
+    function toggleProcess() {
+      document.getElementById('process-drawer').classList.toggle('active');
+    }
+
+    function toggleOverlay() {
+      document.getElementById('overlay').classList.toggle('active');
+    }
+  </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/f6e40f30be85/claude-code.html b/data/artifacts/f6e40f30be85/claude-code.html
new file mode 100644
index 0000000..c879d1f
--- /dev/null
+++ b/data/artifacts/f6e40f30be85/claude-code.html
@@ -0,0 +1,796 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Wall of Sound — An Immersive Room</title>
+<style>
+  :root{
+    --bg:#0d0d0f; --surface:#17171c; --surface-2:#1d1d24;
+    --text:#f5f2ea; --muted:#8a8578;
+    --gold:#c9a961; --bronze:#7d6a45;
+    --line:rgba(201,169,97,.18);
+    /* perspective-driven ambient accents (default: stage) */
+    --amb1:#c9a961; --amb2:#7d6a45; --amb-glow:rgba(201,169,97,.18);
+    --field:#c9a961;
+    --pad:clamp(20px,5vw,64px);
+    --ease:cubic-bezier(.22,1,.36,1);
+  }
+  *{box-sizing:border-box}
+  html{scroll-behavior:smooth}
+  body{
+    margin:0; background:var(--bg); color:var(--text);
+    font-family:-apple-system,'Segoe UI','Helvetica Neue',Arial,sans-serif;
+    font-size:16px; line-height:1.65; letter-spacing:.01em;
+    overflow-x:hidden;
+    -webkit-font-smoothing:antialiased;
+  }
+  h1,h2,h3,.display{font-family:'Didot','Bodoni MT','Playfair Display',Georgia,serif;font-weight:400}
+  ::selection{background:var(--gold);color:#0d0d0f}
+
+  /* ambient drifting backdrop */
+  .ambient{
+    position:fixed;inset:0;z-index:0;pointer-events:none;
+    background:
+      radial-gradient(60vw 60vw at 22% 18%, var(--amb-glow), transparent 60%),
+      radial-gradient(50vw 50vw at 82% 78%, rgba(125,106,69,.14), transparent 62%),
+      radial-gradient(40vw 40vw at 50% 50%, rgba(201,169,97,.05), transparent 70%);
+    transition:background 1.4s var(--ease);
+    animation:drift 18s ease-in-out infinite alternate;
+  }
+  @keyframes drift{
+    from{transform:translate3d(-1.5%,-1%,0) scale(1.02)}
+    to{transform:translate3d(1.5%,1.5%,0) scale(1.06)}
+  }
+  body.quiet .ambient{animation:none}
+
+  .wrap{position:relative;z-index:1;max-width:1200px;margin:0 auto;padding:0 var(--pad)}
+
+  /* ---- utility ---- */
+  .kicker{
+    font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
+    display:block;margin-bottom:12px;
+  }
+  .lead{font-size:clamp(17px,2.1vw,21px);color:var(--muted);max-width:62ch}
+  .rule{height:1px;background:var(--line);border:0;margin:0}
+
+  a.link{color:var(--gold);text-decoration:none;border-bottom:1px solid var(--line)}
+
+  /* entrance */
+  .fade{opacity:0;transform:translateY(28px)}
+  .fade.in{animation:fadeUp .7s var(--ease) both}
+  @keyframes fadeUp{from{opacity:0;transform:translateY(28px)}to{opacity:1;transform:none}}
+  body.quiet .fade{opacity:1!important;transform:none!important;animation:none!important}
+
+  /* ================= TOP BAR ================= */
+  header.bar{
+    position:sticky;top:0;z-index:40;
+    display:flex;align-items:center;justify-content:space-between;gap:16px;
+    padding:14px var(--pad);
+    background:rgba(13,13,15,.72);backdrop-filter:blur(14px);
+    border-bottom:1px solid var(--line);
+  }
+  .brand{display:flex;align-items:baseline;gap:12px;min-width:0}
+  .brand .mark{font-family:'Didot',Georgia,serif;font-size:20px;letter-spacing:.02em;white-space:nowrap}
+  .brand .sub{font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
+  .bar-actions{display:flex;gap:8px;align-items:center;flex-shrink:0}
+  .btn{
+    font:inherit;font-size:12px;letter-spacing:.12em;text-transform:uppercase;
+    color:var(--text);background:transparent;border:1px solid var(--line);
+    padding:9px 14px;border-radius:10px;cursor:pointer;
+    transition:all .2s var(--ease);white-space:nowrap;
+  }
+  .btn:hover,.btn:focus-visible{border-color:var(--gold);color:var(--gold);outline:none}
+  .btn[aria-pressed="true"]{background:var(--gold);color:#0d0d0f;border-color:var(--gold)}
+  :focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:6px}
+
+  /* ================= HERO / STAGE ================= */
+  .hero{padding:clamp(48px,9vw,96px) 0 40px;text-align:center}
+  .hero h1{
+    font-size:clamp(38px,8vw,67px);line-height:1.02;margin:0 auto 18px;
+    max-width:16ch;letter-spacing:.01em;
+  }
+  .hero h1 em{font-style:italic;color:var(--gold)}
+  .hero .lead{margin:0 auto 8px;text-align:center}
+
+  /* installation frame */
+  .installation{
+    margin:44px auto 0;max-width:920px;position:relative;
+    aspect-ratio:16/10;border:1px solid var(--line);border-radius:16px;
+    background:
+      radial-gradient(120% 120% at 50% 120%, rgba(201,169,97,.08), transparent 55%),
+      linear-gradient(180deg,#101014,#0a0a0c);
+    box-shadow:0 30px 90px rgba(0,0,0,.55), inset 0 1px 0 rgba(255,255,255,.03);
+    overflow:hidden;
+  }
+  .installation svg{position:absolute;inset:0;width:100%;height:100%}
+  .stage-label{
+    position:absolute;left:16px;bottom:14px;
+    font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted);
+    z-index:5;
+  }
+  .stage-label b{color:var(--gold);font-weight:400}
+
+  /* animated waveform + fields controlled by JS/CSS classes */
+  .field-ring{transition:opacity 1s var(--ease), stroke 1.2s var(--ease)}
+  .pulse{transform-origin:center;transform-box:fill-box}
+  body:not(.quiet) .pulse.a{animation:ripple 5.5s var(--ease) infinite}
+  body:not(.quiet) .pulse.b{animation:ripple 5.5s var(--ease) infinite .9s}
+  body:not(.quiet) .pulse.c{animation:ripple 5.5s var(--ease) infinite 1.8s}
+  body:not(.quiet) .pulse.d{animation:ripple 5.5s var(--ease) infinite 2.7s}
+  @keyframes ripple{
+    0%{opacity:.85;transform:scale(.28)}
+    80%{opacity:0;transform:scale(1.9)}
+    100%{opacity:0;transform:scale(1.9)}
+  }
+  .wave path{transition:opacity .6s var(--ease)}
+  body:not(.quiet).demo-on .wave path{animation:wavemove 3s linear infinite}
+  @keyframes wavemove{to{transform:translateX(-160px)}}
+  .signal{stroke-dasharray:6 10;transition:stroke 1s var(--ease)}
+  body:not(.quiet).demo-on .signal{animation:dash 2.2s linear infinite}
+  @keyframes dash{to{stroke-dashoffset:-160}}
+
+  .speaker-cell{transition:fill 1.1s var(--ease), opacity 1.1s var(--ease)}
+  .listener{transition:transform 1.1s var(--ease), opacity 1s var(--ease)}
+  body:not(.quiet).demo-on .lit-meter rect{animation:meter 1.4s var(--ease) infinite alternate}
+  @keyframes meter{from{transform:scaleY(.35)}to{transform:scaleY(1)}}
+  .lit-meter rect{transform-origin:bottom;transform-box:fill-box}
+
+  /* ================= PERSPECTIVE SWITCH ================= */
+  section{padding:clamp(56px,10vw,96px) 0;position:relative}
+  section > .wrap { position:relative }
+  h2.sec{font-size:clamp(28px,5vw,38px);margin:0 0 8px;letter-spacing:.01em}
+
+  .persp-tabs{display:flex;flex-wrap:wrap;gap:10px;margin:26px 0 34px}
+  .tab{
+    flex:1 1 180px;text-align:left;
+    background:var(--surface);border:1px solid var(--line);border-radius:14px;
+    padding:16px 18px;cursor:pointer;transition:all .25s var(--ease);
+    color:var(--text);font:inherit;position:relative;overflow:hidden;
+  }
+  .tab .n{font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--muted)}
+  .tab .t{font-family:'Didot',Georgia,serif;font-size:22px;margin-top:6px}
+  .tab::after{content:"";position:absolute;left:0;bottom:0;height:3px;width:0;background:var(--field);transition:width .35s var(--ease)}
+  .tab:hover{transform:translateY(-3px);box-shadow:0 16px 48px rgba(0,0,0,.28)}
+  .tab[aria-selected="true"]{border-color:var(--field);background:var(--surface-2)}
+  .tab[aria-selected="true"]::after{width:100%}
+  .tab[aria-selected="true"] .t{color:var(--field)}
+
+  .persp-body{
+    display:grid;grid-template-columns:1.1fr 1fr;gap:clamp(24px,4vw,48px);align-items:center;
+  }
+  .diagram{
+    border:1px solid var(--line);border-radius:16px;overflow:hidden;position:relative;
+    aspect-ratio:4/3;background:linear-gradient(180deg,#101014,#0b0b0e);
+    box-shadow:0 20px 60px rgba(0,0,0,.4);
+  }
+  .diagram svg{width:100%;height:100%;display:block}
+  .persp-text .kicker{color:var(--field)}
+  .persp-text h3{font-size:clamp(24px,4vw,32px);margin:0 0 14px}
+  .persp-text p{color:var(--muted);margin:0 0 18px}
+  .meta-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:8px}
+  .meta{border-top:1px solid var(--line);padding-top:10px}
+  .meta .k{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
+  .meta .v{font-family:'Didot',Georgia,serif;font-size:19px;color:var(--text);margin-top:2px}
+
+  /* ================= EXPLODED VIEW ================= */
+  .exploded-stage{
+    border:1px solid var(--line);border-radius:16px;overflow:hidden;
+    background:linear-gradient(180deg,#101014,#0a0a0c);position:relative;
+    box-shadow:0 24px 70px rgba(0,0,0,.45);
+  }
+  .exploded-stage svg{width:100%;height:auto;display:block}
+  .layer{transition:transform .8s var(--ease), opacity .6s var(--ease)}
+  .exploded .layer.l1{transform:translateY(-46px)}
+  .exploded .layer.l2{transform:translateY(-16px)}
+  .exploded .layer.l3{transform:translateY(16px)}
+  .exploded .layer.l4{transform:translateY(46px)}
+  .callout{opacity:0;transition:opacity .5s var(--ease) .2s}
+  .exploded .callout{opacity:1}
+
+  /* ================= CARDS GRID ================= */
+  .grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:24px;margin-top:36px}
+  .card{
+    background:var(--surface);border:1px solid var(--line);border-radius:14px;
+    padding:24px;transition:transform .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease);
+    position:relative;
+  }
+  .card:hover{transform:translateY(-4px);box-shadow:0 16px 48px rgba(0,0,0,.28);border-color:var(--gold)}
+  .card .spec{font-size:12px;letter-spacing:.15em;text-transform:uppercase;color:var(--gold);margin-bottom:6px}
+  .card h3{font-size:23px;margin:0 0 10px}
+  .card p{color:var(--muted);font-size:15px;margin:0 0 14px}
+  .card .stats{display:flex;flex-wrap:wrap;gap:8px}
+  .chip{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);border:1px solid var(--line);border-radius:20px;padding:5px 11px}
+  .card-icon{width:44px;height:44px;margin-bottom:16px;color:var(--gold)}
+
+  /* history — timeline */
+  .timeline{margin-top:36px;border-left:1px solid var(--line);padding-left:28px;display:grid;gap:34px}
+  .tl{position:relative}
+  .tl::before{content:"";position:absolute;left:-34px;top:6px;width:11px;height:11px;border-radius:50%;background:var(--gold);box-shadow:0 0 0 5px rgba(201,169,97,.12)}
+  .tl .yr{font-family:'Didot',Georgia,serif;font-size:26px;color:var(--gold)}
+  .tl h3{font-size:20px;margin:2px 0 8px}
+  .tl p{color:var(--muted);margin:0;max-width:60ch}
+
+  /* glossary */
+  details.gl{
+    border-bottom:1px solid var(--line);padding:4px 0;
+  }
+  details.gl summary{
+    list-style:none;cursor:pointer;padding:18px 4px;display:flex;justify-content:space-between;align-items:baseline;gap:16px;
+    transition:color .2s var(--ease);
+  }
+  details.gl summary::-webkit-details-marker{display:none}
+  details.gl summary .term{font-family:'Didot',Georgia,serif;font-size:22px}
+  details.gl summary .pron{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)}
+  details.gl[open] summary .term{color:var(--gold)}
+  details.gl .def{padding:0 4px 20px;color:var(--muted);max-width:70ch;animation:fadeUp .4s var(--ease) both}
+  .plus{color:var(--gold);font-size:20px;transition:transform .3s var(--ease)}
+  details.gl[open] .plus{transform:rotate(45deg)}
+
+  footer{padding:64px var(--pad) 80px;border-top:1px solid var(--line);text-align:center;position:relative;z-index:1}
+  footer .disc{max-width:64ch;margin:16px auto 0;font-size:13px;color:var(--muted)}
+
+  .demo-note{
+    display:inline-flex;align-items:center;gap:10px;margin-top:22px;
+    font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);
+    border:1px solid var(--line);border-radius:20px;padding:8px 16px;
+  }
+  .dot{width:8px;height:8px;border-radius:50%;background:var(--muted);transition:background .3s}
+  .demo-on .dot{background:var(--gold);box-shadow:0 0 12px var(--gold)}
+
+  .quiet-flag{
+    position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(140%);
+    background:var(--surface-2);border:1px solid var(--gold);color:var(--gold);
+    padding:10px 20px;border-radius:24px;z-index:60;
+    font-size:12px;letter-spacing:.14em;text-transform:uppercase;
+    transition:transform .5s var(--ease);box-shadow:0 10px 40px rgba(0,0,0,.5);
+  }
+  body.quiet .quiet-flag{transform:translateX(-50%) translateY(0)}
+
+  .kbd{font-family:ui-monospace,Menlo,monospace;font-size:12px;background:var(--surface-2);border:1px solid var(--line);border-bottom-width:2px;border-radius:6px;padding:2px 7px;color:var(--text)}
+
+  @media(max-width:760px){
+    .persp-body{grid-template-columns:1fr}
+    .brand .sub{display:none}
+    .meta-grid{grid-template-columns:1fr}
+  }
+  @media(prefers-reduced-motion:reduce){
+    *{animation:none!important;scroll-behavior:auto}
+    .fade{opacity:1;transform:none}
+  }
+</style>
+</head>
+<body>
+<div class="ambient" aria-hidden="true"></div>
+
+<header class="bar">
+  <div class="brand">
+    <span class="mark">Wall of Sound</span>
+    <span class="sub">An Immersive Room · Gallery Installation</span>
+  </div>
+  <div class="bar-actions">
+    <button class="btn" id="demoBtn" aria-pressed="false" title="Toggle the honest visual simulation (no audio)">◈ Demo Signal</button>
+    <button class="btn" id="quietBtn" aria-pressed="false" title="Stop all motion; preserve the design">Quiet Mode</button>
+  </div>
+</header>
+
+<main>
+  <!-- HERO -->
+  <section class="hero" id="top">
+    <div class="wrap">
+      <span class="kicker fade">A Virtual Installation · Sound as Architecture</span>
+      <h1 class="fade">Standing Inside the <em>Wall of Sound</em></h1>
+      <p class="lead fade">In 1974 a band tried to remove distortion from live music by building a speaker system that was, in effect, a building. This room is a study of that ambition — a place to move between vantage points and watch how a single signal reshapes the air around you.</p>
+
+      <div class="installation fade" role="img" aria-label="Abstract monumental speaker array with concentric sound fields and a moving waveform.">
+        <svg viewBox="0 0 920 575" preserveAspectRatio="xMidYMid slice" id="heroSvg">
+          <defs>
+            <linearGradient id="col" x1="0" y1="0" x2="0" y2="1">
+              <stop offset="0" stop-color="#22222a"/><stop offset="1" stop-color="#0c0c10"/>
+            </linearGradient>
+            <radialGradient id="pool" cx="50%" cy="82%" r="60%">
+              <stop offset="0" stop-color="var(--amb1)" stop-opacity=".28"/>
+              <stop offset="1" stop-color="var(--amb1)" stop-opacity="0"/>
+            </radialGradient>
+            <filter id="soft"><feGaussianBlur stdDeviation="2.2"/></filter>
+          </defs>
+
+          <!-- pool of light -->
+          <rect x="0" y="0" width="920" height="575" fill="url(#pool)"/>
+
+          <!-- concentric sound fields -->
+          <g fill="none" stroke="var(--field)" stroke-opacity=".22">
+            <circle class="field-ring" cx="460" cy="250" r="120"/>
+            <circle class="field-ring" cx="460" cy="250" r="185"/>
+            <circle class="field-ring" cx="460" cy="250" r="255"/>
+            <circle class="field-ring" cx="460" cy="250" r="330"/>
+          </g>
+          <!-- animated pulses -->
+          <g fill="none" stroke="var(--field)" stroke-width="1.4" stroke-opacity=".5">
+            <circle class="pulse a" cx="460" cy="250" r="120"/>
+            <circle class="pulse b" cx="460" cy="250" r="120"/>
+            <circle class="pulse c" cx="460" cy="250" r="120"/>
+            <circle class="pulse d" cx="460" cy="250" r="120"/>
+          </g>
+
+          <!-- THE ARRAY : abstract towers of speaker cells -->
+          <g id="array">
+            <!-- back scaffold -->
+            <g stroke="#3a3527" stroke-width="1.5" stroke-opacity=".7">
+              <line x1="300" y1="70" x2="300" y2="470"/><line x1="620" y1="70" x2="620" y2="470"/>
+              <line x1="300" y1="70" x2="620" y2="70"/><line x1="300" y1="470" x2="620" y2="470"/>
+              <line x1="360" y1="70" x2="360" y2="470"/><line x1="460" y1="70" x2="460" y2="470"/><line x1="560" y1="70" x2="560" y2="470"/>
+            </g>
+          </g>
+
+          <!-- moving waveform band -->
+          <g class="wave" opacity=".9">
+            <path d="M-160,250 q40,-40 80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0 t80,0"
+                  fill="none" stroke="var(--field)" stroke-width="1.6" stroke-opacity=".5"/>
+          </g>
+
+          <!-- signal path from board to array -->
+          <path class="signal" d="M120,520 C260,520 300,360 460,320" fill="none" stroke="var(--amb1)" stroke-width="1.6" stroke-opacity=".8"/>
+          <circle cx="120" cy="520" r="5" fill="var(--amb1)"/>
+
+          <!-- level meter -->
+          <g class="lit-meter" transform="translate(720,360)" opacity=".85">
+            <rect x="0" width="8" height="70" fill="var(--field)" fill-opacity=".7"/>
+            <rect x="14" width="8" height="70" fill="var(--field)" fill-opacity=".55"/>
+            <rect x="28" width="8" height="70" fill="var(--field)" fill-opacity=".7"/>
+            <rect x="42" width="8" height="70" fill="var(--field)" fill-opacity=".5"/>
+          </g>
+        </svg>
+        <div class="stage-label">Perspective: <b id="stageName">Front Rail</b> · <span id="demoState">signal idle</span></div>
+      </div>
+
+      <div class="demo-note"><span class="dot"></span><span id="noteTxt">Visual simulation — this installation makes no sound. Toggle “Demo Signal” to animate the modeled signal path.</span></div>
+    </div>
+  </section>
+
+  <hr class="rule"/>
+
+  <!-- PERSPECTIVES -->
+  <section id="perspectives">
+    <div class="wrap">
+      <span class="kicker fade" style="color:var(--field)">Four Listening Perspectives</span>
+      <h2 class="sec fade">Where you stand is what you hear</h2>
+      <p class="lead fade">A wall of sound is not one experience but a gradient of them. Choose a vantage point — the diagram, the ambient light, the interpretive text, and the modeled signal path all change with you.</p>
+
+      <div class="persp-tabs fade" role="tablist" aria-label="Listening perspectives">
+        <button class="tab" role="tab" aria-selected="false" data-p="stage" id="tab-stage">
+          <span class="n">01 · On</span><span class="t">Stage</span>
+        </button>
+        <button class="tab" role="tab" aria-selected="true" data-p="rail" id="tab-rail">
+          <span class="n">02 · The</span><span class="t">Front Rail</span>
+        </button>
+        <button class="tab" role="tab" aria-selected="false" data-p="board" id="tab-board">
+          <span class="n">03 · At the</span><span class="t">Soundboard</span>
+        </button>
+        <button class="tab" role="tab" aria-selected="false" data-p="hill" id="tab-hill">
+          <span class="n">04 · The</span><span class="t">Hillside</span>
+        </button>
+      </div>
+
+      <div class="persp-body">
+        <div class="diagram fade" id="diagram" role="img" aria-live="polite" aria-label="Spatial diagram of the chosen perspective.">
+          <svg viewBox="0 0 480 360" id="planSvg">
+            <defs>
+              <radialGradient id="d-pool" cx="50%" cy="30%" r="70%">
+                <stop offset="0" stop-color="var(--field)" stop-opacity=".22"/>
+                <stop offset="1" stop-color="var(--field)" stop-opacity="0"/>
+              </radialGradient>
+            </defs>
+            <rect x="0" y="0" width="480" height="360" fill="url(#d-pool)"/>
+            <!-- the wall (fixed) -->
+            <g id="wall">
+              <rect x="150" y="26" width="180" height="40" rx="4" fill="none" stroke="var(--field)" stroke-opacity=".8"/>
+              <g stroke="var(--field)" stroke-opacity=".4">
+                <line x1="180" y1="26" x2="180" y2="66"/><line x1="210" y1="26" x2="210" y2="66"/>
+                <line x1="240" y1="26" x2="240" y2="66"/><line x1="270" y1="26" x2="270" y2="66"/><line x1="300" y1="26" x2="300" y2="66"/>
+              </g>
+              <text x="240" y="18" text-anchor="middle" fill="var(--muted)" font-size="10" letter-spacing="2">THE ARRAY</text>
+            </g>
+            <!-- radiating field -->
+            <g id="dfield" fill="none" stroke="var(--field)" stroke-opacity=".3">
+              <path d="M240,66 Q140,150 120,300"/>
+              <path d="M240,66 Q240,180 240,320"/>
+              <path d="M240,66 Q340,150 360,300"/>
+            </g>
+            <!-- listener marker (moves per perspective) -->
+            <g class="listener" id="listener">
+              <circle cx="240" cy="250" r="9" fill="var(--field)"/>
+              <circle cx="240" cy="250" r="18" fill="none" stroke="var(--field)" stroke-opacity=".5"/>
+              <text x="240" y="285" text-anchor="middle" fill="var(--text)" font-size="10" letter-spacing="2" id="youTxt">YOU</text>
+            </g>
+            <!-- signal path (animated when demo on) -->
+            <path class="signal" id="dsignal" d="M240,320 C240,200 240,140 240,66" fill="none" stroke="var(--amb1)" stroke-width="1.4"/>
+          </svg>
+        </div>
+
+        <div class="persp-text fade">
+          <span class="kicker" id="pKicker">Perspective 02</span>
+          <h3 id="pTitle">The Front Rail</h3>
+          <p id="pBody"></p>
+          <div class="meta-grid">
+            <div class="meta"><div class="k">Spatial Character</div><div class="v" id="mChar"></div></div>
+            <div class="meta"><div class="k">Ambient Field</div><div class="v" id="mColor"></div></div>
+            <div class="meta"><div class="k">Distance to Array</div><div class="v" id="mDist"></div></div>
+            <div class="meta"><div class="k">Perceived Image</div><div class="v" id="mImage"></div></div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </section>
+
+  <hr class="rule"/>
+
+  <!-- EXPLODED VIEW -->
+  <section id="exploded">
+    <div class="wrap">
+      <span class="kicker fade">Technical View · 1970s Engineering Drawing</span>
+      <h2 class="sec fade">The array, taken apart</h2>
+      <p class="lead fade">A monumental column separated into its functional strata. Toggle the exploded view to see how frequency was divided across dedicated banks — the design principle that let each driver do only one job.</p>
+      <p class="fade" style="margin:22px 0"><button class="btn" id="explodeBtn" aria-pressed="false">⤢ Explode the Column</button></p>
+
+      <div class="exploded-stage fade" id="explodeStage">
+        <svg viewBox="0 0 900 460" role="img" aria-label="Exploded technical diagram of the speaker column, four layers.">
+          <defs>
+            <pattern id="grid" width="26" height="26" patternUnits="userSpaceOnUse">
+              <path d="M26 0H0V26" fill="none" stroke="#26221a" stroke-width=".6"/>
+            </pattern>
+          </defs>
+          <rect x="0" y="0" width="900" height="460" fill="url(#grid)"/>
+          <!-- center axis -->
+          <line x1="450" y1="20" x2="450" y2="440" stroke="var(--bronze)" stroke-dasharray="3 6" stroke-opacity=".5"/>
+
+          <!-- Layer 4: sub-bass base -->
+          <g class="layer l4">
+            <rect x="330" y="330" width="240" height="70" rx="5" fill="#15150f" stroke="var(--gold)" stroke-opacity=".7"/>
+            <circle cx="390" cy="365" r="22" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <circle cx="450" cy="365" r="22" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <circle cx="510" cy="365" r="22" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <g class="callout"><line x1="570" y1="365" x2="700" y2="365" stroke="var(--muted)"/><text x="706" y="362" fill="var(--muted)" font-size="12">Sub-bass bank · below 100 Hz</text><text x="706" y="378" fill="var(--muted)" font-size="10" letter-spacing="1">STRAIGHT-LINE, NO CROSSOVER</text></g>
+          </g>
+          <!-- Layer 3: low-mid -->
+          <g class="layer l3">
+            <rect x="355" y="250" width="190" height="66" rx="5" fill="#161610" stroke="var(--gold)" stroke-opacity=".7"/>
+            <circle cx="410" cy="283" r="18" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <circle cx="450" cy="283" r="18" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <circle cx="490" cy="283" r="18" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <g class="callout"><line x1="545" y1="283" x2="700" y2="283" stroke="var(--muted)"/><text x="706" y="280" fill="var(--muted)" font-size="12">Low-mid drivers · 100–400 Hz</text></g>
+          </g>
+          <!-- Layer 2: mid -->
+          <g class="layer l2">
+            <rect x="375" y="180" width="150" height="56" rx="5" fill="#17170f" stroke="var(--gold)" stroke-opacity=".7"/>
+            <rect x="395" y="196" width="26" height="26" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <rect x="437" y="196" width="26" height="26" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <rect x="479" y="196" width="26" height="26" fill="none" stroke="var(--gold)" stroke-opacity=".7"/>
+            <g class="callout"><line x1="375" y1="208" x2="200" y2="208" stroke="var(--muted)"/><text x="196" y="205" text-anchor="end" fill="var(--muted)" font-size="12">Midrange cluster · 400 Hz–4 kHz</text></g>
+          </g>
+          <!-- Layer 1: tweeter crown -->
+          <g class="layer l1">
+            <rect x="398" y="120" width="104" height="44" rx="5" fill="#18180f" stroke="var(--gold)" stroke-opacity=".8"/>
+            <polygon points="420,142 434,132 434,152" fill="none" stroke="var(--gold)" stroke-opacity=".8"/>
+            <polygon points="452,142 466,132 466,152" fill="none" stroke="var(--gold)" stroke-opacity=".8"/>
+            <g class="callout"><line x1="398" y1="142" x2="200" y2="142" stroke="var(--muted)"/><text x="196" y="139" text-anchor="end" fill="var(--muted)" font-size="12">Tweeter crown · above 4 kHz</text></g>
+          </g>
+
+          <text x="450" y="440" text-anchor="middle" fill="var(--muted)" font-size="10" letter-spacing="3">FIG. 1 — VERTICAL DRIVER STRATIFICATION · NOT TO SCALE</text>
+        </svg>
+      </div>
+    </div>
+  </section>
+
+  <hr class="rule"/>
+
+  <!-- HISTORY -->
+  <section id="history">
+    <div class="wrap">
+      <span class="kicker fade">A Concise History</span>
+      <h2 class="sec fade">The most ambitious PA ever built</h2>
+      <p class="lead fade">Between 1973 and 1974 a touring band and its audio engineers pursued a radical idea: instead of amplifying a signal and pointing it at a crowd, build a system so transparent that the amplifier disappears and only the instrument remains.</p>
+
+      <div class="timeline">
+        <div class="tl fade"><div class="yr">1965–72</div><h3>The distortion problem</h3><p>Early rock PA systems muddied everything — vocals fought guitars through the same overtaxed columns, and musicians on stage couldn't hear themselves clearly. The dream took shape: a system with no compromise between fidelity and volume.</p></div>
+        <div class="tl fade"><div class="yr">1973</div><h3>One driver, one job</h3><p>Engineers split the signal so each range of frequencies had its own dedicated bank of speakers. Instruments were kept on separate channels rather than mixed into a common muddy bus, letting each voice radiate cleanly from its own column.</p></div>
+        <div class="tl fade"><div class="yr">1974</div><h3>The wall stands</h3><p>At full height the system rose behind the musicians as a towering array of hundreds of drivers — a monument of speaker cabinets that doubled as the band's own monitor. It projected startlingly clear sound across great distances, coherent even a quarter-mile away.</p></div>
+        <div class="tl fade"><div class="yr">1974 →</div><h3>Beautiful and impossible</h3><p>It demanded enormous power, two full crews, and days to assemble. Retired within a year, it remains a landmark in the history of live audio — proof that a crowd could share not just a concert but a single, unified field of sound.</p></div>
+      </div>
+    </div>
+  </section>
+
+  <hr class="rule"/>
+
+  <!-- EQUIPMENT -->
+  <section id="equipment">
+    <div class="wrap">
+      <span class="kicker fade">Annotated Equipment</span>
+      <h2 class="sec fade">What the room is made of</h2>
+      <p class="lead fade">The installation abstracts real components into sculptural forms. Each card annotates the engineering intent behind a part of the array.</p>
+
+      <div class="grid">
+        <article class="card fade">
+          <svg class="card-icon" viewBox="0 0 44 44" fill="none" stroke="currentColor" stroke-width="1.4"><rect x="6" y="4" width="32" height="36" rx="3"/><circle cx="22" cy="16" r="7"/><circle cx="22" cy="31" r="4"/></svg>
+          <div class="spec">Component 01</div>
+          <h3>Driver Column</h3>
+          <p>A vertical stack of matched loudspeakers, each cell reproducing only a narrow band of frequencies so it never has to compromise. Stacked, they form the “wall.”</p>
+          <div class="stats"><span class="chip">Full-range</span><span class="chip">Line-source</span><span class="chip">Modular</span></div>
+        </article>
+
+        <article class="card fade">
+          <svg class="card-icon" viewBox="0 0 44 44" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M4 22h8l4-12 6 24 5-16 3 8h10"/></svg>
+          <div class="spec">Component 02</div>
+          <h3>Active Crossover</h3>
+          <p>Divides the incoming signal into frequency bands before amplification, sending highs, mids and lows to their own dedicated banks. The key to a clean, un-muddied field.</p>
+          <div class="stats"><span class="chip">4-way split</span><span class="chip">Pre-amp</span><span class="chip">Phase-aligned</span></div>
+        </article>
+
+        <article class="card fade">
+          <svg class="card-icon" viewBox="0 0 44 44" fill="none" stroke="currentColor" stroke-width="1.4"><rect x="5" y="10" width="34" height="24" rx="3"/><circle cx="14" cy="22" r="4"/><circle cx="26" cy="22" r="4"/><path d="M33 17v10"/></svg>
+          <div class="spec">Component 03</div>
+          <h3>Power Amplifiers</h3>
+          <p>Rows of amplifiers deliver the immense, clean headroom the array requires. Generous power reserves keep transients sharp instead of clipping into distortion.</p>
+          <div class="stats"><span class="chip">High headroom</span><span class="chip">Low noise</span><span class="chip">Redundant</span></div>
+        </article>
+
+        <article class="card fade">
+          <svg class="card-icon" viewBox="0 0 44 44" fill="none" stroke="currentColor" stroke-width="1.4"><rect x="6" y="6" width="32" height="32" rx="3"/><path d="M12 14h20M12 22h20M12 30h20"/><circle cx="16" cy="14" r="1.6" fill="currentColor"/><circle cx="24" cy="22" r="1.6" fill="currentColor"/><circle cx="20" cy="30" r="1.6" fill="currentColor"/></svg>
+          <div class="spec">Component 04</div>
+          <h3>Mixing Console</h3>
+          <p>The soundboard, positioned out in the audience, where the engineer balances each instrument's channel. Every source keeps its own path to its own speakers.</p>
+          <div class="stats"><span class="chip">Multi-channel</span><span class="chip">Front-of-house</span><span class="chip">Per-source</span></div>
+        </article>
+
+        <article class="card fade">
+          <svg class="card-icon" viewBox="0 0 44 44" fill="none" stroke="currentColor" stroke-width="1.4"><path d="M22 6v32M10 14v16M34 14v16M4 20v8M40 20v8"/></svg>
+          <div class="spec">Component 05</div>
+          <h3>Differential Mic Rig</h3>
+          <p>Paired microphones cancel a vocalist's own monitor bleed, so the singer can stand directly in front of the wall without a feedback howl — letting the array serve as its own monitor.</p>
+          <div class="stats"><span class="chip">Noise-cancelling</span><span class="chip">On-axis</span><span class="chip">Feedback-safe</span></div>
+        </article>
+
+        <article class="card fade">
+          <svg class="card-icon" viewBox="0 0 44 44" fill="none" stroke="currentColor" stroke-width="1.4"><rect x="8" y="8" width="28" height="28"/><path d="M8 8l28 28M36 8L8 36"/></svg>
+          <div class="spec">Component 06</div>
+          <h3>Scaffold & Rigging</h3>
+          <p>The structural steel that holds tons of cabinetry safely upright. Assembling and striking the tower took a dedicated crew and the better part of a day at each stop.</p>
+          <div class="stats"><span class="chip">Load-rated</span><span class="chip">Tour-portable</span><span class="chip">Two crews</span></div>
+        </article>
+      </div>
+    </div>
+  </section>
+
+  <hr class="rule"/>
+
+  <!-- GLOSSARY -->
+  <section id="glossary">
+    <div class="wrap">
+      <span class="kicker fade">Acoustics Glossary</span>
+      <h2 class="sec fade">A short lexicon of the field</h2>
+      <p class="lead fade">The vocabulary a listener needs to read this room. Open a term to expand its definition.</p>
+
+      <div class="fade" style="margin-top:30px">
+        <details class="gl"><summary><span><span class="term">Line Source</span> <span class="pron"> · ˈlīn sȯrs</span></span><span class="plus">+</span></summary><div class="def">A tall vertical column of drivers that behaves as a single continuous emitter. Its sound spreads cylindrically rather than spherically, so level falls off far more slowly with distance — the physical reason a wall of sound stays coherent across a large field.</div></details>
+        <details class="gl"><summary><span><span class="term">Crossover</span> <span class="pron"> · ˈkrȯs-ˌō-vər</span></span><span class="plus">+</span></summary><div class="def">The circuit that splits a full-range signal into frequency bands and routes each to speakers built for it. An <em>active</em> crossover does this before amplification, giving each band its own clean amplifier and eliminating the interference that muddies a shared driver.</div></details>
+        <details class="gl"><summary><span><span class="term">Headroom</span> <span class="pron"> · ˈhed-ˌrüm</span></span><span class="plus">+</span></summary><div class="def">The margin between the average signal level and the point of distortion. Abundant headroom lets sudden transients — a drum hit, a plucked string — reproduce cleanly instead of clipping, which is why the system carried far more power than its average output required.</div></details>
+        <details class="gl"><summary><span><span class="term">Phase Coherence</span> <span class="pron"> · ˈfāz kō-ˈhir-əns</span></span><span class="plus">+</span></summary><div class="def">When multiple drivers radiate the same waveform in step, their outputs reinforce rather than cancel. Aligning phase across hundreds of speakers is what turns a crowd of cabinets into one unified sound field instead of a smear of echoes.</div></details>
+        <details class="gl"><summary><span><span class="term">Standing Wave</span> <span class="pron"> · ˈstan-diŋ ˈwāv</span></span><span class="plus">+</span></summary><div class="def">A stationary pattern of loud and quiet zones formed when reflected sound overlaps the source. Large indoor systems fight standing waves with directivity and placement; outdoors, the open air lets the field radiate freely.</div></details>
+        <details class="gl"><summary><span><span class="term">Directivity</span> <span class="pron"> · də-ˌrek-ˈti-və-tē</span></span><span class="plus">+</span></summary><div class="def">How tightly a source focuses its energy in a given direction. High directivity concentrates sound toward the audience and away from reflective surfaces, improving clarity and reducing the feedback that plagues open-stage vocals.</div></details>
+        <details class="gl"><summary><span><span class="term">Transient</span> <span class="pron"> · ˈtran(t)-sh(ē-)ənt</span></span><span class="plus">+</span></summary><div class="def">The brief, sharp attack at the onset of a sound — the leading edge that carries much of its perceived realism. Preserving transients requires fast, un-clipped reproduction, one of the array's central design goals.</div></details>
+      </div>
+    </div>
+  </section>
+</main>
+
+<footer>
+  <div class="wrap">
+    <span class="kicker">Wall of Sound · An Immersive Room</span>
+    <p style="font-family:'Didot',Georgia,serif;font-size:clamp(22px,4vw,30px);margin:14px 0 0">“Not amplification — architecture.”</p>
+    <p class="disc"><strong style="color:var(--gold);font-weight:400">On honesty:</strong> This is a silent visual installation. It plays no audio and simulates none. The “Demo Signal” control animates a <em>modeled</em> signal path — an illustration of how the system distributed sound — and produces no sound whatsoever. All motion can be stopped with Quiet Mode without losing any of the design.</p>
+    <p class="disc" style="margin-top:18px">Keyboard: <span class="kbd">1</span>–<span class="kbd">4</span> switch perspectives · <span class="kbd">D</span> demo signal · <span class="kbd">Q</span> quiet mode · <span class="kbd">E</span> explode · <span class="kbd">← →</span> cycle perspective · <span class="kbd">Tab</span> to traverse controls.</p>
+  </div>
+</footer>
+
+<div class="quiet-flag" role="status" aria-live="polite">Quiet Mode · Motion Stilled</div>
+
+<script>
+(function(){
+  "use strict";
+  var body = document.body;
+
+  /* ---------- perspective data ---------- */
+  var P = {
+    stage: {
+      idx:"01", name:"On Stage", label:"On Stage",
+      body:"You stand where the musicians stood — with the wall directly behind you. Here the array is a monitor: your own voice returns to you clean and immediate, and the field radiates outward past your shoulders into the dark. The sensation is of being inside the source, not in front of it.",
+      char:"Enveloping", color:"Amber Core", dist:"0 m · at the array", image:"Behind & around",
+      amb1:"#c9a961", amb2:"#7d6a45", field:"#d8b869",
+      listenY:76, listenX:240, you:"MUSICIAN", signal:"M240,300 C240,180 240,120 240,66"
+    },
+    rail: {
+      idx:"02", name:"The Front Rail", label:"Front Rail",
+      body:"Pressed against the barrier, you are inside the near field. Individual driver columns are still resolvable — you can almost point to where each instrument lives on the wall. The image is enormous and physical, the transients arriving as pressure you feel before you name it.",
+      char:"Immediate · Physical", color:"Warm Gold", dist:"6 m · near field", image:"Wall-wide, resolvable",
+      amb1:"#c9a961", amb2:"#8a6f3a", field:"#c9a961",
+      listenY:150, listenX:240, you:"YOU", signal:"M240,320 C240,220 240,150 240,66"
+    },
+    board: {
+      idx:"03", name:"At the Soundboard", label:"Soundboard",
+      body:"Out in the crowd at front-of-house, you hear the mix as the engineer balances it. The columns have merged into a single coherent panorama; instruments occupy stable positions across a wide, even stage. This is the sweet spot the whole system was tuned to serve.",
+      char:"Balanced · Coherent", color:"Bronze Neutral", dist:"30 m · far field", image:"Unified panorama",
+      amb1:"#b79a5e", amb2:"#6f5d3c", field:"#a98f57",
+      listenY:250, listenX:240, you:"ENGINEER", signal:"M240,340 C240,240 240,150 240,66"
+    },
+    hill: {
+      idx:"04", name:"The Hillside", label:"Hillside",
+      body:"Far back on the grass, a quarter-mile from the array, the wall proves its purpose. Level has barely fallen; clarity survives the distance where an ordinary system would have collapsed into mush. The field is now a shared atmosphere binding thousands of listeners into one audience.",
+      char:"Vast · Communal", color:"Cool Dusk", dist:"400 m · distant field", image:"Atmospheric, shared",
+      amb1:"#8f9bb0", amb2:"#5d6b52", field:"#9aa6b8",
+      listenY:320, listenX:240, you:"CROWD", signal:"M240,352 C240,250 240,150 240,66"
+    }
+  };
+  var order = ["stage","rail","board","hill"];
+  var current = "rail";
+
+  var tabs = Array.prototype.slice.call(document.querySelectorAll('.tab'));
+  var el = {
+    kicker:document.getElementById('pKicker'), title:document.getElementById('pTitle'),
+    bodyt:document.getElementById('pBody'), char:document.getElementById('mChar'),
+    color:document.getElementById('mColor'), dist:document.getElementById('mDist'),
+    image:document.getElementById('mImage'), stageName:document.getElementById('stageName'),
+    listener:document.getElementById('listener'), you:document.getElementById('youTxt'),
+    dsignal:document.getElementById('dsignal')
+  };
+
+  function apply(key){
+    var d = P[key]; if(!d) return;
+    current = key;
+    document.documentElement.style.setProperty('--amb1', d.amb1);
+    document.documentElement.style.setProperty('--amb2', d.amb2);
+    document.documentElement.style.setProperty('--amb-glow', hexA(d.amb1,.18));
+    document.documentElement.style.setProperty('--field', d.field);
+
+    el.kicker.textContent = "Perspective "+d.idx;
+    el.title.textContent = d.name;
+    el.bodyt.textContent = d.body;
+    el.char.textContent = d.char;
+    el.color.textContent = d.color;
+    el.dist.textContent = d.dist;
+    el.image.textContent = d.image;
+    el.stageName.textContent = d.label;
+    el.you.textContent = d.you;
+    el.dsignal.setAttribute('d', d.signal);
+
+    // move listener marker
+    el.listener.setAttribute('transform','translate('+(d.listenX-240)+','+(d.listenY-250)+')');
+
+    tabs.forEach(function(t){
+      var on = t.getAttribute('data-p')===key;
+      t.setAttribute('aria-selected', on?'true':'false');
+    });
+  }
+
+  // convert hex + alpha -> rgba
+  function hexA(hex,a){
+    var h=hex.replace('#',''); if(h.length===3){h=h[0]+h[0]+h[1]+h[1]+h[2]+h[2];}
+    var r=parseInt(h.substr(0,2),16),g=parseInt(h.substr(2,2),16),b=parseInt(h.substr(4,2),16);
+    return 'rgba('+r+','+g+','+b+','+a+')';
+  }
+
+  tabs.forEach(function(t){
+    t.addEventListener('click', function(){ apply(t.getAttribute('data-p')); });
+    t.addEventListener('keydown', function(e){
+      if(e.key==='ArrowRight'||e.key==='ArrowLeft'){
+        e.preventDefault();
+        var i=order.indexOf(current);
+        i = e.key==='ArrowRight' ? (i+1)%order.length : (i-1+order.length)%order.length;
+        apply(order[i]); tabs[i].focus();
+      }
+    });
+  });
+
+  /* ---------- demo signal ---------- */
+  var demoBtn=document.getElementById('demoBtn');
+  var demoState=document.getElementById('demoState');
+  var noteTxt=document.getElementById('noteTxt');
+  function setDemo(on){
+    body.classList.toggle('demo-on', on);
+    demoBtn.setAttribute('aria-pressed', on?'true':'false');
+    demoState.textContent = on ? 'signal active (visual only)' : 'signal idle';
+    noteTxt.textContent = on
+      ? 'Demo Signal on — animating the MODELED signal path. No audio is produced; this is a silent illustration.'
+      : 'Visual simulation — this installation makes no sound. Toggle “Demo Signal” to animate the modeled signal path.';
+  }
+  demoBtn.addEventListener('click', function(){ setDemo(!body.classList.contains('demo-on')); });
+
+  /* ---------- quiet mode ---------- */
+  var quietBtn=document.getElementById('quietBtn');
+  function setQuiet(on){
+    body.classList.toggle('quiet', on);
+    quietBtn.setAttribute('aria-pressed', on?'true':'false');
+    quietBtn.textContent = on ? 'Quiet Mode · On' : 'Quiet Mode';
+  }
+  quietBtn.addEventListener('click', function(){ setQuiet(!body.classList.contains('quiet')); });
+
+  /* ---------- explode ---------- */
+  var explodeBtn=document.getElementById('explodeBtn');
+  var explodeStage=document.getElementById('explodeStage');
+  explodeBtn.addEventListener('click', function(){
+    var on = explodeStage.classList.toggle('exploded');
+    explodeBtn.setAttribute('aria-pressed', on?'true':'false');
+    explodeBtn.textContent = on ? '⤡ Reassemble the Column' : '⤢ Explode the Column';
+  });
+
+  /* ---------- keyboard shortcuts ---------- */
+  document.addEventListener('keydown', function(e){
+    if(/^(INPUT|TEXTAREA|SUMMARY)$/.test((e.target.tagName||''))) return;
+    var k=e.key.toLowerCase();
+    if(k==='1'){apply('stage');}
+    else if(k==='2'){apply('rail');}
+    else if(k==='3'){apply('board');}
+    else if(k==='4'){apply('hill');}
+    else if(k==='d'){setDemo(!body.classList.contains('demo-on'));}
+    else if(k==='q'){setQuiet(!body.classList.contains('quiet'));}
+    else if(k==='e'){explodeBtn.click();}
+    else if(e.key==='ArrowRight'||e.key==='ArrowLeft'){
+      if(document.activeElement && document.activeElement.classList.contains('tab')) return;
+      var i=order.indexOf(current);
+      i = e.key==='ArrowRight' ? (i+1)%order.length : (i-1+order.length)%order.length;
+      apply(order[i]);
+    }
+  });
+
+  /* ---------- build the array cells (hero) ---------- */
+  (function buildArray(){
+    var g=document.getElementById('array');
+    var cols=[[300,360],[360,460],[460,560],[560,620]];
+    var svgns="http://www.w3.org/2000/svg";
+    for(var c=0;c<4;c++){
+      var x0=cols[c][0], x1=cols[c][1], w=x1-x0-8;
+      var rows = 10;
+      for(var r=0;r<rows;r++){
+        var y=78 + r*(384/rows);
+        var cell=document.createElementNS(svgns,'rect');
+        cell.setAttribute('class','speaker-cell');
+        cell.setAttribute('x', x0+4); cell.setAttribute('y', y);
+        cell.setAttribute('width', w); cell.setAttribute('height', (384/rows)-6);
+        cell.setAttribute('rx','2');
+        var op = 0.10 + Math.random()*0.28;
+        cell.setAttribute('fill','var(--field)');
+        cell.setAttribute('fill-opacity', op.toFixed(2));
+        cell.setAttribute('stroke','var(--bronze)');
+        cell.setAttribute('stroke-opacity','.35');
+        // speaker cone hint
+        g.appendChild(cell);
+        var cone=document.createElementNS(svgns,'circle');
+        cone.setAttribute('cx', x0+4+w/2); cone.setAttribute('cy', y+(384/rows-6)/2);
+        cone.setAttribute('r', Math.min(w,384/rows-6)/2 - 3);
+        cone.setAttribute('fill','none'); cone.setAttribute('stroke','var(--field)');
+        cone.setAttribute('stroke-opacity','.25');
+        g.appendChild(cone);
+      }
+    }
+  })();
+
+  /* ---------- scroll entrances ---------- */
+  var io = ('IntersectionObserver' in window) ? new IntersectionObserver(function(entries){
+    entries.forEach(function(en){ if(en.isIntersecting){ en.target.classList.add('in'); io.unobserve(en.target); } });
+  }, {threshold:0.12, rootMargin:'0px 0px -8% 0px'}) : null;
+  var fades=document.querySelectorAll('.fade');
+  if(io){ fades.forEach(function(f){io.observe(f);}); }
+  else { fades.forEach(function(f){f.classList.add('in');}); }
+
+  /* stagger siblings a touch */
+  document.querySelectorAll('.grid, .timeline, .persp-tabs').forEach(function(parent){
+    Array.prototype.slice.call(parent.children).forEach(function(ch,i){
+      ch.style.animationDelay = (i*0.09)+'s';
+    });
+  });
+
+  /* init */
+  apply('rail');
+})();
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/f6e40f30be85/qwen25-7b.html b/data/artifacts/f6e40f30be85/qwen25-7b.html
new file mode 100644
index 0000000..4f310f9
--- /dev/null
+++ b/data/artifacts/f6e40f30be85/qwen25-7b.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Wall of Sound: An Immersive Room</title>
+    <style>
+        * {
+            margin: 0;
+            padding: 0;
+            box-sizing: border-box;
+            font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+        }
+        body {
+            background-color: #f7efe6;
+            color: #3a2c22;
+            display: grid;
+            place-items: center;
+            padding-top: 96px;
+            animation: bgGradient 18s infinite linear;
+        }
+        @keyframes bgGradient {
+            from {background-image: linear-gradient(45deg, rgba(207, 95, 56, .3) 0%, rgba(224, 165, 88, .3) 100%);}
+            to {background-image: linear-gradient(-45deg, rgba(207, 95, 56, .3) 0%, rgba(224, 165, 88, .3) 100%);}
+        }
+        .container {
+            max-width: 1280px;
+            width: 100%;
+            padding: 48px;
+            display: grid;
+            gap: 24px;
+            animation: settle 5s forwards;
+        }
+        h1, h2, h3, p, .card {
+            margin-top: 24px;
+        }
+        .card {
+            background-color: #fff9f1;
+            color: #3a2c22;
+            border-radius: 14px;
+            padding: 24px;
+            text-align: center;
+            transition: transform 0.7s cubic-bezier(.22,1,.36,1);
+        }
+        .card:hover {
+            transform: scale(1.05);
+        }
+        @keyframes fadeUp {
+            from {opacity: 0; transform: translateY(28px);}
+            to {opacity: 1; transform: none;}
+        }
+        .card:hover::after {
+            content: '';
+            position: absolute;
+            top: -4px;
+            left: -4px;
+            right: -4px;
+            bottom: -4px;
+            border-radius: 14px;
+            background-color: rgba(207, 95, 56, .3);
+        }
+        .card label {
+            font-size: 12px;
+            letter-spacing: .15em;
+            color: #a08c7a;
+        }
+        .label-display {
+            text-transform: uppercase;
+            animation: allCaps 1s infinite linear alternate-reverse;
+        }
+        @keyframes allCaps {
+            to {letter-spacing: .2em;}
+        }
+        .section {
+            display: grid;
+            gap: 24px;
+            padding: 0 16px;
+        }
+        .technical-view, .history-panel, .equipment-cards, .glossary, .quiet-mode-control {
+            background-color: #fff9f1;
+            border-radius: 14px;
+            padding: 24px;
+        }
+        .listening-perspectives {
+            display: grid;
+            gap: 24px;
+            margin-top: 48px;
+        }
+    </style>
+</head>
+<body>
+<div class="container">
+    <h1>Wall of Sound: An Immersive Room</h1>
+    <p class="label-display">EXHIBIT DESCRIPTION</p>
+    <div class="section">
+        <div class="technical-view card" onclick="changeView('technical')">
+            <p>Technical View</p>
+        </div>
+        <div class="history-panel card" onclick="changeView('history')">
+            <p>HISTORY PANEL</p>
+        </div>
+        <div class="equipment-cards card" onclick="changeView('equipment')">
+            <p>EQUIPMENT CARDS</p>
+        </div>
+        <div class="glossary card" onclick="changeView('glossary')">
+            <p>GLOSSARY</p>
+        </div>
+    </div>
+    <h2 id="listening-perspectives">Listening Perspectives</h2>
+    <div class="section listening-perspectives">
+        <div class="stage card" onclick="setPerspective('stage')">
+            <p>STAGE</p>
+        </div>
+        <div class="front-rail card" onclick="setPerspective('front-rail')">
+            <p>FRONT RAIL</p>
+        </div>
+        <div class="soundboard card" onclick="setPerspective('soundboard')">
+            <p>SOUNDBOARD</p>
+        </div>
+        <div class="hillside card" onclick="setPerspective('hillside')">
+            <p>HILLSIDE</p>
+        </div>
+    </div>
+    <h2 id="quiet-mode">Quiet Mode</h2>
+    <div class="section quiet-mode-control" onclick="toggleQuietMode()">
+        <p>STOP MOTION WITHOUT DIMINISHING THE DESIGN</p>
+    </div>
+</div>
+
+<script>
+    let currentView = 'technical';
+    function changeView(view) {
+        document.getElementById('listening-perspectives').style.display = 'none';
+        document.getElementById('quiet-mode').style.display = 'none';
+        document.getElementById(currentView).scrollIntoView({behavior: 'smooth'});
+        currentView = view;
+    }
+
+    let quietModeEnabled = false;
+
+    function setPerspective(perspective) {
+        if (!quietModeEnabled) {
+            const section = document.querySelector(`.listening-perspectives .${perspective}`);
+            section.scrollIntoView({behavior: 'smooth'});
+        }
+    }
+
+    function toggleQuietMode() {
+        quietModeEnabled = !quietModeEnabled;
+        const controls = document.querySelectorAll('.card, #listening-perspectives .stage, #listening-perspectives .front-rail, #listening-perspectives .soundboard, #listening-perspectives .hillside');
+        controls.forEach(control => control.style.animationPlayState = quietModeEnabled ? 'paused' : 'running');
+    }
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/f6e40f30be85/qwen3-14b.html b/data/artifacts/f6e40f30be85/qwen3-14b.html
new file mode 100644
index 0000000..b11eac7
--- /dev/null
+++ b/data/artifacts/f6e40f30be85/qwen3-14b.html
@@ -0,0 +1,350 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>Wall of Sound: An Immersive Room</title>
+  <style>
+    :root {
+      --bg: #0d0d0f;
+      --surface: #17171c;
+      --text: #f5f2ea;
+      --muted: #8a8578;
+      --accent: #c9a961;
+      --accent2: #7d6a45;
+      --card-radius: 14px;
+      --spacing-4: 4px;
+      --spacing-8: 8px;
+      --spacing-12: 12px;
+      --spacing-16: 16px;
+      --spacing-24: 24px;
+      --spacing-32: 32px;
+      --spacing-48: 48px;
+      --spacing-64: 64px;
+      --spacing-96: 96px;
+      --spacing-128: 128px;
+      --font-caption: 12px;
+      --font-body: 16px;
+      --font-lead: 21px;
+      --font-h3: 28px;
+      --font-h2: 38px;
+      --font-h1: 50px;
+      --font-display: 67px;
+    }
+
+    * {
+      box-sizing: border-box;
+      margin: 0;
+      padding: 0;
+    }
+
+    body {
+      background: var(--bg);
+      color: var(--text);
+      font-family: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
+      line-height: 1.6;
+      scroll-behavior: smooth;
+      overflow-x: hidden;
+    }
+
+    h1 {
+      font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      font-size: var(--font-h1);
+      letter-spacing: 0.15em;
+      text-transform: uppercase;
+      margin-bottom: var(--spacing-16);
+    }
+
+    h2 {
+      font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      font-size: var(--font-h2);
+      margin-bottom: var(--spacing-24);
+    }
+
+    h3 {
+      font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      font-size: var(--font-h3);
+      margin-bottom: var(--spacing-16);
+    }
+
+    .container {
+      max-width: 1200px;
+      margin: 0 auto;
+      padding: var(--spacing-96) var(--spacing-32);
+    }
+
+    .card {
+      background: var(--surface);
+      border-radius: var(--card-radius);
+      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+      padding: var(--spacing-24);
+      transition: box-shadow 150ms ease;
+    }
+
+    .card:hover {
+      box-shadow: 0 16px 48px rgba(0, 0, 0, 0.18);
+    }
+
+    .card-grid {
+      display: grid;
+      grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
+      gap: var(--spacing-24);
+    }
+
+    .section {
+      padding: var(--spacing-96) var(--spacing-32);
+    }
+
+    .controls {
+      display: flex;
+      flex-wrap: wrap;
+      gap: var(--spacing-16);
+      margin-bottom: var(--spacing-32);
+    }
+
+    .control {
+      background: var(--accent);
+      color: var(--text);
+      padding: var(--spacing-12) var(--spacing-16);
+      border-radius: var(--card-radius);
+      cursor: pointer;
+      transition: background 150ms ease;
+      font-size: var(--font-body);
+    }
+
+    .control:hover {
+      background: var(--accent2);
+    }
+
+    .demo-control {
+      font-size: var(--font-body);
+      font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      letter-spacing: 0.15em;
+      text-transform: uppercase;
+      background: var(--muted);
+      color: var(--text);
+      padding: var(--spacing-12) var(--spacing-16);
+      border-radius: var(--card-radius);
+      cursor: pointer;
+      transition: background 150ms ease;
+    }
+
+    .demo-control:hover {
+      background: var(--accent);
+      color: var(--text);
+    }
+
+    .view {
+      position: relative;
+      height: 400px;
+      background: #1e0b3d;
+      color: white;
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      font-family: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
+      font-size: var(--font-lead);
+      text-align: center;
+      border-radius: var(--card-radius);
+      box-shadow: 0 0 24px var(--accent);
+      transition: box-shadow 150ms ease;
+    }
+
+    .view.active {
+      box-shadow: 0 0 24px var(--accent2);
+    }
+
+    .view-text {
+      position: absolute;
+      bottom: var(--spacing-16);
+      width: 100%;
+      text-align: center;
+      font-size: var(--font-body);
+      color: var(--muted);
+    }
+
+    .signal-path {
+      position: absolute;
+      top: 50%;
+      left: 50%;
+      transform: translate(-50%, -50%);
+      width: 100%;
+      height: 100%;
+      pointer-events: none;
+    }
+
+    .signal-path path {
+      fill: none;
+      stroke: var(--accent);
+      stroke-width: 2;
+      opacity: 0.3;
+    }
+
+    .signal-path path.active {
+      stroke: var(--accent2);
+      opacity: 1;
+    }
+
+    .glow {
+      position: absolute;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background: linear-gradient(180deg, var(--accent), var(--accent2), var(--accent));
+      background-size: 400% 400%;
+      animation: glow 18s linear infinite;
+      z-index: -1;
+    }
+
+    @keyframes glow {
+      0% { background-position: 0% 50%; }
+      50% { background-position: 100% 50%; }
+      100% { background-position: 0% 50%; }
+    }
+
+    @keyframes fadeUp {
+      from {
+        opacity: 0;
+        transform: translateY(28px);
+      }
+      to {
+        opacity: 1;
+        transform: none;
+      }
+    }
+
+    .fade-up {
+      animation: fadeUp 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
+    }
+
+    .fade-up-delayed {
+      animation-delay: 90ms;
+    }
+
+    .fade-up-delayed-2 {
+      animation-delay: 180ms;
+    }
+
+    .fade-up-delayed-3 {
+      animation-delay: 270ms;
+    }
+
+    .fade-up-delayed-4 {
+      animation-delay: 360ms;
+    }
+  </style>
+</head>
+<body>
+  <div class="container">
+    <h1>Wall of Sound: An Immersive Room</h1>
+    <p class="fade-up">A virtual homage to the Grateful Dead’s live sound and communal spirit.</p>
+
+    <div class="controls fade-up">
+      <div class="control" onclick="setView('stage')">Stage</div>
+      <div class="control" onclick="setView('front-rail')">Front Rail</div>
+      <div class="control" onclick="setView('soundboard')">Soundboard</div>
+      <div class="control" onclick="setView('hillside')">Hillside</div>
+      <div class="control" onclick="toggleQuietMode()">Quiet Mode</div>
+      <div class="demo-control" onclick="toggleDemo()">Demo</div>
+    </div>
+
+    <div class="view stage" id="stage" class="active fade-up">
+      <div class="view-text">Stage Perspective: The source of the sound, where the band’s energy radiates outward.</div>
+      <svg class="signal-path" viewBox="0 0 500 500">
+        <path d="M100 250 L300 100 L500 250" />
+      </svg>
+    </div>
+    <div class="view front-rail" id="front-rail" class="fade-up fade-up-delayed">
+      <div class="view-text">Front Rail Perspective: Close to the sound, where clarity and intensity meet.</div>
+      <svg class="signal-path" viewBox="0 0 500 500">
+        <path d="M50 250 L250 100 L450 250" />
+      </svg>
+    </div>
+    <div class="view soundboard" id="soundboard" class="fade-up fade-up-delayed-2">
+      <div class="view-text">Soundboard Perspective: The control center, where the entire sonic experience is shaped.</div>
+      <svg class="signal-path" viewBox="0 0 500 500">
+        <path d="M100 250 L300 400 L500 250" />
+      </svg>
+    </div>
+    <div class="view hillside" id="hillside" class="fade-up fade-up-delayed-3">
+      <div class="view-text">Hillside Perspective: A distant, reverberant field, capturing the live spirit in full.</div>
+      <svg class="signal-path" viewBox="0 0 500 500">
+        <path d="M100 250 L300 350 L500 250" />
+      </svg>
+    </div>
+  </div>
+
+  <div class="section">
+    <h2>Exploded Technical View</h2>
+    <p class="fade-up">This immersive chamber features a monumental abstract speaker array, concentric sound fields, and pools of colored light that react dynamically to your controls. The design is inspired by 1970s engineering diagrams, combined with contemporary installation art and restrained psychedelic color.</p>
+  </div>
+
+  <div class="section">
+    <h2>History</h2>
+    <p class="fade-up">Inspired by the Grateful Dead’s legendary live performances, this installation seeks to capture the communal experience of live sound, where the audience becomes part of the sonic journey. The Grateful Dead’s approach to sound and listening was groundbreaking, and this room is a tribute to that legacy.</p>
+  </div>
+
+  <div class="section">
+    <h2>Equipment Cards</h2>
+    <div class="card-grid fade-up">
+      <div class="card">
+        <h3>Speaker Array</h3>
+        <p>A massive, sculptural sound source, designed to emulate the immersive sound of a live Grateful Dead performance.</p>
+      </div>
+      <div class="card">
+        <h3>Signal Modulator</h3>
+        <p>Interactive controls for altering waveform motion and color pools, allowing visitors to shape the sonic environment.</p>
+      </div>
+      <div class="card">
+        <h3>Color Field Projector</h3>
+        <p>Responds to sound dynamics, creating a visual representation of the audio experience through shifting light.</p>
+      </div>
+    </div>
+  </div>
+
+  <div class="section">
+    <h2>Acoustics Glossary</h2>
+    <div class="card-grid fade-up">
+      <div class="card">
+        <h3>Reflection</h3>
+        <p>The bouncing of sound waves off surfaces, which can enhance or distort the perception of sound.</p>
+      </div>
+      <div class="card">
+        <h3>Diffraction</h3>
+        <p>The bending of sound waves around obstacles, contributing to the spatial perception of sound.</p>
+      </div>
+      <div class="card">
+        <h3>Reverberation</h3>
+        <p>The persistence of sound in a space after the source has stopped, creating a sense of depth and ambiance.</p>
+      </div>
+    </div>
+  </div>
+
+  <script>
+    let demoMode = false;
+    let quietMode = false;
+
+    function setView(view) {
+      document.querySelectorAll('.view').forEach(el => {
+        el.classList.remove('active');
+      });
+      document.getElementById(view).classList.add('active');
+    }
+
+    function toggleQuietMode() {
+      quietMode = !quietMode;
+      document.querySelectorAll('.signal-path path').forEach(el => {
+        el.classList.toggle('active', quietMode);
+      });
+    }
+
+    function toggleDemo() {
+      demoMode = !demoMode;
+      document.querySelectorAll('.view').forEach(el => {
+        el.classList.toggle('demo', demoMode);
+      });
+    }
+  </script>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/challenges.json b/data/challenges.json
index dd8bc79..9140b7e 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -34357,7 +34357,14 @@
         "finished_at": "2026-09-01T19:52:07.366Z",
         "queued_at": "2026-09-01T19:47:49.730Z",
         "bytes": 9742,
-        "thumb": true
+        "thumb": true,
+        "aiScore": 6.8,
+        "aiReason": "The image effectively represents the theme of touring culture but lacks the detailed interactivity and visual richness expected in a polished cultural journalism feature.",
+        "aiScores": {
+          "qwen2.5vl:7b": 7,
+          "minicpm-v:latest": 6.5
+        },
+        "aiSpread": 0.5
       },
       {
         "model": "qwen25-7b",
@@ -34369,19 +34376,38 @@
         "finished_at": "2026-09-01T19:49:59.609Z",
         "queued_at": "2026-09-01T19:47:49.735Z",
         "bytes": 4526,
-        "thumb": true
+        "thumb": true,
+        "aiScore": 7.3,
+        "aiReason": "The design shows promise but lacks the rich data and interactivity required for a fully realized editorial gallery.",
+        "aiScores": {
+          "qwen2.5vl:7b": 7,
+          "minicpm-v:latest": 7.5
+        },
+        "aiSpread": 0.5
       },
       {
         "model": "claude-code",
-        "status": "running",
+        "status": "done",
         "error": null,
-        "seconds": null,
-        "cost": null,
+        "seconds": 455,
+        "cost": 0,
         "started_at": "2026-09-01T19:59:27.531Z",
-        "finished_at": null,
-        "queued_at": "2026-09-01T19:47:49.739Z"
+        "finished_at": "2026-09-01T20:07:02.947Z",
+        "queued_at": "2026-09-01T19:47:49.739Z",
+        "bytes": 51922,
+        "thumb": true,
+        "aiScore": 9.3,
+        "aiReason": "The design effectively fulfills the challenge by providing an engaging and visually coherent exploration of Grateful Dead touring culture. It includes a stylized map, venue ribbons, seasonal movement ",
+        "aiScores": {
+          "qwen2.5vl:7b": 9,
+          "minicpm-v:latest": 9.5
+        },
+        "aiSpread": 0.5
       }
-    ]
+    ],
+    "judging": false,
+    "aiPick": "claude-code",
+    "judged_at": "2026-09-01T20:07:27.672Z"
   },
   {
     "id": "4c73c905dfd0",
@@ -34402,7 +34428,14 @@
         "finished_at": "2026-09-01T19:53:18.135Z",
         "queued_at": "2026-09-01T19:47:49.748Z",
         "bytes": 11474,
-        "thumb": true
+        "thumb": true,
+        "aiScore": 9.3,
+        "aiReason": "The image effectively fulfills the challenge by presenting an elegant and detailed exhibition layout for 'Objects in the Golden Road,' with clear placeholders and thoughtful descriptions. The visual q",
+        "aiScores": {
+          "qwen2.5vl:7b": 9,
+          "minicpm-v:latest": 9.5
+        },
+        "aiSpread": 0.5
       },
       {
         "model": "qwen25-7b",
@@ -34414,18 +34447,37 @@
         "finished_at": "2026-09-01T19:50:24.158Z",
         "queued_at": "2026-09-01T19:47:49.753Z",
         "bytes": 2859,
-        "thumb": true
+        "thumb": true,
+        "aiScore": 8.3,
+        "aiReason": "The image effectively fulfills the challenge by presenting an elegant and detailed catalog entry for a Grateful Dead artifact, adhering to the specified design elements and content requirements.",
+        "aiScores": {
+          "qwen2.5vl:7b": 9,
+          "minicpm-v:latest": 7.5
+        },
+        "aiSpread": 1.5
       },
       {
         "model": "claude-code",
-        "status": "queued",
+        "status": "done",
         "error": null,
-        "seconds": null,
-        "cost": null,
-        "started_at": null,
-        "finished_at": null,
-        "queued_at": "2026-09-01T19:47:49.758Z"
+        "seconds": 323,
+        "cost": 0,
+        "started_at": "2026-09-01T20:07:02.953Z",
+        "finished_at": "2026-09-01T20:12:25.543Z",
+        "queued_at": "2026-09-01T19:47:49.758Z",
+        "bytes": 56045,
+        "thumb": true,
+        "aiScore": 8.3,
+        "aiReason": "The image effectively fulfills the challenge by presenting an elegant and detailed catalog of Grateful Dead fan artifacts in a refined HTML format.",
+        "aiScores": {
+          "qwen2.5vl:7b": 9,
+          "minicpm-v:latest": 7.5
+        },
+        "aiSpread": 1.5
       }
-    ]
+    ],
+    "judging": false,
+    "aiPick": "qwen3-14b",
+    "judged_at": "2026-09-01T20:12:45.723Z"
   }
 ]
\ No newline at end of file
diff --git a/verification/grateful-dead-five-live.png b/verification/grateful-dead-five-live.png
new file mode 100644
index 0000000..a4fb4da
Binary files /dev/null and b/verification/grateful-dead-five-live.png differ
diff --git a/verification/grateful-dead-five-proof.json b/verification/grateful-dead-five-proof.json
new file mode 100644
index 0000000..5d22aa8
--- /dev/null
+++ b/verification/grateful-dead-five-proof.json
@@ -0,0 +1,48 @@
+{
+  "intent": "Create five sophisticated Grateful Dead-themed gallery challenges and compare three available zero-cost models on each brief.",
+  "riskTier": "R4 production content mutation",
+  "environment": "https://modelarena.agentabrams.com/",
+  "timestamp": "2026-09-01T20:15:00-07:00",
+  "buildCommit": "dd024dc",
+  "baseline": {
+    "service": "online",
+    "selectedModels": ["qwen3-14b", "qwen25-7b", "claude-code"],
+    "estimatedMeteredSpendUsd": 0
+  },
+  "mutation": {
+    "challengeIds": ["a5990564b1ee", "b05597bd9f5a", "f6e40f30be85", "6d9acbcfa9a2", "4c73c905dfd0"],
+    "promptCharacters": [1119, 1074, 1166, 1143, 1134],
+    "requestedRuns": 15,
+    "designTools": true
+  },
+  "checks": [
+    {
+      "boundary": "production challenge API",
+      "verdict": "PASS",
+      "assertions": ["five unique challenges persisted", "each challenge has exactly three requested models", "all prompts exceed 1000 characters"]
+    },
+    {
+      "boundary": "generation and rendering",
+      "verdict": "PASS",
+      "assertions": ["15/15 runs completed", "15/15 thumbnails rendered", "zero failed runs", "zero metered spend"]
+    },
+    {
+      "boundary": "AI referee",
+      "verdict": "PASS",
+      "assertions": ["15/15 artifacts received numeric scores", "all five challenges have an AI comparison record"]
+    },
+    {
+      "boundary": "live browser journey",
+      "verdict": "PASS",
+      "command": "ARENA_URL=https://modelarena.agentabrams.com/ node verification/grateful-dead-five.e2e.js",
+      "assertions": ["all five titles visible in Newest view", "all production records readable", "all runs done/rendered/scored", "zero browser errors"]
+    }
+  ],
+  "evidence": [
+    "verification/grateful-dead-five.e2e.js",
+    "verification/grateful-dead-five-live.png",
+    "data/grateful-dead-gallery-challenges.json"
+  ],
+  "cleanup": "The five requested production challenges and their 15 artifacts are intentionally retained. No metered models were selected and no retries were required.",
+  "verdict": "PASS"
+}
diff --git a/verification/grateful-dead-five.e2e.js b/verification/grateful-dead-five.e2e.js
new file mode 100644
index 0000000..f11b670
--- /dev/null
+++ b/verification/grateful-dead-five.e2e.js
@@ -0,0 +1,56 @@
+#!/usr/bin/env node
+const { chromium } = require('/Users/macstudio3/Projects/Designer-Wallcoverings/node_modules/playwright');
+
+const ids = ['a5990564b1ee', 'b05597bd9f5a', 'f6e40f30be85', '6d9acbcfa9a2', '4c73c905dfd0'];
+const titles = [
+  'The Long Strange Archive',
+  'Deadhead Print Lab',
+  'Wall of Sound: An Immersive Room',
+  'Routes, Residencies & Rituals',
+  'Objects in the Golden Road',
+];
+
+(async () => {
+  const browser = await chromium.launch({ executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', headless: true });
+  const context = await browser.newContext({
+    viewport: { width: 1440, height: 1100 },
+    httpCredentials: { username: process.env.ARENA_USER || 'admin', password: process.env.ARENA_PASS || 'DW2024!' },
+  });
+  const page = await context.newPage();
+  const errors = [];
+  page.on('pageerror', error => errors.push(String(error)));
+  page.on('console', message => {
+    if (message.type() === 'error' && !/^Failed to load resource:/.test(message.text())) errors.push(message.text());
+  });
+  const base = process.env.ARENA_URL || 'https://modelarena.agentabrams.com/';
+  await page.goto(base, { waitUntil: 'domcontentloaded' });
+  await page.waitForSelector('#list .card');
+  const cardText = await page.locator('#list').innerText();
+  for (const title of titles) if (!cardText.includes(title)) throw new Error(`live list missing ${title}`);
+
+  const records = await page.evaluate(async challengeIds => Promise.all(
+    challengeIds.map(id => fetch('/api/challenges/' + id).then(response => response.json()))
+  ), ids);
+  for (const record of records) {
+    if (record.prompt.length < 1000) throw new Error(`${record.title} prompt too short: ${record.prompt.length}`);
+    if (record.runs.length !== 3) throw new Error(`${record.title} expected 3 runs, got ${record.runs.length}`);
+    const incomplete = record.runs.filter(run => run.status !== 'done');
+    if (incomplete.length) throw new Error(`${record.title} has incomplete runs: ${incomplete.map(run => `${run.model}:${run.status}`).join(', ')}`);
+    const unrendered = record.runs.filter(run => !run.thumb || typeof run.aiScore !== 'number');
+    if (unrendered.length) throw new Error(`${record.title} has unrendered or unscored runs: ${unrendered.map(run => run.model).join(', ')}`);
+  }
+  await page.screenshot({ path: 'verification/grateful-dead-five-live.png', fullPage: true });
+  if (errors.length) throw new Error(`browser errors: ${errors.join(' | ')}`);
+  console.log(JSON.stringify({
+    pass: true,
+    challenges: records.map(record => ({
+      id: record.id,
+      title: record.title,
+      characters: record.prompt.length,
+      states: record.runs.map(run => run.status),
+      scores: record.runs.map(run => ({ model: run.model, score: run.aiScore })),
+    })),
+    browserErrors: 0,
+  }));
+  await browser.close();
+})().catch(error => { console.error(error.stack || error); process.exit(1); });

← fe65583 auto-data-snapshot: 2026-09-01T12:55:30 (14 data files) — da  ·  back to Model Arena  ·  auto-data-snapshot: 2026-09-01T13:36:10 (1 data files) — dat 2ce0937 →