/* ============================================================
   Saint Howl — sainthowl.com

   The site is built as a printed object, not a screen. Everything
   here comes from the band's own screen-printed sticker sheet:
   the spot colours are sampled off those files, the wordmark is
   their actual lettering placed as artwork, and photographs get a
   real halftone dot screen rather than sitting flat.

   Spot colours, sampled:
     teal    #37AB9C   from 01_wordmark-banner_teal
     red     #DF4127   from 07_dragon_teal
     yellow  #FFF300   process yellow, the wordmark ink
     ochre   #E9C50C   from 09_wordmark_yellow-circle
     ink     #17190C   the Green Electric Chapel cover's shadow
   ============================================================ */

/* Suffix Serif, Jen Wagner Type. Commercial licence held by the band: web +
   commercial. Served from this site only. The files live in this repository
   because it is private; see README "Typeface" before making it public. */
@font-face {
  font-family: "Text Serif";
  src: url("/fonts/suffixserif-light.01d0ace6.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Text Serif";
  src: url("/fonts/suffixserif-regular.4b5bb508.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Text Serif";
  src: url("/fonts/suffixserif-italic.2b5f2223.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Text Serif";
  src: url("/fonts/suffixserif-medium.263c1fe8.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Text Serif";
  src: url("/fonts/suffixserif-mediumitalic.85ae2525.woff2") format("woff2");
  font-weight: 500;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Text Serif";
  src: url("/fonts/suffixserif-semibold.e8bf4514.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Plex Mono";
  src: url("/fonts/plexmono-400.c36f509c.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Plex Mono";
  src: url("/fonts/plexmono-500.a76f53ca.woff2") format("woff2");
  font-weight: 500;
  font-display: swap;
}

:root {
  --paper:      #EDE6D6;
  --paper-deep: #E2D9C3;
  --ink:        #17190C;
  --ink-soft:   #5A5B47;

  --teal:   #37AB9C;
  --red:    #DF4127;
  --yellow: #FFF300;
  --ochre:  #E9C50C;

  --serif: "Text Serif", Georgia, "Times New Roman", serif;
  --mono:  "Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --measure: 34rem;
  --gutter:  clamp(1.25rem, 5vw, 3.5rem);

  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

html { background: var(--paper); -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 400;
  font-size: clamp(1.0625rem, 0.98rem + 0.42vw, 1.25rem);
  line-height: 1.6;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Paper fibre, tiled into the background rather than laid over the page, so it
   scrolls with the content and leaves no seam. A procedural SVG noise texture,
   the same category of thing as a CSS gradient: not an image, not generated art. */
.wrap {
  width: 100%;
  max-width: 62rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

a { color: inherit; text-decoration: none; }

strong, b { font-weight: 600; }

:focus-visible {
  outline: 2px solid var(--red);
  outline-offset: 3px;
}

.skip { position: absolute; left: -9999px; }
.skip:focus {
  left: var(--gutter); top: 1rem; z-index: 10000;
  background: var(--ink); color: var(--paper);
  padding: 0.6rem 1rem;
}

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Caption type: printed small copy. Dates, venues, credits, labels. */
.meta {
  font-family: var(--mono);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft);
  line-height: 1.5;
}

/* ---------- the wordmark, placed as artwork ----------
   Their own lettering, masked so it can take any spot colour. */

.wordmark {
  display: block;
  width: clamp(11rem, 26vw, 17rem);
  aspect-ratio: 1600 / 502;
  background-color: var(--ink);
  -webkit-mask: url("/assets/brand/wordmark.png") no-repeat center / contain;
  mask: url("/assets/brand/wordmark.png") no-repeat center / contain;
  transition: background-color 120ms ease;
}
.wordmark:hover { background-color: var(--red); }

.wordmark--large {
  width: min(100%, 46rem);
  background-color: var(--red);
}

/* ---------- masthead ---------- */

.masthead { padding-block: clamp(1.5rem, 4vw, 2.5rem) clamp(1rem, 2.5vw, 1.5rem); }

.masthead__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1.25rem 2rem;
}

/* With the wordmark gone from the home page's masthead the nav is the only
   child, and space-between drops it to the left. Push it back so the nav does
   not jump sides when you click through from the home page to any other. */
.masthead__inner > .nav:only-child { margin-left: auto; }

/* The rule under the masthead is a printed bar, not a hairline. */
.bar {
  height: 7px;
  background: var(--ink);
  position: relative;
}
.bar::after {
  content: "";
  position: absolute;
  inset: 0;
  transform: translate(2px, 2px);
  background: var(--teal);
  mix-blend-mode: multiply;
  z-index: -1;
}
.bar--red::after { background: var(--red); }

.nav { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.5rem; }
.nav a {
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  padding: 0.3rem 0;
  border-bottom: 2px solid transparent;
}
.nav a:hover { border-bottom-color: var(--red); }
.nav a[aria-current="page"] { border-bottom-color: var(--ink); }
.nav__sep { color: var(--teal); user-select: none; font-size: 0.6875rem; }
/* On a phone the masthead is two lines by design. base.njk places an empty
   .nav__break after the larger half of the items, and below 34rem it becomes
   the line break, so the row splits at the same place on every phone (Shows,
   Music, Gallery, Letters over Bio, Pasaj, Contact) instead of wherever the
   last word stopped fitting, which used to strand Contact alone on a second
   line. A fixed break can never strand an interpunct, so the mark from the
   cover lettering now stays on phones too; only the one that would open the
   second line is dropped. Above 34rem the break is inert and the row holds on
   one line, measured at every width from 545 to 1280 on 28 September 2026. */
.nav__break { display: none; }
@media (max-width: 34rem) {
  .nav__break { display: block; flex-basis: 100%; height: 0; }
  .nav__break + .nav__sep { display: none; }
}

/* ---------- headings, printed slightly out of register ----------
   In a real two-colour print the plates never line up perfectly and the
   second colour shows at the edges. That is what this is. */

.h-print {
  font-weight: 300;
  line-height: 1.02;
  letter-spacing: -0.02em;
  color: var(--ink);
  text-shadow: 2px -2px 0 var(--teal);
}
.h-print--red { text-shadow: 2px -2px 0 var(--red); }

.page-head { padding-block: clamp(2.5rem, 7vw, 5rem) clamp(1.5rem, 3.5vw, 2.5rem); }
.page-head h1 {
  margin: 0.6rem 0 0;
  font-size: clamp(2.5rem, 1.5rem + 5vw, 5rem);
  max-width: 16ch;
}
.page-head > p { margin: 1.25rem 0 0; max-width: var(--measure); }

main { flex: 1 0 auto; }

.prose { max-width: var(--measure); }

/* When one element is both the page container and the text column, .wrap's
   centring takes hold of the 34rem measure and centres THAT in the window, so
   the text drifts right and stops sharing a left edge with its own heading.
   Keep the container's box; constrain the text inside it instead. */
.wrap.prose { max-width: 62rem; }
.wrap.prose > * { max-width: var(--measure); }
.prose p { margin: 0 0 1.3em; }
.prose a { border-bottom: 2px solid var(--ink); }
.prose a:hover { border-bottom-color: var(--red); }
.prose h2 { font-weight: 500; font-size: 1.5rem; margin: 2.4em 0 0.6em; }
.prose blockquote {
  margin: 2em 0;
  padding: 0.2rem 0 0.2rem 1.25rem;
  border-left: 5px solid var(--red);
  font-style: italic;
  font-weight: 500;
}

/* ---------- the feed ---------- */

.entry {
  display: grid;
  gap: 0.5rem;
  padding-block: clamp(1.75rem, 4vw, 2.5rem);
  border-bottom: 2px solid var(--ink);
}
.entry:last-child { border-bottom: 0; }
@media (min-width: 46rem) {
  .entry { grid-template-columns: 9rem 1fr; gap: 0 2.5rem; align-items: start; }
}
.entry__date { padding-top: 0.6rem; }
.entry__title {
  margin: 0;
  font-weight: 400;
  font-size: clamp(1.5rem, 1.15rem + 1.6vw, 2.125rem);
  line-height: 1.16;
  letter-spacing: -0.018em;
  max-width: 24ch;
}
.entry__body { margin: 0.6rem 0 0; max-width: var(--measure); font-size: 0.9375em; }

/* Links read as rubber-stamped tags, not underlined web text. */
.stamp {
  display: inline-block;
  margin-top: 0.85rem;
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--paper);
  background: var(--ink);
  padding: 0.5rem 0.8rem;
}
.stamp:hover { background: var(--yellow); color: var(--ink); }
.stamp--teal { background: var(--teal); color: var(--ink); }
.stamp--teal:hover { background: var(--yellow); color: var(--ink); }

/* ---------- shows ---------- */

.show {
  display: grid;
  gap: 0.3rem;
  padding-block: 1.4rem;
  border-bottom: 2px solid var(--ink);
}
@media (min-width: 46rem) {
  .show { grid-template-columns: 9rem 1fr auto; gap: 0 2.5rem; align-items: center; }
}
.show__city { font-size: 1.25rem; letter-spacing: -0.01em; }
.show__venue { color: var(--ink-soft); font-size: 0.9375rem; }
.show--past { border-bottom-width: 1px; }
.show--past .show__city { font-size: 1.0625rem; color: var(--ink-soft); }

/* ---------- releases ---------- */

.release { display: grid; gap: 1.75rem; padding-block: clamp(1.5rem, 4vw, 2.5rem); }
@media (min-width: 40rem) {
  .release { grid-template-columns: minmax(0, 15rem) 1fr; gap: 2.75rem; align-items: start; }
}
.release__cover { aspect-ratio: 1; background: var(--paper-deep); }
.release__cover img { display: block; width: 100%; height: 100%; object-fit: cover; }
.release__title {
  margin: 0.35rem 0 0;
  font-weight: 400;
  font-size: clamp(1.75rem, 1.3rem + 2vw, 2.5rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
.listen { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 1.4rem; }

/* Where the record can be bought. One stamp in the wordmark's yellow, ink on
   it at 15:1, so it reads as the thing to do rather than one logo among five;
   the services that only stream follow in ink. */
.buy {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.9rem;
  margin: 1.4rem 0 0;
}
.buy .stamp { margin-top: 0; }
.buy__note { margin: 0; }
.buy + .listen, .buy + .listen__label { margin-top: 0.9rem; }
.stamp--buy { background: var(--yellow); color: var(--ink); }
.stamp--buy:hover { background: var(--ink); color: var(--paper); }

/* ---------- /listen/, the page the Listen ads point at ----------
   One job: the record and a tap to each place it plays, all of it in the
   first screen of a phone held in Instagram's browser. The sleeve stays small
   beside the title on a phone; the stamps stack full width, big enough for a
   thumb, Spotify first, Bandcamp's yellow under them. */
.hub { padding-block: clamp(1.25rem, 5vw, 3rem) clamp(2rem, 6vw, 4rem); }
.hub__record { display: grid; grid-template-columns: 6.5rem 1fr; gap: 1.1rem; align-items: end; }
@media (min-width: 40rem) { .hub__record { grid-template-columns: 12rem 1fr; gap: 2rem; } }
.hub__cover { display: block; width: 100%; height: auto; background: var(--paper-deep); }
.hub__title {
  margin: 0.35rem 0 0;
  font-weight: 400;
  font-size: clamp(1.6rem, 1.2rem + 2vw, 2.5rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}
.listen--stack { flex-direction: column; align-items: stretch; max-width: 24rem; gap: 0.55rem; }
.listen--stack .stamp { font-size: 0.75rem; padding: 0.8rem 1rem; text-align: center; }
.hub .buy { max-width: 24rem; margin-top: 0.9rem; }
.hub .buy .stamp { font-size: 0.75rem; padding: 0.8rem 1rem; text-align: center; flex: 1 1 100%; }
.hub__also { margin: 0.8rem 0 0; }
.hub__also a { border-bottom: 1px solid currentColor; }
.hub__more { margin: 1.75rem 0 0; }
.hub__more a { border-bottom: 1px solid currentColor; }

/* ---------- the record's own account ----------
   The band's writing about the album, printed under the catalogue entry as a
   sheet of text rather than squeezed into the column beside the sleeve. The
   red rule is the mark the enclosed piece already uses: it says the voice has
   changed, from the site describing the record to the band describing it. */
.about {
  max-width: var(--measure);
  padding-bottom: clamp(1.5rem, 4vw, 2.5rem);
}
.about::before {
  content: "";
  display: block;
  width: 5rem;
  height: 3px;
  margin-bottom: clamp(1.75rem, 4vw, 2.5rem);
  background: var(--red);
}
.about p { margin: 0 0 1.3em; }
.about p:last-child { margin-bottom: 0; }

/* The opening line is one sentence and does a standfirst's job, so it is set
   up to display size. Declared after .about p, and with a class to spare, so
   source order cannot hand its margins back to the paragraph rule above. */
.about .about__open {
  margin-bottom: 1.15em;
  font-size: clamp(1.375rem, 1.05rem + 1.05vw, 1.75rem);
  line-height: 1.24;
  letter-spacing: -0.012em;
}

/* ---------- halftone photographs ----------
   A real dot screen laid over the image in multiply, the way their merch
   is printed. The photograph underneath is untouched. */

/* Columns rather than a grid: these are real crops at their true proportions,
   portrait and landscape mixed, and a row-based grid leaves every row as tall
   as its tallest photograph with holes underneath the rest. Flowing them fills
   the wall, and at one column on a phone the sequence still reads in order. */
.grid {
  column-count: 3;
  column-gap: clamp(0.85rem, 2vw, 1.4rem);
}
@media (max-width: 62rem) { .grid { column-count: 2; } }
@media (max-width: 34rem) { .grid { column-count: 1; } }
.shot {
  display: inline-block;
  width: 100%;
  margin: 0 0 clamp(0.85rem, 2vw, 1.4rem);
  break-inside: avoid;
}
.shot__frame { position: relative; background: var(--paper-deep); }
.shot__frame img { display: block; width: 100%; height: auto; }
.shot__frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  mix-blend-mode: multiply;
  opacity: 0.5;
  background-image: radial-gradient(circle at 50% 50%, rgba(23,25,12,0.85) 0.9px, transparent 1.1px);
  background-size: 3.5px 3.5px;
}
.shot figcaption { margin-top: 0.5rem; }

/* The band's own prints, sitting in the same wall as the photographs. They
   are already screen-printed, so laying a second dot screen over them only
   muddies the ink, and the die-cut ones want the page behind them rather
   than a tinted box: a sticker on paper, not a framed picture. */
.shot__frame--print { background: none; }
.shot__frame--print::after { content: none; }

/* ---------- placeholders ----------
   Deliberately conspicuous. A missing asset must look missing. */

.placeholder {
  display: grid;
  place-content: center;
  gap: 0.4rem;
  text-align: center;
  min-height: 11rem;
  padding: 1.5rem;
  background:
    repeating-linear-gradient(45deg, transparent 0 10px, rgba(223,65,39,0.13) 10px 20px),
    var(--paper-deep);
  border: 2px dashed var(--red);
}
.placeholder__label { color: var(--red); font-weight: 500; }
.placeholder__note { color: var(--ink-soft); font-size: 0.875rem; max-width: 30ch; margin: 0 auto; }

/* ---------- the seal ----------
   Their own circular sticker, placed as a sticker is placed: off-axis. */

.seal {
  width: clamp(5.5rem, 13vw, 8.5rem);
  height: auto;
  transform: rotate(-8deg);
}

/* ---------- footer ---------- */

footer.site { flex-shrink: 0; margin-top: clamp(3rem, 7vw, 5rem); }
footer.site .inner {
  padding-block: 1.75rem 3rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem 2rem;
  align-items: flex-end;
  justify-content: space-between;
}
footer.site .links { display: flex; flex-wrap: wrap; gap: 0.5rem; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0.01ms !important; }
}

/* The dragon print, placed on the dead end like a sticker slapped on a wall. */
.lost {
  display: block;
  width: min(100%, 30rem);
  height: auto;
  margin-top: clamp(2.5rem, 6vw, 4rem);
  transform: rotate(-2.5deg);
}

/* ---------- spacing classes ----------
   These replace inline style attributes, which the site's own
   Content-Security-Policy (style-src 'self') silently drops in production. */

.lede           { margin-top: 0.5rem; }
.footer-name    { margin: 0 0 0.6rem; }
.section-label  { margin: 4rem 0 0.75rem; }
.gap-above      { margin-top: 2rem; }
.gap-above-lg   { margin-top: 3.5rem; }
.band           { padding-block: 2rem; }
.prose--piece   { padding-top: 2.5rem; }

/* ---------- the home page, read as the back of a sleeve ----------
   The band's line, then a plate, then the record, the dates, and the prints.
   Nothing here is an essay; every block is an object you could point at on a
   printed sleeve. */

/* The home page carries the wordmark itself, so the masthead above it holds
   only the navigation and the page needs less air before the name arrives. */
.page-head--home { padding-block: clamp(1.25rem, 4vw, 2.5rem) 0; }

.statement { padding-block: clamp(1.75rem, 5vw, 3rem) 0; }
.statement__line {
  margin: 0;
  max-width: 20ch;
  font-size: clamp(1.875rem, 1.1rem + 3.4vw, 3.25rem);
}

/* The plate runs the full measure of the page rather than the text measure,
   because a photograph on a sleeve is not set to a column. */
.plate { margin-block: clamp(2.5rem, 6vw, 4rem) 0; }
.plate__caption { margin: 0.5rem 0 0; }

/* The record as an object: both printed faces side by side, the way you turn a
   sleeve over. Artwork never takes the dot screen, so neither face is screened;
   the paper-deep ground behind them is the only frame they get. */
.record { padding-top: clamp(2rem, 5vw, 3rem); }
.record__meta { margin: 1.25rem 0 0; }
.sleeve {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(0.9rem, 2.5vw, 1.5rem);
  margin: clamp(1.25rem, 3vw, 1.75rem) 0 0;
}
@media (min-width: 46rem) { .sleeve { grid-template-columns: 1fr 1fr; } }
.sleeve__face { margin: 0; background: var(--paper-deep); aspect-ratio: 1; }
.sleeve__face img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* The record's contents, set the way a sleeve insert sets them: two columns of
   quiet type, numbered by the list itself so the numerals stay out of the way. */
.tracks {
  margin: clamp(1.25rem, 3vw, 1.75rem) 0 0;
  padding: 0 0 0 1.6rem;
  columns: 2;
  column-gap: clamp(1.5rem, 4vw, 3rem);
  font-size: 0.9375rem;
}
@media (max-width: 30rem) { .tracks { columns: 1; } }
.tracks__item {
  break-inside: avoid;
  margin-bottom: 0.3rem;
  padding-left: 0.2rem;
  color: var(--ink-soft);
}
.tracks__item::marker { font-family: var(--mono); font-size: 0.75em; }

/* The compact player is a pasted-on object, not part of the grid: Spotify
   brings its own chrome and pretending otherwise looks worse than admitting
   it. Sat on the paper with a shadow, the way the dragon sits on the 404. */
/* .player carries max-width:34rem and is declared later in this file, so the
   compact variant needs the extra class to win rather than relying on order. */
.player.player--compact {
  max-width: none;
  margin: clamp(1.5rem, 4vw, 2rem) 0 0;
  box-shadow: 3px 3px 0 var(--paper-deep);
}
.player--compact iframe { display: block; width: 100%; border: 0; }

.release__title a { border-bottom: 2px solid transparent; }
.release__title a:hover { border-bottom-color: var(--red); }

.dates { padding-top: clamp(2rem, 5vw, 3rem); }
.dates__label { margin: 1.25rem 0 0.5rem; }
.dates .show:last-of-type { border-bottom: 0; }

/* A sticker sheet tipped into the sleeve: the prints at thumbnail size, each
   one linking into the gallery. No dot screen — they are already printed. */
.prints { padding-top: clamp(2rem, 5vw, 3rem); }
.prints__sheet {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(0.9rem, 2.5vw, 1.6rem);
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
  align-items: center;
}
/* One height for all three so they read as stickers off the same sheet rather
   than as three unrelated pictures. The tall engraving would otherwise tower
   over the moon and the dragon at equal column widths. */
.prints__item img {
  display: block;
  width: 100%;
  height: clamp(7rem, 16vw, 11rem);
  object-fit: contain;
  object-position: center;
  transition: transform 120ms ease-out;
}
.prints__item a:hover img,
.prints__item a:focus-visible img { transform: translate(-2px, -2px); }
.bar--thin      { height: 3px; }
.stamp--inline  { margin-top: 0; }

/* ---------- deeper paper ----------
   One noise layer reads as digital grain. Real stock has fine fibre AND a
   slower mottle from how the pulp settled, so this lays both down at very
   different scales, plus a faint edge shade so the sheet has a body. */

body {
  background-color: var(--paper);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='f'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23f)' opacity='0.20'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='700' height='700'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='700' height='700' filter='url(%23m)' opacity='0.13'/%3E%3C/svg%3E");
  background-repeat: repeat, repeat;
  background-size: 260px 260px, 700px 700px;
}

/* ---------- ink behaviour ----------
   A screen-printed bar does not have a ruled edge; the ink catches and breaks
   along it. The SVG displacement filter in base.njk roughens the boundary. */

.bar {
  filter: url(#roughen);
}

/* Where two plates overlap, real ink darkens rather than covering. */
.bar::after { mix-blend-mode: multiply; }

/* Flat CSS colour reads as a swatch. A dot screen over the fill makes the
   stamps read as ink laid on paper. */
.stamp {
  position: relative;
  overflow: hidden;
  filter: url(#roughen-tight);
}
.stamp::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.22;
  mix-blend-mode: screen;
  background-image: radial-gradient(circle at 50% 50%, rgba(237,230,214,0.9) 0.6px, transparent 0.8px);
  background-size: 3px 3px;
}
.stamp--teal::after, .stamp--buy::after { mix-blend-mode: multiply; opacity: 0.16;
  background-image: radial-gradient(circle at 50% 50%, rgba(23,25,12,0.9) 0.6px, transparent 0.8px); }

/* The placeholder hatching is a printed fill too. */
.placeholder { filter: url(#roughen-tight); }

/* Nothing on a printed sheet is perfectly square to the page. */
.release__cover { transform: rotate(-0.35deg); }
.filters { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ---------- the coupon ----------
   A mail-order slip: cut line, a ruled field to write on, a stamp to send it.
   The shape a band's sign-up actually took before it was a modal. */

.coupon {
  margin-top: clamp(2.5rem, 6vw, 4rem);
  padding: 3px;
  background: repeating-linear-gradient(
    90deg, var(--ink) 0 8px, transparent 8px 15px
  ),
  repeating-linear-gradient(
    180deg, var(--ink) 0 8px, transparent 8px 15px
  ),
  repeating-linear-gradient(
    90deg, var(--ink) 0 8px, transparent 8px 15px
  ),
  repeating-linear-gradient(
    180deg, var(--ink) 0 8px, transparent 8px 15px
  );
  background-size: 100% 2px, 2px 100%, 100% 2px, 2px 100%;
  background-position: 0 0, 100% 0, 0 100%, 0 0;
  background-repeat: no-repeat;
  transform: rotate(-0.4deg);
}
.coupon__inner { padding: clamp(1.5rem, 4vw, 2.5rem); }
.coupon__label { margin: 0; }
.coupon__lede {
  margin: 0.6rem 0 1.5rem;
  max-width: 34ch;
  font-size: 1.125rem;
  line-height: 1.45;
}

.coupon__form {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.9rem 1rem;
  /* A slip, not a banner: the field and its stamp stay one object. */
  max-width: 30rem;
}

/* A ruled line to write on, not a rounded box. */
.coupon__field {
  flex: 1 1 13rem;
  min-width: 0;
  font-family: var(--serif);
  font-size: 1.125rem;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 2px solid var(--ink);
  border-radius: 0;
  padding: 0.35rem 0.1rem;
  appearance: none;
}
.coupon__field::placeholder { color: var(--ink-soft); opacity: 0.75; }
.coupon__field:focus-visible {
  border-bottom-width: 3px;
  border-bottom-color: var(--red);
  background: rgba(223, 65, 39, 0.06);
}
.coupon__form .stamp { flex: 0 0 auto; }
.coupon__fine { margin: 1.1rem 0 0; }

/* On /join/ the coupon is the page rather than the footer of one, so it sits at
   the top with no margin above it and its lede is set a size up. Everything
   else about it stays identical — it should read as the same coupon people
   have already seen elsewhere on the site, not a different offer. */
.coupon--hero { margin-top: 0; }
.coupon--hero .coupon__lede {
  max-width: 42ch;
  font-size: clamp(1.125rem, 1rem + 0.6vw, 1.375rem);
}


/* ---------- shop ----------
   A shop item is the same object as a record: a square image placed like a
   print, the details beside it, a stamp to act on. It reuses .release rather
   than inventing a second layout, so the page reads as part of the catalogue
   and not as a store bolted onto the side. */
.shop__price {
  margin: 1rem 0 0;
  font-size: 1.35rem;
  font-variant-numeric: tabular-nums;
}
.shop__sold {
  margin: 1rem 0 0;
  color: var(--red);
}
.shop__fine {
  color: var(--ink-soft);
  max-width: var(--measure);
  line-height: 1.7;
}

/* ---------- enclosure ----------
   What arrives after the coupon is sent. A packing list, not a download page:
   the same ruled rows as the shows archive, so it reads as part of the same
   printed object rather than a separate offer. */
.enclosure {
  list-style: none;
  margin: 0;
  padding: 0;
  max-width: var(--measure);
}
.enclosure__item {
  padding-block: 1.4rem;
  border-bottom: 2px solid var(--ink);
}
.enclosure__kind { margin: 0 0 0.35rem; }
.enclosure__title {
  margin: 0;
  font-size: 1.35rem;
  line-height: 1.25;
}
.enclosure__title a { border-bottom: 2px solid var(--ink); }
.enclosure__title a:hover { border-bottom-color: var(--red); }
.enclosure__note {
  margin: 0.5rem 0 0;
  color: var(--ink-soft);
  font-size: 0.9375rem;
  max-width: 44ch;
}
.enclosure__foot { color: var(--ink-soft); }

/* ---------- the letter on the subscriber page ----------
   A letter, not an article: the photograph runs a little wider than the text
   so the page reads as a printed sheet with a plate on it, and the text keeps
   the same 34rem measure as every other piece of writing on the site. */

.letter { margin-top: clamp(2.5rem, 6vw, 4rem); }
.letter__label { margin: 0.75rem 0 0; }

.letter__figure { margin: clamp(1.5rem, 4vw, 2.25rem) 0 0; max-width: 44rem; }

/* A strip of film frames, not a plate: at better than five to one it takes the
   whole column rather than the plate width. It was briefly held to a minimum
   width and allowed to scroll, which on a phone cut the third frame off with
   nothing to say it could be pulled into view — a composed triptych sliced in
   half reads as a broken image, where the same strip shown small and whole
   reads as exactly what it is. So it shrinks, and the lightbox every other
   photograph on the site already has is what opens it properly.
   The dot screen comes off: at this height the dots eat the picture. */
.letter__figure--strip { max-width: none; }
.shot__frame--strip::after { content: none; }
.shot__frame--strip img { display: block; width: 100%; height: auto; }

.letter__body { margin-top: clamp(1.75rem, 4vw, 2.5rem); }

/* The enclosed piece is someone else's writing. It gets its own rule above it
   and a little more air, so a reader can see where Burke stops and Andrea
   starts without being told twice. */
.letter__piece { margin-top: clamp(2.25rem, 5vw, 3.25rem); }
.letter__piece::before {
  content: "";
  display: block;
  width: 5rem;
  height: 3px;
  margin-bottom: clamp(1.75rem, 4vw, 2.5rem);
  background: var(--red);
}
.letter__piece-title { margin-top: 0; font-style: italic; }
.letter__credit { margin: 2.25em 0 0; color: var(--ink-soft); }

/* Where to hear the record, under the letter that is about it. The label and
   stamp row are the same pair the music page uses, so the two read as one
   system; only the space above it is new. */
.letter__listen { margin-top: clamp(1.75rem, 4vw, 2.5rem); }

/* ---------- the player ----------
   A foreign object placed on the sheet: the band's own frame around someone
   else's box, so it sits on the paper instead of floating over it. */
.player {
  margin: 1.6rem 0 1.75rem;
  padding: 3px;
  background: var(--ink);
  max-width: 34rem;
}
.player iframe { display: block; width: 100%; border: 0; background: var(--paper-deep); }

/* ---------- the video ----------
   The same frame as the audio player, because it is the same kind of object:
   somebody else's box sat on the band's paper. What differs is that nothing is
   loaded until it is asked for, so what the page holds at rest is the band's
   own frame of film, halftoned like every other photograph on the site. The
   dot screen lifts on play, because a dot screen over live video is a mess. */
.video {
  position: relative;
  aspect-ratio: 16 / 9;
  margin: clamp(1.5rem, 4vw, 2.25rem) 0 0;
  padding: 3px;
  background: var(--ink);
  box-shadow: 4px 4px 0 var(--paper-deep);
}
.video iframe { display: block; width: 100%; height: 100%; border: 0; }

.video__poster {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: var(--paper-deep);
  cursor: pointer;
  overflow: hidden;
}
.video__poster img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* The dot screen, matched to .shot__frame::after so a film still and a
   photograph are printed by the same press. */
.video__poster::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: radial-gradient(var(--ink) 34%, transparent 36%);
  background-size: 3px 3px;
  mix-blend-mode: multiply;
  opacity: 0.32;
}

/* A pressed seal rather than a play button: the band's yellow, an ink
   triangle cut out of it, sitting slightly off centre the way a stamp lands. */
.video__play {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: clamp(4rem, 11vw, 5.5rem);
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--yellow);
  box-shadow: 3px 3px 0 var(--red);
  transition: transform 120ms ease-out;
}
.video__play::before {
  content: "";
  position: absolute;
  left: 54%;
  top: 50%;
  transform: translate(-50%, -50%);
  border-style: solid;
  border-width: 0.7em 0 0.7em 1.15em;
  border-color: transparent transparent transparent var(--ink);
  font-size: clamp(1rem, 2.6vw, 1.3rem);
}
.video__poster:hover .video__play { transform: translate(-50%, -50%) scale(1.06); }
.video__poster:focus-visible { outline: 3px solid var(--red); outline-offset: 3px; }

@media (prefers-reduced-motion: reduce) {
  .video__play, .video__poster:hover .video__play { transition: none; transform: translate(-50%, -50%); }
}
.listen__label { margin: 0 0 0.6rem; }

/* ---------- lightbox ----------
   Enhancement only: without the script the gallery is still a grid of
   photographs. With it, a photograph can actually be looked at. */

.shot__frame img { cursor: zoom-in; }
.shot__frame img:focus-visible { outline: 2px solid var(--red); outline-offset: 3px; }

html.is-lit { overflow: hidden; }

/* A class-level display value beats the browser's [hidden] rule, so hiding it
   has to be stated explicitly or el.hidden silently does nothing. */
.lightbox[hidden] { display: none; }

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 10000;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(23, 25, 12, 0.94);
}
.lightbox__frame {
  display: grid;
  gap: 0.75rem;
  max-width: min(100%, 68rem);
  max-height: 100%;
}
.lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 78vh;
  width: auto;
  height: auto;
  margin-inline: auto;
  border: 3px solid var(--paper);
}
.lightbox__cap { color: var(--paper); text-align: center; margin: 0; }
.lightbox__close {
  position: absolute;
  top: clamp(0.75rem, 2vw, 1.5rem);
  right: clamp(0.75rem, 2vw, 1.5rem);
  font-family: var(--mono);
  font-weight: 500;
  font-size: 0.625rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--yellow);
  border: 0;
  padding: 0.55rem 0.85rem;
  cursor: pointer;
}
.lightbox__close:hover { background: var(--paper); color: var(--ink); }

/* ---------- the Pasaj application form ----------
   The same ruled line to write on as the coupon, one field under another, a
   stamp to send it. A form on paper, not a panel. */

.form { max-width: 34rem; padding-bottom: clamp(2rem, 5vw, 4rem); }
.field { display: block; margin: 0 0 1.6rem; }
.field__label {
  display: block;
  font-weight: 500;
  margin: 0 0 0.35rem;
}
.field__input {
  display: block;
  width: 100%;
  box-sizing: border-box;
  font-family: var(--serif);
  font-size: 1.0625rem;
  line-height: 1.45;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 2px solid var(--ink);
  border-radius: 0;
  padding: 0.35rem 0.1rem;
  appearance: none;
}
.field__input::placeholder { color: var(--ink-soft); opacity: 0.75; }
.field__input:focus-visible {
  outline: none;
  border-bottom-width: 3px;
  border-bottom-color: var(--red);
  background: rgba(223, 65, 39, 0.06);
}
/* A textarea is ruled all round, since one line under a block of text reads
   as an underline on the last line only. */
textarea.field__input {
  min-height: 6rem;
  resize: vertical;
  border: 2px solid var(--ink);
  padding: 0.5rem 0.6rem;
}
textarea.field__input:focus-visible { border-width: 2px; border-color: var(--red); }
.field__help {
  display: block;
  margin: 0.35rem 0 0;
  font-size: 0.875em;
  color: var(--ink-soft);
}
.field--choices { border: 0; padding: 0; margin: 0 0 1.6rem; min-width: 0; }
.field--choices legend { padding: 0; }
.field__choice {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  margin: 0.4rem 0;
}
.field__choice input { accent-color: var(--red); margin: 0; }

/* Three photographs in one row, as a contact sheet strip, rather than the
   gallery's flowing columns: on /pasaj/ they sit between the heading and the
   text, and a row reads as one object where a partial masonry reads as a gap. */
.shots-row {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(0.85rem, 2vw, 1.4rem);
  margin: 0 0 clamp(1.5rem, 4vw, 2.5rem);
}
.shots-row .shot { margin: 0; }
@media (max-width: 34rem) { .shots-row { grid-template-columns: 1fr; } }

/* ---------- the cookie banner ----------
   Only while site.meta.live is on. One sentence and two answers. Printed on a slip of the same paper with an
   ink edge, answered with the same stamps as everywhere else, the two answers
   the same size on purpose. One line where it fits, two on a phone. Below the
   lightbox, above the page. */
.consent[hidden] { display: none; }
.consent {
  position: fixed;
  /* Lined up with the text column's left edge, as .wrap centres it. */
  left: max(var(--gutter), calc((100vw - 62rem) / 2 + var(--gutter)));
  right: var(--gutter);
  bottom: clamp(0.75rem, 2vw, 1.25rem);
  z-index: 9000;
  max-width: 44rem;
  margin: 0;
  padding: 0.7rem 0.9rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem 1rem;
  background-color: var(--paper);
  border: 2px solid var(--ink);
  box-shadow: 4px 4px 0 var(--paper-deep);
  font-size: 0.875rem;
  line-height: 1.45;
}
.consent p { margin: 0; }
.consent__text { flex: 1 1 20rem; }
.consent .consent__actions { display: flex; gap: 0.5rem; }
.consent .consent__actions .stamp { min-width: 4.5rem; text-align: center; }
/* One language at a time, set by site.js from the browser's language. */
.consent[data-lang="tr"] [data-say="en"],
.consent[data-lang="en"] [data-say="tr"] { display: none; }
button.stamp { border: 0; cursor: pointer; }
.footer-privacy { margin: 0.4rem 0 0; }
.footer-privacy a { border-bottom: 1px solid currentColor; }

/* ---------- /howl, the QR sticker's page ----------
   For someone who just scanned a sticker. The page is one room, the art "a
   piece of the living page" (Burke, 9 October 2026): designer's welcome wall,
   and on the same green the line, a printed rule, the letters, Instagram
   first and largest, and the music, like the label beside a painting. Under
   the wall on a phone, beside it on a computer. One column of fixed rhythm
   (1.5rem between parts, 0.5rem from a label to what it labels), every button
   at least 44px tall for a thumb, the services in an even two-column grid.

   What makes it warm is kept quiet (Burke, 9 October: no panels, nothing
   over the top): the picture's plaster carried on across the page, a lamp's
   warmth around the art, a slow drift of light like low sun through leaves
   (the band's bio), stamps that rest on the wall and give under a finger,
   and the words settling in as the page opens. Every texture is drawn in
   code (SVG noise and gradients), like the paper fibre: it depicts nothing. */

/* The ground: the wall's plaster a shade darker than its lower edge, with
   the picture's own kind of surface, a fine grain and a slow cloud of tone,
   laid in soft light, and the lamp's warmth from above. Ink would vanish on
   it, so the page's type is paper and its stamps paper and teal. */
html.page--howl { background: #19211B; }
.page--howl body {
  color: var(--paper);
  background-color: #19211B;
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' seed='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)' opacity='0.34'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='640' height='640'%3E%3Cfilter id='m' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.006' numOctaves='3' seed='21' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1'/%3E%3C/filter%3E%3Crect width='640' height='640' filter='url(%23m)' opacity='0.18'/%3E%3C/svg%3E"),
    radial-gradient(110% 55% at 50% 0%, rgba(255, 196, 132, 0.06), rgba(255, 196, 132, 0) 75%);
  background-size: 220px 220px, 640px 640px, 100% 100%;
  background-repeat: repeat, repeat, no-repeat;
  background-blend-mode: soft-light, soft-light, normal;
}

/* The light behind the wall stays inside the room: no sideways scroll on a
   phone, no scroll at all on a computer. */
.howl-room { position: relative; isolation: isolate; overflow: hidden; overflow: clip; }

/* Low sun through leaves: warm patches drifting across the plaster, slow
   enough to be felt more than seen, behind everything, never over the art.
   Still for anyone whose device asks for less motion. */
.howl-room::before {
  content: "";
  position: absolute;
  z-index: -2;
  inset: -6%;
  pointer-events: none;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='900' height='900'%3E%3Cfilter id='s' x='0' y='0' width='100%25' height='100%25' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.0035' numOctaves='2' seed='13' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 .88 0 0 0 0 .7 1.3 0 0 0 -.62'/%3E%3C/filter%3E%3Crect width='900' height='900' filter='url(%23s)'/%3E%3C/svg%3E") 0 0 / 900px 900px;
  mix-blend-mode: soft-light;
  opacity: 0.14;
  animation: howl-breeze 40s ease-in-out infinite alternate;
  will-change: transform;
}
@keyframes howl-breeze {
  0%   { transform: translate3d(-3%, -1.5%, 0); }
  50%  { transform: translate3d(0.5%, 1%, 0); }
  100% { transform: translate3d(3%, 2.5%, 0); }
}
/* The consent slip stays a paper slip in ink, as on every other page. */
.page--howl .consent { color: var(--ink); }

/* The wall (designer, 9 October 2026) is shown whole: never cropped, nothing
   over it. Only its plain plaster margin fades into the room: at 720px there
   are 40px of bare plaster outside every frame at the sides, 33 at the top
   and 45 at the foot, and the fade stays inside that, so no piece is cut or
   touched. Behind it, a pool of its mid-plaster green, so its edges fall off
   into the room the way gallery light does rather than stopping at a line. */
.howl-wall {
  position: relative;
  isolation: isolate;
  max-width: 720px;
  margin-inline: auto;
}
.howl-wall::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: -8% -30%;
  pointer-events: none;
  background:
    radial-gradient(closest-side, rgba(255, 200, 140, 0.06), rgba(255, 200, 140, 0) 85%),
    radial-gradient(closest-side, rgba(53, 71, 58, 0.9), rgba(53, 71, 58, 0.45) 60%, rgba(53, 71, 58, 0));
}
.howl-wall picture { display: block; }
.howl-wall img {
  display: block;
  width: 100%;
  height: auto;
  -webkit-mask-image:
    linear-gradient(to right, transparent, #000 4.5%, #000 95.5%, transparent),
    linear-gradient(transparent, #000 2.5%, #000 96%, transparent);
  -webkit-mask-composite: source-in;
  mask-image:
    linear-gradient(to right, transparent, #000 4.5%, #000 95.5%, transparent),
    linear-gradient(transparent, #000 2.5%, #000 96%, transparent);
  mask-composite: intersect;
}

.howl {
  position: relative;
  width: 100%;
  max-width: 28rem;
  margin-inline: auto;
  padding: 0.75rem var(--gutter) 1.5rem;
}
.howl__line { margin: 0; font-size: 1.125rem; line-height: 1.4; max-width: 30ch; }
.howl .meta { color: rgba(237, 230, 214, 0.64); }
.howl :focus-visible { outline-color: var(--yellow); }

/* The printed rule in the room's inks: paper, with the teal plate off
   register. */
.howl__rule { margin-top: 1.1rem; background: var(--paper); }
.howl__rule::after { mix-blend-mode: normal; }

.howl > section { margin-top: 1.5rem; }
.howl__rule + section { margin-top: 1.25rem; }
.howl__label { margin: 0 0 0.5rem; }

.howl__form { flex-wrap: nowrap; align-items: flex-end; gap: 0.75rem; max-width: none; }
.howl__form .coupon__field { flex: 1 1 auto; padding-block: 0.55rem 0.4rem; }
.howl__form .stamp { flex: 0 0 auto; min-height: 2.75rem; padding: 0.85rem 1.1rem; font-size: 0.6875rem; }
.howl__fine {
  margin: 0.75rem 0 0;
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  text-transform: none;
  line-height: 1.5;
}
.howl__fine a { border-bottom: 1px solid currentColor; }

.howl__instagram {
  display: block;
  margin: 0;
  padding: 1rem;
  font-size: 0.75rem;
  line-height: 1.4;
  text-align: center;
}
.howl__handle { display: block; margin-top: 0.2rem; opacity: 0.8; text-transform: none; letter-spacing: 0.06em; }

.howl__places { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.howl__places .stamp {
  margin: 0;
  min-height: 2.75rem;
  padding: 0.85rem 0.5rem;
  font-size: 0.6875rem;
  text-align: center;
}
/* Seven services: the last one takes the whole row instead of half of it. */
.howl__places .stamp:last-child:nth-child(odd) { grid-column: 1 / -1; }

.howl__show-item {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem 1rem;
}
/* Only the first date shows: the next one moves up when site.js removes a
   date that has passed. */
.howl__show-item + .howl__show-item { display: none; }
.howl__venue { margin: 0; font-size: 1rem; line-height: 1.35; }
.howl__venue time { display: block; }
.howl__show-item .stamp { margin: 0; }

/* Paper stamps: ink on paper, the dot screen in ink like the teal ones. */
.stamp--paper { background: var(--paper); color: var(--ink); }
.stamp--paper:hover { background: var(--yellow); color: var(--ink); }
.stamp--paper::after { mix-blend-mode: multiply; opacity: 0.16;
  background-image: radial-gradient(circle at 50% 50%, rgba(23,25,12,0.9) 0.6px, transparent 0.8px); }

/* The field on the wall: written in paper, a paper line, yellow when in use,
   and a browser's autofill kept to the room's colours. */
.howl__form .coupon__field { color: var(--paper); border-bottom-color: var(--paper); }
.howl__form .coupon__field::placeholder { color: var(--paper); opacity: 0.55; }
.howl__form .coupon__field:focus-visible { border-bottom-color: var(--yellow); background: rgba(255, 243, 0, 0.06); }
.howl__form .coupon__field:-webkit-autofill {
  -webkit-text-fill-color: var(--paper);
  -webkit-box-shadow: 0 0 0 100px #1C251E inset;
  caret-color: var(--paper);
}

.howl__foot { margin: 2.25rem 0 0; }
.howl__foot a { border-bottom: 1px solid currentColor; }

/* The stamps rest on the wall like paper on plaster, a soft shadow under
   each, and give a little under a finger or a click. */
.howl .stamp {
  box-shadow: 0 1px 0 rgba(8, 12, 9, 0.45), 0 6px 14px -6px rgba(8, 12, 9, 0.7);
  transition: transform 140ms ease, box-shadow 140ms ease, background-color 200ms ease, color 200ms ease;
}
.howl .stamp:active {
  transform: translateY(1px);
  box-shadow: 0 0 0 rgba(8, 12, 9, 0.45), 0 2px 5px -2px rgba(8, 12, 9, 0.7);
}

/* The words settle in as the page opens, one after another, a breath and
   no more. */
@keyframes howl-settle {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
.howl > * { animation: howl-settle 700ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
.howl > :nth-child(2) { animation-delay: 60ms; }
.howl > :nth-child(3) { animation-delay: 120ms; }
.howl > :nth-child(4) { animation-delay: 180ms; }
.howl > :nth-child(5) { animation-delay: 240ms; }
.howl > :nth-child(n+6) { animation-delay: 300ms; }

@media (prefers-reduced-motion: reduce) {
  .howl-room::before, .howl > * { animation: none; }
  .howl .stamp { transition: none; }
}

/* On a touch screen a tapped stamp would stay yellow when the visitor comes
   back from Spotify or Instagram; there the yellow shows only under the
   finger. */
@media (hover: none) {
  .howl .stamp--paper:hover { background: var(--paper); color: var(--ink); }
  .howl .stamp--teal:hover { background: var(--teal); color: var(--ink); }
  .howl .stamp:active { background: var(--yellow); color: var(--ink); }
}

/* A computer: the wall and its words side by side on one screen, the wall as
   tall as the window allows (never over 720px wide), the words centred
   beside it. The consent slip sits under the words, clear of the art. */
@media (min-width: 1024px) and (min-height: 600px) {
  .page--howl {
    --howl-gap: 5rem;
    --howl-text: 25rem;
    --howl-wall: min(720px, calc((100vh - 4rem) * 2 / 3), calc(100vw - var(--howl-text) - var(--howl-gap) - 2 * var(--gutter)));
    --howl-wall: min(720px, calc((100svh - 4rem) * 2 / 3), calc(100vw - var(--howl-text) - var(--howl-gap) - 2 * var(--gutter)));
  }
  .howl-room {
    display: grid;
    grid-template-columns: var(--howl-wall) var(--howl-text);
    justify-content: center;
    align-items: center;
    column-gap: var(--howl-gap);
    min-height: 100vh;
    min-height: 100svh;
    padding: 2rem var(--gutter);
  }
  .howl-wall { margin: 0; }
  .howl { max-width: none; margin: 0; padding: 0; }
  .howl__line { font-size: 1.25rem; }
  .page--howl .consent {
    left: auto;
    right: calc((100vw - var(--howl-wall) - var(--howl-gap) - var(--howl-text)) / 2);
    width: var(--howl-text);
    max-width: var(--howl-text);
  }
}
