/* bibliotech · the flyer
   one photocopied sheet stapled to a black wall.
   no javascript. one animation (the misregistration slip). */

*{margin:0;padding:0;box-sizing:border-box}

html,body{
  background:#050505;
  overflow-x:hidden;          /* the photo hangs off the sheet on purpose */
}
body{
  font-family:'Inter',sans-serif;
  color:#f2f0e6;
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}
::selection{background:#cd2cf2;color:#050505}
a{color:inherit}
a:focus-visible{outline:2px solid #cd2cf2;outline-offset:3px}

/* the filter definition lives in the html but must not take up space */
.filters{position:absolute;width:0;height:0;overflow:hidden}

/* photocopy texture over the whole wall */
.grain{
  position:fixed;inset:-50%;width:200%;height:200%;
  pointer-events:none;z-index:50;opacity:.11;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grain 7s steps(10) infinite;
}
@keyframes grain{
  0%,100%{transform:translate(0,0)}
  20%{transform:translate(-3%,2%)}
  40%{transform:translate(2%,-3%)}
  60%{transform:translate(-2%,-2%)}
  80%{transform:translate(3%,3%)}
}

/* ===== the wall ===== the current flyer is pasted over the older
   ones. .wall is exactly sheet-width, so the past posters can be
   hung off its corners and end up half-buried behind the sheet */
.wall{
  position:relative;
  width:min(680px,94vw);
  margin:clamp(5rem,11vh,8rem) auto clamp(4rem,9vh,6rem);
}

/* the buried layers. dimmed and knocked back so the live flyer
   still owns the page. torn edges via clip-path, one shape each. */
.past{
  position:absolute;
  display:block;
  height:auto;                 /* width rules below drive the size */
  /* knock back, then crush to tone steps last so the banding stays crisp */
  filter:grayscale(.72) contrast(1.25) brightness(.52) url(#posterise);
  box-shadow:0 14px 34px rgba(0,0,0,.75);
}
.p1{  /* bibliotech 01 · bar eleven · may 2024 · deepest */
  width:270px;top:-54px;left:-72px;rotate:-9deg;z-index:1;
  clip-path:polygon(6% 0%,100% 3%,97% 100%,55% 96%,30% 100%,4% 94%,8% 62%,2% 55%,7% 30%,0% 22%);
}
.p2{  /* .freedom /dance · billy bootleggers · apr 2025 */
  width:288px;top:-36px;right:-80px;rotate:8deg;z-index:2;
  clip-path:polygon(2% 4%,28% 0%,60% 5%,96% 1%,100% 34%,93% 41%,99% 66%,95% 98%,5% 96%);
}
.p3{  /* the model x park90 · aug 2025 */
  width:262px;bottom:-26px;left:-86px;rotate:-6deg;z-index:3;
  clip-path:polygon(5% 2%,45% 6%,96% 0%,100% 97%,40% 100%,3% 95%,9% 70%,1% 48%,8% 26%);
}
.p4{  /* vol 3 · the model · may 2026 · most recent, nearest the top */
  width:236px;bottom:-62px;right:-64px;rotate:6deg;z-index:4;
  clip-path:polygon(0% 3%,95% 0%,100% 45%,94% 52%,98% 80%,60% 92%,35% 100%,4% 90%);
}

/* ===== the sheet ===== */
.sheet{
  --pad-x:clamp(1.4rem,4vw,3rem);
  --pad-y:clamp(2rem,5vw,3.5rem);
  width:100%;
  margin:0;
  padding:var(--pad-y) var(--pad-x);
  background:#0b0b0a;
  rotate:.7deg;
  box-shadow:0 30px 80px rgba(0,0,0,.85);
  position:relative;
  z-index:5;
}
/* halftone screen: a fine dot grid laid over everything printed on
   the sheet, like newsprint held close. pointer-events:none so the
   players and tear-off tabs stay clickable through it. */
.sheet::after{
  content:'';
  position:absolute;inset:0;z-index:10;
  pointer-events:none;
  background-image:radial-gradient(circle,rgba(242,240,230,.06) .6px,transparent .7px);
  background-size:3px 3px;
}
/* uneven ink: the paper is not lit evenly */
.sheet::before{
  content:'';
  position:absolute;inset:0;z-index:9;
  pointer-events:none;
  background:
    radial-gradient(ellipse at 28% 12%,rgba(242,240,230,.028),transparent 55%),
    radial-gradient(ellipse at 82% 88%,rgba(0,0,0,.3),transparent 62%);
}

/* tape: corners of the sheet, and one across the photo */
.tape{
  position:absolute;
  width:90px;height:28px;
  background:rgba(242,240,230,.14);
}
.tape.tl{top:-14px;left:-22px;rotate:-40deg}
.tape.tr{top:-14px;right:-22px;rotate:35deg}

/* ===== printed matter, top to bottom ===== */

/* corner print */
.corner{
  display:flex;justify-content:flex-end;align-items:baseline;
  gap:1rem;flex-wrap:wrap;
  font-size:.68rem;letter-spacing:.26em;color:#666;
  margin-bottom:2.5rem;
}
.corner-links{display:flex;gap:1.1rem}
.corner a{text-decoration:none}
.corner a:hover{text-decoration:underline;text-underline-offset:4px}

/* the wordmark. the pink layer is the press running out of register:
   it sits behind the yellow and slips every few seconds (see @slip) */
.wordmark{
  position:relative;
  font-family:'Oswald',sans-serif;font-weight:700;
  font-size:clamp(4rem,17vw,7.5rem);
  line-height:.9;
  rotate:-2deg;
  margin-bottom:0;
}
.wordmark .ink{position:relative;color:#d4c641}
.wordmark .mis{
  position:absolute;left:4px;top:3px;
  color:#cd2cf2;
  animation:slip 9s steps(1,end) infinite;
}
@keyframes slip{
  0%,92%,100%{translate:0 0}
  94%{translate:7px -4px}
  97%{translate:-3px 2px}
}

/* ===== the burst ===== the litany, screen-printed onto a spiky
   sticker. the pink copy sits behind and out of register, same press
   fault as the wordmark. text is real html, so it stays selectable.
   cqw sizing keeps the type a fixed share of the shape, so it can
   never outgrow the spikes at any screen size. */
.burst{
  position:relative;
  container-type:inline-size;
  width:min(100%,620px);
  aspect-ratio:600/420;
  margin:1.5rem auto 3rem;
  rotate:1.6deg;
}
.burst svg{position:absolute;inset:0;width:100%;height:100%;display:block}
/* tight misregistration, same as the wordmark: a plate a few pixels
   out, not a drop shadow. the breathe is deliberately tiny - on a
   600px shape even 1% is a visible swell */
.burst-mis{
  translate:4px 3px;
  transform-origin:50% 50%;
  animation:breathe 6.5s ease-in-out infinite;
}
.burst-mis path{fill:#cd2cf2}
@keyframes breathe{
  0%,100%{scale:1}
  50%{scale:1.008}
}
.burst-fill{fill:#d4c641}
.burst-dash{
  fill:none;stroke:#050505;stroke-width:2.5;
  stroke-dasharray:9 7;stroke-linecap:round;
}

/* rubber stamp */
.stamped{margin-bottom:5rem}
.stamp{
  display:inline-block;
  font-family:'Oswald',sans-serif;font-weight:600;
  font-size:.86rem;letter-spacing:.16em;
  color:#d4c641;
  border:2px solid #d4c641;border-radius:2px;
  padding:.5rem .9rem;
  rotate:-3deg;opacity:.92;
}
/* the sets */
.heading{
  font-family:'Oswald',sans-serif;font-weight:600;
  font-size:.7rem;letter-spacing:.34em;color:#d4c641;
  margin-bottom:1.1rem;
}
/* each set is printed on the flyer like a cassette insert: a yellow
   side tab, the title, and the real player underneath. the player is
   soundcloud's own widget, so it still plays; the dashed box and the
   invert are what make it look printed rather than pasted-in */
.cassette{
  display:flex;gap:.85rem;
  border:1px dashed #333;
  background:rgba(212,198,65,.035);
  padding:.75rem .85rem;
  margin-bottom:.9rem;
}
.cassette-side{
  flex:none;width:1.85rem;
  display:flex;align-items:center;justify-content:center;
  font-family:'Oswald',sans-serif;font-weight:700;
  font-size:1.05rem;line-height:1;
  color:#050505;background:#d4c641;
}
.cassette-body{flex:1;min-width:0}
.cassette-title{
  display:block;
  font-size:.78rem;color:#f2f0e6;text-decoration:none;
  margin-bottom:.45rem;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.cassette-title:hover{text-decoration:underline;text-underline-offset:4px}
/* the soundcloud bar ships white and glares on black paper. inverting
   it lands the widget on near-black; the hue swing takes the accent
   (set to yellow in the src) back to yellow rather than blue */
.set-embed{
  width:100%;height:20px;display:block;border:0;
  filter:invert(1) hue-rotate(180deg);
}

/* the litany, sitting inside the burst. black ink on yellow is the
   only pairing here with real contrast (11:1), so the shape carries
   the colour and the words stay legible */
.litany{
  position:absolute;inset:0;
  display:flex;flex-direction:column;justify-content:center;align-items:center;
  text-align:center;
  font-family:'Oswald',sans-serif;font-weight:600;
  font-size:clamp(.85rem,4.4vw,1.9rem);  /* fallback */
  font-size:5.2cqw;
  line-height:1.2;
  color:#050505;
  /* sits the words on the shape's optical centre, which is a touch
     above the box centre */
  padding-bottom:5%;
}
.litany span{display:block}

/* ===== the tear-off strip =====
   negative margins pull the strip out to the paper's edges */
.strip{
  display:flex;
  border-top:2px dashed #333;
  margin:3rem calc(-1 * var(--pad-x)) calc(-1 * var(--pad-y));
}
.tab{
  flex:1 1 0;min-width:0;
  height:7rem;
  display:flex;align-items:center;justify-content:center;
  border-left:2px dashed #333;
  font-family:'Oswald',sans-serif;font-weight:600;
  font-size:.72rem;letter-spacing:.18em;
  color:#d4c641;text-decoration:none;
  transition:translate .2s ease;
}
.tab:first-child{border-left:0}
.tab span{writing-mode:vertical-rl}
.tab:hover{translate:0 -3px}
/* hand-cut, so no two tabs sit quite straight */
.tab:nth-child(1){rotate:-.8deg}
.tab:nth-child(2){rotate:1.1deg}
.tab:nth-child(4){rotate:-1.4deg}
.tab:nth-child(5){rotate:.6deg}
.tab:nth-child(6){rotate:-.4deg}
.tab:nth-child(7){rotate:1.5deg}
.tab:nth-child(8){rotate:-1.1deg}
/* someone already took one */
.tab.torn{
  align-self:flex-start;
  height:1.3rem;
  background:rgba(242,240,230,.05);
  clip-path:polygon(0 0,100% 0,100% 58%,86% 100%,72% 52%,58% 94%,44% 48%,30% 88%,16% 54%,0 82%);
}

/* ===== small screens ===== */
/* narrow screens have no room either side of the sheet, so the old
   posters peek out above and below it instead of from the corners */
@media (max-width:760px){
  .p1{width:42%;top:-48px;left:1%;right:auto}
  .p2{width:44%;top:-34px;right:2%;left:auto}
  .p3{width:40%;bottom:-30px;left:3%;right:auto}
  .p4{width:36%;bottom:-54px;right:1%;left:auto}
}

@media (max-width:520px){
  /* fewer tabs so each stays a real thumb target */
  .tab:nth-child(n+7){display:none}
}

@media (prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
}
