← back to Gallery Agentabrams
builds/deadhead-print-lab/index.html
768 lines
<!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>