← 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>