/* =========================================================================
   CC Ascher — site stylesheet
   Direction D4: a dividing line (the datum) near the middle of the first
   screen, a lighter field above it holding a photo on the right, the
   title resting on the line on the left, nav directly under the line.
   Static — no scroll-driven shrinking, no fixed positioning. An earlier,
   scroll-shrinking version of this hid content behind itself as you
   scrolled; that's gone for good.

   Tone: the palette below is only the no-JavaScript default.
   assets/scheme.js picks one of nine monochrome film tones per visit and
   overrides these variables; see that file for the palettes.

   Materials: off-white paper, warm-black ink, one restrained plum/oxblood
   accent (the margin note and the one stamp, nothing else). Courier
   Prime carries titles, nav, and now the body copy too — full typewriter,
   not a book face. Caveat (handwriting) carries exactly two things: the
   one margin note and the one photo caption. A torn photo corner, a
   strip of tape, a coffee-ring stain — each used once, not scattered.
   ========================================================================= */

:root{
  --paper:#EAE6DE;
  --field:#F3F0EB;
  --ink:#1A1813;
  --mut:#706C64;
  --line:#BAB4AB;
  --note:#683F41;
  /* the carriage: quick to start, long glide, hard stop */
  --carriage: cubic-bezier(.55,0,.15,1);
  color-scheme: light;
  box-sizing: border-box;
}
html{
  padding-top: env(safe-area-inset-top, 0px);
  padding-bottom: env(safe-area-inset-bottom, 0px);
  scroll-padding-top: env(safe-area-inset-top, 0px);
  /* .margin-note is positioned with a negative right offset past
     .content's edge, which can push past the viewport's right edge on
     some widths and force an unwanted horizontal scrollbar on the whole
     page — caught by checking actual scrollWidth vs innerWidth, not by
     eye. Clipping here is harmless: the note is decorative, never
     critical content. */
  overflow-x: clip;
}
*{ box-sizing: border-box; }
html,body{ margin: 0; }

/* ---- custom fonts ---------------------------------------------------
   All in assets/fonts/. Titles: OldNewspaperTypes. Album-card titles,
   lyric headings, and Index slips: Moms Typewriter. Body: Libre Caslon
   Text. The Smith-Corona faces are declared but not used anywhere yet. */
@font-face{
  font-family: "Moms Typewriter";
  src: url("fonts/MomsTypewriter.ttf") format("truetype");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face{
  font-family: "Libre Caslon Text";
  src: url("fonts/LibreCaslonText-Regular.ttf") format("truetype");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face{
  font-family: "Libre Caslon Text";
  src: url("fonts/LibreCaslonText-Bold.ttf") format("truetype");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face{
  font-family: "Libre Caslon Text";
  src: url("fonts/LibreCaslonText-Italic.ttf") format("truetype");
  font-weight: 400; font-style: italic; font-display: swap;
}

@font-face {
  font-family: 'Smith-Corona EC1100 Prestige';
  src: url('fonts/Smith-Corona EC1100 Prestige.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}

@font-face {
  font-family: 'Smith-Corona EC1100 Mini Gothic';
  src: url('fonts/Smith-Corona EC1100 Mini Gothic.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}

@font-face {
  font-family: 'Smith-Corona EC1100 Script';
  src: url('fonts/Smith-Corona EC1100 Script.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}

@font-face {
  font-family: 'OldNewspaperTypes';
  src: url('fonts/OldNewspaperTypes.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}

body{
  color: var(--ink);
  /* "The rest of the text" — everything on the site except page titles
     — is Libre Caslon Text once it's uploaded. Until then this falls
     back to Literata (already loaded via Google Fonts on every page),
     which is a closer approximation of a Caslon-style serif than the
     typewriter face body copy used previously, so the interim look is
     closer to the intended final result. */
  font-family: "Libre Caslon Text", "Literata", Georgia, serif;
  line-height: 1.65;
  font-size: 16px;
  position: relative;
  -webkit-font-smoothing: antialiased;
  /* clip, not hidden: hidden turns body into a scroll container, which
     silently breaks every position: sticky on the site (the songs page's
     lyric pane) */
  overflow-x: clip;
}
a{ color: inherit; }
img{ max-width: 100%; display: block; }

.skip-link{
  position: absolute; left: -9999px; top: 0;
  background: var(--ink); color: var(--paper); padding: 8px 14px; z-index: 30;
}
.skip-link:focus{ left: 12px; top: 12px; }

/* ---- the paper ----------------------------------------------------------
   One seamless 1024px tile (assets/images/paper.jpg): soft mottling,
   the tooth of the sheet, fine grain, and pulp fibres laid in several
   directions. It's a near-white greyscale image multiplied into the
   tone's --paper color, so it takes every tone without a second file.
   It sits on the root background and scrolls with the page, like a
   sheet you're reading down, rather than staying pinned to the window.
   The tile is periodic by construction, so there are no seams. */
html{
  background-color: var(--paper);
  background-image: url("images/paper.jpg");
  background-size: 1024px 1024px;
  background-repeat: repeat;
  background-blend-mode: multiply;
}
body{ background: transparent; }

.site{ position: relative; }

/* One coffee-ring stain, one instance, on About only — a raster image,
   PIL-rendered rather than a real scanned stain. Placed behind the bio paragraph's corner, not floating
   alone in empty space. Kerouac's own mythology more than a design
   flourish; a direct, requested exception to "no fake aging." */
.stain{
  position: absolute; z-index: 0; pointer-events: none;
  /* toned like everything else: grey, then multiplied into the paper, so
     it takes the session's tone and loses its rectangular backing */
  filter: grayscale(1); mix-blend-mode: multiply; opacity: .8;
  width: 190px; height: 190px;
  background-image: url("images/coffee-stain.png");
  background-size: contain; background-repeat: no-repeat;
}

/* ---- the datum composition ---------------------------------------------
   .hero's own height IS the field's height — the line sits at the box's
   bottom edge directly. An earlier version made .hero taller than the
   field with nav as a sibling after it closed, leaving a dead gap
   between the line and the nav; fixed by removing that extra height
   rather than trying to close the gap with more CSS. */
.hero{ position: relative; z-index: 1; height: 55vh; min-height: 540px; }
.hero.no-photo{ height: 26vh; min-height: 190px; }
/* The banner behind the title: the field, an optional looping video
   (assets/banner.js), and a film grain over both. */
.hero-field{ position: absolute; inset: 0; background: var(--field); overflow: hidden; }
.hero-field video, .hero-field .banner-poster{
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  /* toned like the photos: grey, multiplied into the field color, and
     kept faint so the title reads over it. --banner-video on the
     .hero-field element sets the strength (0 to 1). */
  filter: grayscale(1) contrast(.95);
  mix-blend-mode: multiply; opacity: var(--banner-video, .35);
}
.hero-field video{ opacity: 0; transition: opacity 600ms linear; }
.hero-field video.playing{ opacity: var(--banner-video, .35); }
/* Film grain: an oversized noise tile jumped around in steps, so it
   flickers like grain rather than sliding. Transform-only, so it runs
   on the compositor and costs next to nothing. */
.hero-field::after{
  content: ""; position: absolute; inset: -100%; pointer-events: none;
  background-image: url("images/grain.png"); background-size: 256px 256px;
  opacity: .13; mix-blend-mode: multiply;
  animation: kr-grain 8s steps(10) infinite;
}
@keyframes kr-grain{
  0%, 100%{ transform: translate(0, 0); }
  10%{ transform: translate(-5%, -10%); }
  20%{ transform: translate(-15%, 5%); }
  30%{ transform: translate(7%, -25%); }
  40%{ transform: translate(-5%, 25%); }
  50%{ transform: translate(-15%, 10%); }
  60%{ transform: translate(15%, 0%); }
  70%{ transform: translate(0%, 15%); }
  80%{ transform: translate(3%, 35%); }
  90%{ transform: translate(-10%, 10%); }
}
@media (prefers-reduced-motion: reduce){ .hero-field::after{ animation: none; } }
.datum{ position: absolute; left: 0; right: 0; bottom: 0; height: 1px; background: var(--ink); z-index: 2; }
.hero-photo{
  position: absolute; right: 6vw; top: 24px;
  width: 34vw; max-width: 380px; min-width: 200px;
  aspect-ratio: 4 / 5;
  /* a torn, not-quite-rectangular edge instead of a clean crop */
  clip-path: polygon(0 0, 97% 0, 100% 3%, 100% 100%, 3% 100%, 0 96%);
  z-index: 1;
}
.hero-photo img{
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: url(#duotone) contrast(1.12) saturate(0.9);
  mix-blend-mode: multiply;
}
.tape{
  position: absolute; top: -14px; left: 12%; width: 60px; height: 22px;
  background: color-mix(in srgb, var(--line) 60%, transparent);
  border-left: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  border-right: 1px solid color-mix(in srgb, var(--ink) 12%, transparent);
  transform: rotate(-4deg); z-index: 2;
}
/* Pages with a photo (About, album pages): on wider screens the photo
   hangs down across the line into the content below. */
@media (min-width: 761px){
  .hero.hang{ overflow: visible; z-index: 2; }
  .hero.hang .hero-photo{ transform: translate(-3vw, 200px); z-index: 3; }
}
.hero-title{
  position: absolute; left: 6vw; bottom: 0; margin: 0;
  /*font-family: "Moms Typewriter", "Special Elite", "Courier Prime", monospace; */
  font-family: "OldNewspaperTypes", "Special Elite", "Courier Prime", monospace;
  font-weight: 400; letter-spacing: -0.01em; line-height: 0.9;
  font-size: clamp(38px, 7vw, 100px);
  color: var(--ink);
  white-space: nowrap; max-width: 56vw; z-index: 2;
}
/* A thin blinking bar, not a solid block — the brief was to mix the
   typewriter ethos with "the reality of digital word processors," and
   a block cursor reads as an old terminal, not a modern text caret. */
/* The caret is drawn, not typed: a thin upright bar the height of the
   line, the way a text cursor looks in any word processor, rather than
   a "|" in the title's typewriter face (typewriters had no cursor).
   The "|" stays in the markup for no-CSS readers; here it's hidden and
   the box itself is the bar. overflow: hidden also makes the box sit on
   the baseline, so the bar runs from just below it to the ascenders. */
.cursor{
  display: inline-block; opacity: 0;
  width: max(2px, .028em); height: 1em; margin-left: .07em;
  vertical-align: -.16em; overflow: hidden;
  background: var(--ink); color: transparent;
}
.cursor.blink{ animation: blink 1s steps(1) infinite; }
/* Explicit stops at both halves, not just 50% — with only one keyframe
   defined, the implicit 0%/100% values fall back to whatever the
   element's opacity would be WITHOUT the animation, which is the
   inline opacity:1 the typewriter script sets while actively typing.
   That made the "blink" look permanently solid: confirmed by sampling
   computed opacity over time and seeing it never leave 1. */
@keyframes blink{ 0%, 49%{ opacity: 1; } 50%, 100%{ opacity: 0; } }
/* On desktop the title sits right on the datum line, so the caret's
   drop below the baseline read as touching the line; there it rests on
   the baseline and rises to the capitals instead. Phones keep the
   original, which already looks right with more room under the title. */
@media (min-width: 761px){
  .hero-title .cursor{ height: .74em; vertical-align: .005em; }
}
@media (prefers-reduced-motion: reduce){
  .cursor{ display: none; }
}

.site-nav{
  font-size: 13px; letter-spacing: .02em; display: flex; gap: 1.6em; flex-wrap: wrap;
  padding: 14px 6vw 18px; margin-top: 2.2vh;
  border-bottom: 1px solid var(--line); position: relative; z-index: 1;
  view-transition-name: site-nav;
}
.site-nav a{ text-decoration: none; color: var(--mut); position: relative; padding-bottom: 4px; }
.site-nav a:hover{ color: var(--ink); }
.site-nav a.cur{ color: var(--ink); }
.site-nav a.cur::after{
  content:""; position: absolute; left: -1px; right: -2px; bottom: 1px; height: 2px;
  background: var(--ink); transform: rotate(-0.7deg); transform-origin: left center;
  /* Named so the browser treats this as the same object continuing
     across a page navigation, rather than two unrelated rectangles —
     this is what makes the underline slide from its old position to
     its new one instead of just appearing in a new spot. */
  view-transition-name: nav-underline;
}
.site-nav a:focus-visible{ outline: 2px solid var(--ink); outline-offset: 3px; }

/* ---- page-to-page motion: the carriage return --------------------------
   Cross-document view transitions (Chrome, Edge, Safari 18.2+). Browsers
   without them simply navigate; nothing breaks.

   Modeled on returning a typewriter carriage, in two beats:
   1. Line feed. The old page ratchets up one line in two hard steps,
      the platen's clicks, then starts to slide right as the carriage
      is thrown.
   2. Carriage. The new page is uncovered left to right behind that
      motion, gliding in from the left and stopping hard at the margin,
      with a small knock back from the stop. That knock is the clack.
   No opacity anywhere: nothing dissolves; things move and stop.

   The nav and its underline are held separately (view-transition-name
   on .site-nav and on the current item's underline). The nav is the
   machine, not the paper, so it stays put while the sheet changes, and
   only moves if the next page's line sits higher or lower. The
   underline travels along it with the same glide and the same hard
   stop, and the new nav's highlighted item appears the moment the
   underline lands, not before.

   The title is re-typed after all this lands; typewriter.js waits on
   the transition (motion.js). --------------------------------------------- */
@view-transition{ navigation: auto; }

::view-transition-old(root){ animation: kr-linefeed 520ms both; }
::view-transition-new(root){ animation: kr-carriage 520ms both; }

@keyframes kr-linefeed{
  0%  { transform: translate(0, 0);      animation-timing-function: steps(2, jump-end); }
  26% { transform: translate(0, -26px);  animation-timing-function: cubic-bezier(.6,0,1,1); }
  100%{ transform: translate(7vw, -26px); }
}
@keyframes kr-carriage{
  0%  { clip-path: inset(0 100% 0 0); transform: translateX(-7vw); animation-timing-function: linear; }
  22% { clip-path: inset(0 100% 0 0); transform: translateX(-7vw); animation-timing-function: var(--carriage); }
  86% { clip-path: inset(0 0 0 0);    transform: translateX(0);    animation-timing-function: ease-out; }
  92% { clip-path: inset(0 0 0 0);    transform: translateX(-4px); animation-timing-function: ease-in; }
  100%{ clip-path: inset(0 0 0 0);    transform: translateX(0); }
}

/* the nav and the underline share one clock: same length, same curve */
::view-transition-group(site-nav),
::view-transition-group(nav-underline),
::view-transition-group(menu-btn){
  animation-duration: 520ms;
  animation-timing-function: var(--carriage);
}
::view-transition-old(site-nav){ animation: kr-hold-out 520ms linear both; }
::view-transition-new(site-nav){ animation: kr-hold-in 520ms linear both; }
::view-transition-old(nav-underline),
::view-transition-new(nav-underline){ animation: none; }
::view-transition-old(nav-underline){ opacity: 0; }
/* a hard swap, timed to the underline landing; not a fade */
@keyframes kr-hold-out{ 0%, 79%{ opacity: 1; } 80%, 100%{ opacity: 0; } }
@keyframes kr-hold-in { 0%, 79%{ opacity: 0; } 80%, 100%{ opacity: 1; } }

@media (prefers-reduced-motion: reduce){
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*){
    animation: none !important;
  }
}

.hero-meta{ font-size: 13px; color: var(--mut); margin: 1.4em 6vw 0; }
.hero-caption{ font-family: "Caveat", cursive; font-size: 20px; color: var(--mut); margin: .3em 6vw 0; line-height: 1.2; }

.page-body{ padding: 0 6vw 6vh; position: relative; z-index: 1; }
.content{ max-width: 64ch; margin-top: 4vh; }
.content.wide{ max-width: none; }
.content p{ margin: 0 0 1.2em; position: relative; z-index: 1; }
.content em{ font-style: italic; }

.margin-note{
  font-family: "Caveat", cursive; font-size: 21px; color: var(--note);
  position: absolute; right: -12.5em; top: .2em; width: 11.5em;
  transform: rotate(-2.2deg); line-height: 1.35; z-index: 1;
}
@media (max-width: 900px){
  .margin-note{ position: static; width: auto; margin: 1.2em 0 1.6em 0; transform: rotate(-1.1deg); font-size: 19px; }
}

.meta{ font-size: 13px; color: var(--mut); margin-top: 2em; display: flex; align-items: center; gap: 1em; flex-wrap: wrap; position: relative; z-index: 1; }
.meta a{ text-decoration: underline; text-decoration-color: var(--line); }

.stamp{
  display: inline-block; border: 2px solid var(--note); color: var(--note);
  font-weight: 700; letter-spacing: .09em; text-transform: uppercase; font-size: 11.5px;
  padding: .32em .6em; transform: rotate(-3deg); opacity: .88; white-space: nowrap;
}
/* Where to hear the record: typed labels with an icon, boxed like a
   button so it's plain they're for listening, not just references. */
.listen, .content .listen{ display: flex; flex-wrap: wrap; gap: 10px 12px; margin: 2.6em 0 0; position: relative; z-index: 1; }
/* Set like the controls on a piece of equipment: the narrow grotesque
   the binder tab uses, small, medium weight. Boxed so they read as
   things you press, with an icon for what happens when you do. */
.listen-link{
  display: inline-flex; align-items: center; gap: .5em;
  padding: .42em .8em .42em .6em; border: 1.25px solid var(--ink);
  font-family: "Archivo Narrow", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  font-weight: 600; font-size: 13.5px; letter-spacing: .03em; line-height: 1.2;
  color: var(--ink); text-decoration: none; background: var(--field);
  transition: background-color 140ms linear, color 140ms linear;
}
.listen-link svg{ width: 17px; height: 17px; flex: none; }
.listen-link:hover, .listen-link:focus-visible{ background: var(--ink); color: var(--field); }
.listen-link:focus-visible{ outline: 2px solid var(--ink); outline-offset: 3px; }


/* return from an album page to the albums index */
.back-link{
  display: inline-flex; align-items: baseline; gap: .45em; margin-top: 2vh;
  font-size: 13px; color: var(--mut); text-decoration: none; position: relative; z-index: 1;
}
.back-link span{ display: inline-block; transition: transform 180ms cubic-bezier(.2,.8,.2,1); }
.back-link:hover{ color: var(--ink); }
.back-link:hover span{ transform: translateX(-4px); }
.back-link:focus-visible{ outline: 2px solid var(--ink); outline-offset: 3px; }

/* ---- tracklist ----------------------------------------------------------*/
.tracklist{
  columns: 2; column-gap: 2.4em; list-style: none; margin: 1.2em 0 0; padding: 0;
  font-size: 15px; max-width: 60ch;
}
.tracklist li{ break-inside: avoid; display: grid; grid-template-columns: 2.2em 1fr; margin-bottom: .35em; }
.tracklist li i{ font-style: normal; color: var(--mut); }
@media (max-width: 640px){ .tracklist{ columns: 1; } }

/* ---- albums index: covers as a list, newest first -----------------------*/
/* Albums index: covers only, large. The title surfaces inside the cover
   on hover: a quiet ink shade rises from the bottom edge and the title
   slides up into it, set in the book serif with the catalog number
   under it in the narrow label face. */
.album-grid{
  list-style: none; margin: 3vh 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: 4vw; max-width: 1100px;
}
.album-grid li{ margin: 0; }
.album-card{ display: block; text-decoration: none; color: inherit; }
.album-card-cover{
  position: relative; display: block; aspect-ratio: 1 / 1; overflow: hidden;
  clip-path: polygon(0 0, 97% 0, 100% 3%, 100% 100%, 3% 100%, 0 97.5%);
  background: var(--field);
}
.album-card-cover img{
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: url(#duotone) contrast(1.12) saturate(0.9); mix-blend-mode: multiply;
  transition: transform 700ms cubic-bezier(.2,.7,.2,1);
}
.album-card-cover::after{
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, color-mix(in srgb, var(--ink) 72%, transparent) 0%, color-mix(in srgb, var(--ink) 30%, transparent) 30%, transparent 58%);
  opacity: 0; transition: opacity 380ms ease;
}
.album-card-caption{
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 1;
  display: flex; flex-direction: column; gap: .3em; padding: 0 22px 20px;
  color: var(--field);
  opacity: 0; transform: translateY(10px);
  transition: opacity 380ms ease, transform 480ms cubic-bezier(.2,.7,.2,1);
}
.album-card-title{ font-style: italic; font-size: 24px; line-height: 1.15; }
.album-card-meta{
  font-family: "Archivo Narrow", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  font-weight: 500; font-size: 11px; letter-spacing: .14em; text-transform: uppercase; opacity: .8;
}
.album-card:hover .album-card-cover::after, .album-card:focus-visible .album-card-cover::after{ opacity: 1; }
.album-card:hover .album-card-caption, .album-card:focus-visible .album-card-caption{ opacity: 1; transform: none; }
.album-card:hover .album-card-cover img, .album-card:focus-visible .album-card-cover img{ transform: scale(1.025); }
.album-card:focus-visible{ outline: 2px solid var(--ink); outline-offset: 5px; }
/* no hover on touch screens: keep the caption showing, softly */
@media (hover: none){
  .album-card-cover::after{ opacity: .85; }
  .album-card-caption{ opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce){
  .album-card-cover img, .album-card-caption{ transition: none; }
}

/* ---- clickable tracklist + lyrics iframe ---------------------------------*/
.tracklist button.track{
  font: inherit; color: inherit; background: none; border: 0; padding: 0;
  text-align: left; cursor: pointer; text-decoration: underline; text-decoration-color: transparent;
}
.tracklist button.track:hover,
.tracklist button.track:focus-visible{ text-decoration-color: var(--line); }
.tracklist li.open button.track{ color: var(--ink); font-weight: 700; }
/* Album page: tracklist left, lyrics right, liner notes underneath. */
.album-body{
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr);
  gap: 3.5vw; align-items: start; margin-top: 1.6em;
}
.album-body .tracklist{ columns: 1; margin-top: 0; max-width: none; }
.album-body .tracklist li{ margin-bottom: .5em; }
/* the lyrics stay beside you while you scroll the tracklist. The slot
   is always the open panel's full height (--lyrics-h: the iframe plus
   the Close bar), open or not, so nothing below it (the liner notes)
   moves when a song is opened or closed. */
.lyrics-slot{ position: sticky; top: 16px; --lyrics-h: 474px; min-height: var(--lyrics-h); }
.lyrics-slot .lyrics-empty{
  margin: 0; padding: 20px 22px; border: 1px dashed var(--line);
  color: var(--mut); font-size: 15px; min-height: var(--lyrics-h);
}
.lyrics-slot:has(.lyrics-panel.open) .lyrics-empty{ display: none; }
.lyrics-panel{
  display: none; margin: 0; border: 1px solid var(--line);
  background: var(--field);
}
.lyrics-panel.open{ display: block; animation: kr-unroll 420ms both; }
.lyrics-panel.open.closing{ animation: kr-rollup 260ms cubic-bezier(.6,0,1,.4) both; }
/* opening: the sheet unrolls downward and knocks to a stop */
@keyframes kr-unroll{
  0%  { clip-path: inset(0 0 100% 0); transform: translateY(-6px); animation-timing-function: var(--carriage); }
  84% { clip-path: inset(0 0 0 0);    transform: translateY(0);    animation-timing-function: ease-out; }
  92% { clip-path: inset(0 0 0 0);    transform: translateY(3px);  animation-timing-function: ease-in; }
  100%{ clip-path: inset(0 0 0 0);    transform: translateY(0); }
}
/* closing: pulled back up out of the machine */
@keyframes kr-rollup{
  0%  { clip-path: inset(0 0 0 0);    transform: translateY(0); }
  100%{ clip-path: inset(0 0 100% 0); transform: translateY(-14px); }
}
@media (prefers-reduced-motion: reduce){
  .lyrics-panel.open, .lyrics-panel.open.closing{ animation: none; }
}
.lyrics-panel iframe{ display: block; width: 100%; height: 440px; border: 0; }

/* Liner notes: announced by a rule and a heading, then set a size
   smaller than the tracklist, in two columns on wide screens, the way
   they run down the back of a sleeve. */
.liner{ margin-top: 9vh; position: relative; z-index: 1; }
.liner-head{
  display: flex; align-items: baseline; justify-content: space-between; gap: 1em; flex-wrap: wrap;
  border-top: 1px solid var(--ink); padding-top: .9em; margin-bottom: 1.6em;
}
.liner-head h2{
  margin: 0; font-weight: 400; line-height: 1;
  font-family: "OldNewspaperTypes", "Special Elite", "Courier Prime", monospace;
  font-size: clamp(28px, 3vw, 38px);
}
.liner-of{ font-size: 13px; color: var(--mut); }
.liner-of em{ color: var(--ink); }
.liner-body{ font-size: 14px; line-height: 1.7; max-width: 1100px; }
.liner-body p{ margin: 0 0 1.05em; hyphens: auto; }
.liner-body .liner-by{ font-style: italic; color: var(--mut); text-align: right; margin-top: 1.4em; }
@media (min-width: 1000px){
  .liner-body{ columns: 2; column-gap: 3.5vw; }
  .liner-body p{ break-inside: avoid-column; }
}
.lyrics-close{
  display: block; width: 100%; text-align: right; padding: 8px 14px;
  font-size: 12px; color: var(--mut); background: none; border: 0;
  border-top: 1px solid var(--line); cursor: pointer; font-family: inherit;
}
.lyrics-close:hover{ color: var(--ink); }

/* ---- songs page: table + same-document lyric pane ------------------------
   The pane is plain DOM, not an iframe — see the comment in songs.html
   for why. Because it's just part of this page, "blending in" is free:
   it already uses the same CSS, no separate styling to keep in sync. */
.songs-layout{ display: grid; grid-template-columns: minmax(0,1.3fr) minmax(0,1fr); gap: 3vw; align-items: start; }
.songs-table{ width: 100%; border-collapse: collapse; font-size: 15px; margin-top: 1.6vh; }
.songs-table th{
  text-align: left; font-size: 12px; letter-spacing: .04em; color: var(--mut);
  font-weight: 400; padding: 0 .8em .5em 0; border-bottom: 1px solid var(--line);
}
.sort-arrow{
  appearance: none; -webkit-appearance: none; border: 0; background: none; padding: 0;
  margin: 0; color: inherit; font: inherit; letter-spacing: inherit; cursor: pointer;
  display: inline-flex; align-items: baseline; gap: .45em; text-align: left;
}
.sort-arrow:hover,
.sort-arrow:focus-visible,
.sort-arrow.active{ color: var(--ink); }
.sort-arrow:focus-visible{ outline: 1px solid var(--ink); outline-offset: 3px; }
.sort-indicator{
  display: inline-block; min-width: 1em; text-align: center; font-size: 13px;
  line-height: 1; color: var(--mut); transform: translateY(.03em);
}
.sort-arrow.active .sort-indicator{ color: var(--ink); }
.songs-table td{ padding: .55em .8em .55em 0; border-bottom: 1px solid var(--line); vertical-align: top; }
.songs-table tbody tr{ cursor: pointer; }
.songs-table tbody tr:hover td{ color: var(--ink); }
.songs-table tbody tr.sel td{ color: var(--ink); font-weight: 700; }
.songs-table td.song-album{ color: var(--mut); }
.songs-table tbody tr:hover td.song-album,
.songs-table tbody tr.sel td.song-album{ color: var(--mut); font-weight: 400; }

.lyric-pane{
  position: relative; z-index: 1;
  border: 1px solid var(--line); background: var(--field);
  padding: 20px 22px; min-height: 260px;
}
.lyric-pane:focus{ outline: none; }
.lyric-pane h2{
  font-family: "Moms Typewriter", "Special Elite", "Courier Prime", monospace; font-weight: 400;
  font-size: 22px; margin: 0 0 .6em; padding-right: 3.5em;
}
.lyric-pane h2.has-credit{ margin-bottom: .05em; }
/* the subtitle: credits, dates, sources */
.lyric-credit{
  margin: 0 0 1.3em; font-size: 12px; line-height: 1.35;
  color: color-mix(in srgb, var(--mut) 78%, var(--field));
}
.lyric-pane .lyric-body{ white-space: pre-line; font-size: 15px; line-height: 1.7; }
.lyric-pane .cur{ display: inline-block; opacity: 0; }
.lyric-pane .cur.blink{ animation: blink 1s steps(1) infinite; }
.lyric-close{ display: none; }

/* The pane and its tab travel together. On wide screens the pair stays
   where it is until you scroll, then follows you down (sticky); top
   leaves room for the tab above the pane. */
.lyric-stack{ position: sticky; top: 16px; padding-top: 30px; margin-top: -30px; }
.lyric-backdrop{ display: none; }

/* The tab: an index divider tucked behind the pane's top edge, labeled
   with the song's album. Lifts on hover as if you were about to pull it. */
.album-tab{
  position: absolute; z-index: 0; top: 4px; right: 22px;
  height: 34px; padding: 7px 26px 0;
  background: var(--line); /* shows as the tab's hairline edge */
  clip-path: polygon(9px 0, calc(100% - 9px) 0, 100% 100%, 0 100%);
  /* printed like a divider insert: a narrow grotesque, small caps-height
     capitals, tracked out; nothing typewritten about it */
  font-family: "Archivo Narrow", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  font-weight: 600; font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase;
  line-height: 20px; color: var(--mut); text-decoration: none; white-space: nowrap;
  transition: transform 200ms cubic-bezier(.2,.8,.2,1.3), color 120ms linear;
}
.album-tab::before{
  content: ""; position: absolute; inset: 1px 1.5px 0; z-index: -1;
  clip-path: polygon(8.5px 0, calc(100% - 8.5px) 0, 100% 100%, 0 100%);
  background: color-mix(in srgb, var(--field) 72%, var(--line));
  transition: background-color 120ms linear;
}
.album-tab span{ position: relative; }
.album-tab:hover, .album-tab:focus-visible{ transform: translateY(-6px); color: var(--ink); }
.album-tab:hover::before, .album-tab:focus-visible::before{ background: var(--field); }
.album-tab:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce){ .album-tab{ transition: none; } }

@media (max-width: 900px){
  .songs-layout{ grid-template-columns: 1fr; }

  /* the pane becomes a popup; hidden until a song is chosen */
  .lyric-stack{ display: none; position: fixed; z-index: 70; top: auto; padding-top: 30px;
    left: 14px; right: 14px; bottom: calc(env(safe-area-inset-bottom, 0px) + 14px);
    max-height: calc(100dvh - env(safe-area-inset-top, 0px) - 84px);
  }
  .lyric-stack.popup{ display: flex; flex-direction: column; animation: kr-feed-in 460ms both; }
  .lyric-stack.popup.closing{ animation: kr-feed-out 240ms cubic-bezier(.6,0,1,.4) both; }
  .lyric-stack .lyric-pane{ min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 22px 20px 28px; }
  .lyric-close{
    display: block; position: absolute; top: 10px; right: 8px;
    font: inherit; font-size: 13px; color: var(--mut); background: none; border: 0;
    height: 40px; padding: 0 10px; cursor: pointer;
  }
  .lyric-close:hover{ color: var(--ink); }
  .lyric-close:focus-visible{ outline: 2px solid var(--ink); }
  .album-tab{ left: 18px; right: auto; }

  .lyric-backdrop{
    display: block; position: fixed; inset: 0; z-index: 65;
    background: var(--ink); opacity: 0; pointer-events: none; transition: opacity 240ms linear;
  }
  .lyrics-open .lyric-backdrop{ opacity: .3; pointer-events: auto; }
  /* lift the page body's layer above the header and menu button while
     the popup is up, so the backdrop covers everything */
  .lyrics-open .page-body{ z-index: 66; }
  html.lyrics-open, html.lyrics-open body{ overflow: hidden; }
}
@keyframes kr-feed-in{
  0%  { transform: translateY(105%); animation-timing-function: var(--carriage); }
  84% { transform: translateY(0);    animation-timing-function: ease-out; }
  91% { transform: translateY(5px);  animation-timing-function: ease-in; }
  100%{ transform: translateY(0); }
}
@keyframes kr-feed-out{ to{ transform: translateY(110%); } }
@media (prefers-reduced-motion: reduce){
  .lyric-stack.popup, .lyric-stack.popup.closing{ animation: none; }
}

/* ---- videos --------------------------------------------------------------*/
.video-grid, .press-list{ margin-top: 2vh; }
.video-grid{ display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 2.2em 2vw; }
.video-frame{ position: relative; aspect-ratio: 16 / 9; background: var(--field); }
.video-frame iframe{ position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.video-caption{ margin-top: .6em; font-size: 15px; color: var(--mut); }
.empty-note{ color: var(--mut); font-size: 15px; }
@media (max-width: 700px){ .video-grid{ grid-template-columns: 1fr; } }

/* ---- press ----------------------------------------------------------------*/
.press-list{ list-style: none; margin: 0; padding: 0; }
.press-row{ display: grid; grid-template-columns: minmax(0,1fr) auto; gap: 1em; padding: 1.1em 0; border-top: 1px solid var(--line); font-size: 15px; }
.press-row:first-child{ border-top: none; }
.press-link{ display: flex; gap: 1.6em; align-items: flex-start; text-decoration: none; color: inherit; }
.press-text{ display: block; max-width: 56ch; }
.press-pub{ color: var(--mut); display: block; font-size: 13px; margin-bottom: .2em; }
.press-title{ display: block; font-size: 19px; line-height: 1.3; }
.press-link:hover .press-title{ text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }
/* the subtitle: what kind of piece it is, in a line */
.press-kind{ display: block; margin-top: .45em; font-size: 14px; line-height: 1.45; color: var(--mut); }
.press-kind em{ color: var(--ink); }
.press-date{ color: var(--mut); white-space: nowrap; font-size: 13px; padding-top: .15em; }

/* the clipping: duotoned into the tone, torn corner, taped down */
.press-img{
  position: relative; flex: 0 0 auto; width: 210px; aspect-ratio: 3 / 2;
  transform: rotate(-1.2deg); margin-top: .3em;
}
.press-img img{
  width: 100%; height: 100%; object-fit: cover; display: block; background: var(--field);
  clip-path: polygon(0 0, 96% 0, 100% 5%, 100% 100%, 3% 100%, 0 95%);
  filter: url(#duotone) contrast(1.1); mix-blend-mode: multiply;
}
.press-img .tape{ top: -11px; left: 14%; width: 52px; }
@media (max-width: 640px){
  .press-row{ grid-template-columns: 1fr; gap: .4em; }
  .press-link{ flex-direction: column; gap: 1.1em; }
  .press-img{ width: min(100%, 320px); }
  .press-date{ order: -1; }
}

/* ---- contact ----------------------------------------------------------- */
.contact-block{ margin-bottom: 2em; }
.contact-block h2{ font-size: 13px; letter-spacing: .04em; color: var(--mut); font-weight: 400; margin: 0 0 .4em; }
.contact-block p{ margin: 0; font-size: 16px; }

/* ---- footer: social links -----------------------------------------------*/
.rule{ border: 0; border-top: 1px solid var(--line); margin: 5vh 6vw 0; position: relative; z-index: 1; }
.site-footer{ font-size: 12.5px; color: var(--mut); padding: 1.2vh 6vw 6vh; display: flex; gap: 1.6em; flex-wrap: wrap; position: relative; z-index: 1; }
.site-footer a{ text-decoration: none; }
.site-footer a:hover{ color: var(--ink); }
/* Footer icons: drawn from the SVGs in assets/images/icons as masks, so
   they're painted in the text color (the muted grey, ink on hover) and
   take every tone, at the size of the lowercase letters. */
.footer-link{ display: inline-flex; align-items: center; gap: .5em; }
.ico{
  display: inline-block; width: 1.1em; height: 1.1em; flex: none;
  background: currentColor; opacity: .75;
  -webkit-mask: var(--ico) center / contain no-repeat;
          mask: var(--ico) center / contain no-repeat;
  transition: opacity 140ms linear;
}
a:hover > .ico{ opacity: 1; }
.ico-kayfabe  { --ico: url("images/icons/kayfabe.svg"); }
.ico-youtube  { --ico: url("images/icons/youtube.svg"); }
.ico-instagram{ --ico: url("images/icons/instagram.svg"); -webkit-mask-size: 88%; mask-size: 88%; }
/* one box size for all three, so the labels line up */
.ico{ width: 1.15em; height: 1.15em; }
.copyline{ margin: 2.2em 6vw 0; font-size: 13px; color: var(--mut); position: relative; z-index: 1; }

/* ---- responsive: the datum composition doesn't fit a narrow screen —
   there's no room for a line-with-field-above AND a right-side photo at
   any sensible size, so it becomes a plain stack: title, then photo,
   then nav, in normal flow. Color moves onto the elements that actually
   have content (an empty decorative div with padding rendered as its
   own dead rectangle in an earlier round of this project — not
   repeating that). ------------------------------------------------------*/
@media (max-width: 760px){
  /* Order on a phone: title on its field, the line, then the photo, its
     caption directly under it, then the one-line description, then the
     page. The DOM order is built for the desktop composition, so flex
     order puts things back in reading order here. */
  .site{ display: flex; flex-direction: column; }
  .site > .hero{ order: 0; }
  .site > .hero-caption{ order: 1; }
  .site > .site-nav{ order: 2; }
  .site > .hero-meta{ order: 3; }
  .site > .page-body{ order: 4; }
  .site > .rule{ order: 5; }
  .site > .site-footer{ order: 6; }

  /* a one-column grid: the banner field shares the first cell with the
     title, so the grain (and any video) sits behind it here too */
  .hero, .hero.no-photo{ position: relative; height: auto; min-height: 0; display: grid; grid-template-columns: 100%; }
  .hero-field{ grid-area: 1 / 1; position: relative; inset: auto; }
  .hero-title{
    grid-area: 1 / 1; z-index: 1;
    position: relative; left: auto; bottom: auto; background: none;
    padding: 9vh 6vw 3.2vh; margin: 0; font-size: clamp(44px, 14vw, 64px);
    max-width: 100%; white-space: normal;
  }
  .datum{ grid-area: 2 / 1; position: static; }
  .hero-photo{
    grid-area: 3 / 1; position: relative; right: auto; top: auto;
    width: 74vw; max-width: 360px; min-width: 0;
    margin: 30px 0 0 6vw; transform: rotate(-1.1deg);
  }
  .hero-caption{ margin: .5em 6vw 0; font-size: 19px; }
  .hero-meta{ margin: 1.8em 6vw 0; }
  .site-nav{ margin-top: 3vh; }
  .js .site-nav{ display: none; }
  .content{ margin-top: 3vh; }
  .page-body{ overflow-x: clip; } /* the stain may hang off the edge, never scroll it */
  .stain{ right: -3.5em !important; top: -2.2em !important; width: 150px; height: 150px; }
  .album-card-title{ font-size: 21px; }
  .lyrics-panel iframe{ height: 380px; }
  .album-body{ grid-template-columns: 1fr; gap: 1.4em; }
  .lyrics-slot{ position: static; min-height: 0; }
  .lyrics-empty{ display: none; }
}

/* Keep the footer links on the left and anchor the Kayfabe mark to the right. */
.site-footer {
  display: flex;
  align-items: center;
}
.site-footer .footer-logo {
  margin-left: auto;
  display: block;
  line-height: 0;
}
.site-footer .footer-logo img {
  display: block;
  width: 50px;
  height: 50px;
  object-fit: contain;
}
@media (max-width: 700px) {
  .site-footer .footer-logo img {
    width: 58px;
    height: 58px;
  }
}

/* ---- mobile menu ---------------------------------------------------------
   Built by assets/menu.js from the page's own nav and footer links. Only
   at the mobile breakpoint, and only when scripts run (html.js); without
   JS the plain nav stays in the page. The drawer arrives the way pages
   do: a carriage glide from the right and a knock at the stop. */
.menu-btn, .menu-backdrop, .menu-drawer{ display: none; }

@media (max-width: 760px){
  .js .menu-btn{
    display: flex; flex-direction: column; justify-content: center; align-items: flex-start; gap: 5px;
    position: fixed; z-index: 50;
    top: calc(env(safe-area-inset-top, 0px) + 14px); right: 14px;
    width: 44px; height: 44px; padding: 0 11px;
    background: var(--field); border: 1px solid var(--line); cursor: pointer;
    view-transition-name: menu-btn;
  }
  /* three typed lines, the last one short: a paragraph, not a symbol */
  .menu-btn span{ display: block; height: 1.5px; width: 20px; background: var(--ink); }
  .menu-btn span:last-child{ width: 12px; }
  .menu-btn:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

  .js .menu-backdrop{
    display: block; position: fixed; inset: 0; z-index: 55;
    background: var(--ink); opacity: 0; pointer-events: none;
    transition: opacity 240ms linear;
  }
  .menu-open .menu-backdrop{ opacity: .3; pointer-events: auto; }

  .js .menu-drawer{
    display: flex; flex-direction: column;
    position: fixed; top: 0; right: 0; bottom: 0; z-index: 60;
    width: min(84vw, 340px);
    padding-top: env(safe-area-inset-top, 0px);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--paper);
    border-left: 1px solid var(--line);
    overflow-y: auto; overscroll-behavior: contain;
    transform: translateX(102%); visibility: hidden;
    transition: transform 220ms cubic-bezier(.6,0,1,.4), visibility 0s linear 220ms;
  }
  .menu-open .menu-drawer{
    visibility: visible; transform: none; transition: none;
    animation: kr-drawer 460ms both;
  }
  .menu-drawer{
    background-image: url("images/paper.jpg"); background-size: 1024px 1024px;
    background-blend-mode: multiply;
  }
  .menu-drawer > *{ position: relative; }

  .menu-head{
    display: flex; justify-content: flex-end; align-items: center;
    height: 72px; padding: 0 14px; background: var(--field);
    border-bottom: 1px solid var(--ink);
  }
  .menu-close{
    font: inherit; font-size: 13px; color: var(--mut); background: none; border: 0;
    height: 44px; padding: 0 8px; cursor: pointer;
  }
  .menu-close:hover{ color: var(--ink); }
  .menu-close:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

  .menu-pages{ padding: 26px 28px 22px; }
  .menu-pages a{
    display: block; width: fit-content; position: relative;
    font-family: "OldNewspaperTypes", "Special Elite", "Courier Prime", monospace;
    font-size: 30px; line-height: 1.2; padding: .12em 0;
    color: var(--mut); text-decoration: none;
  }
  .menu-pages a.cur{ color: var(--ink); }
  .menu-pages a.cur::after{
    content: ""; position: absolute; left: -1px; right: -2px; bottom: .12em; height: 2px;
    background: var(--ink); transform: rotate(-0.7deg); transform-origin: left center;
  }
  .menu-pages a:focus-visible, .menu-out a:focus-visible{ outline: 2px solid var(--ink); outline-offset: 3px; }

  .menu-out{ border-top: 1px solid var(--line); margin: 0 28px; padding: 16px 0; }
  .menu-out a{ display: flex; align-items: center; gap: .6em; font-size: 15px; line-height: 2.1; color: var(--mut); text-decoration: none; }
  .menu-out a:hover{ color: var(--ink); }

  .menu-logo{ margin-top: auto; padding: 22px 28px 28px; }
  .menu-logo a{ display: block; width: 50px; line-height: 0; }
  .menu-logo img{ width: 50px; height: 50px; object-fit: contain; }

  html.menu-open, html.menu-open body{ overflow: hidden; }
}
@keyframes kr-drawer{
  0%  { transform: translateX(102%); animation-timing-function: var(--carriage); }
  84% { transform: translateX(0);    animation-timing-function: ease-out; }
  91% { transform: translateX(5px);  animation-timing-function: ease-in; }
  100%{ transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce){
  .menu-open .menu-drawer{ animation: none; }
  .js .menu-drawer, .js .menu-backdrop{ transition: none; }
}

/* ---- the Index: news column ------------------------------------------------
   The counterweight to the board: a straight, pinned sheet in a fixed
   order, beside slips that move every visit. On wide screens it holds
   its place as you scroll down the board. */
.index-layout{ display: grid; grid-template-columns: minmax(230px, 22%) minmax(0, 1fr); gap: 4vw; align-items: start; margin-top: 5vh; }
.index-layout .board{ margin-top: 0; }
.news{
  position: sticky; top: 16px; z-index: 2;
  background: var(--field); border-top: 1px solid var(--ink);
  padding: 16px 20px 6px;
}
.news-head{
  margin: 0 0 .5em; font-weight: 400;
  font-family: "OldNewspaperTypes", "Special Elite", "Courier Prime", monospace;
  font-size: 28px; line-height: 1;
}
.news-list{ list-style: none; margin: 0; padding: 0; }
.news-list li{ border-top: 1px solid var(--line); }
.news-item{ display: block; padding: .8em 0 .9em; color: inherit; text-decoration: none; }
.news-item time{ display: block; font-size: 12.5px; color: var(--mut); margin-bottom: .2em; }
.news-title{
  display: block; font-family: "Moms Typewriter", "Special Elite", "Courier Prime", monospace;
  font-size: 18px; line-height: 1.2;
}
.news-text{ display: block; margin-top: .35em; font-size: 14px; line-height: 1.5; color: var(--ink); }
a.news-item:hover .news-title{ text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }
a.news-item:focus-visible{ outline: 2px solid var(--ink); outline-offset: 3px; }
@media (max-width: 860px){
  .index-layout{ grid-template-columns: 1fr; gap: 5vh; }
  .news{ position: static; }
}

/* ---- the Index board -------------------------------------------------------
   Positions, widths, and tilts are set by assets/index.js; this only
   styles the fragments themselves. */
.board{ list-style: none; margin: 5vh 0 0; padding: 0; position: relative; min-height: 50vh; }
.frag-item{ position: absolute; top: 0; left: 0; }
.board:not(.laid) .frag-item{ visibility: hidden; }

.frag{
  display: block; position: relative; color: inherit; text-decoration: none;
  transform: rotate(var(--r, 0deg));
  transition: transform 180ms cubic-bezier(.2,.8,.2,1);
}
.frag-item:hover, .frag-item:focus-within{ z-index: 30 !important; }
.frag:hover, .frag:focus-visible{ transform: rotate(calc(var(--r, 0deg) * .3)) translateY(-3px); }
.frag:focus-visible{ outline: 2px solid var(--ink); outline-offset: 5px; }
@media (prefers-reduced-motion: reduce){ .frag{ transition: none; } }

.frag .tape{ top: -12px; left: 18%; }
.frag-img{
  display: block; position: relative; aspect-ratio: 1 / 1; background: var(--field);
  clip-path: polygon(0 0, 96% 0, 100% 4%, 100% 100%, 4% 100%, 0 97%);
}
.frag-img img{
  width: 100%; height: 100%; object-fit: cover; display: block;
  filter: url(#duotone) contrast(1.12) saturate(0.9); mix-blend-mode: multiply;
}
.frag-photo .frag-img{ aspect-ratio: 4 / 5; }
.frag-pressimg .frag-img{ aspect-ratio: 3 / 2; }
.frag-video .frag-img{ aspect-ratio: 16 / 9; clip-path: none; background: var(--ink); }
.frag-video .play{
  position: absolute; left: 16px; bottom: 14px; width: 0; height: 0;
  border-left: 16px solid var(--field); border-top: 10px solid transparent; border-bottom: 10px solid transparent;
}
.frag-cap{ display: block; margin-top: .6em; font-size: 14px; color: var(--mut); line-height: 1.4; }
.frag-cap em{ color: var(--ink); }
.frag-hand{ display: block; margin-top: .35em; font-family: "Caveat", cursive; font-size: 20px; color: var(--mut); line-height: 1.2; }

.frag-slip{
  /* torn edges are drawn per slip by index.js; this is the fallback */
  background: var(--field); padding: 15px 22px 14px 20px;
  clip-path: polygon(0 0, 100% 0, 99.2% 22%, 100% 47%, 99.4% 76%, 100% 100%, 0 100%);
}
.slip-title{
  display: block; font-family: "Moms Typewriter", "Special Elite", "Courier Prime", monospace;
  font-size: 21px; line-height: 1.18;
}
.slip-lyric{ display: block; font-style: italic; font-size: 19px; line-height: 1.4; text-wrap: pretty; }
.slip-meta{ display: block; margin-top: .6em; font-size: 12.5px; color: var(--mut); }
.frag-press .slip-meta{ margin: 0 0 .45em; }
.frag-slip:hover .slip-title, .frag-slip:hover .slip-lyric{ text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 3px; }

.frag-bio{ font-size: clamp(20px, 2vw, 26px); line-height: 1.38; }
.frag-bio:hover{ text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 4px; }
.frag-note{ font-family: "Caveat", cursive; font-size: 24px; line-height: 1.3; color: var(--note); }
.frag-stamp{ width: fit-content; }
.frag-stamp .stamp{ transform: none; font-size: 15px; padding: .4em .75em; }
/* scraps: typed notes and loose pictures, not links */
.frag-scrap{
  font-family: "Moms Typewriter", "Special Elite", "Courier Prime", monospace;
  font-size: 15.5px; line-height: 1.45; cursor: default;
}
.frag-scrapimg{ cursor: default; }
div.frag:hover{ transform: rotate(var(--r, 0deg)); }
.frag-preview{ font-size: 11px; border: 1px dashed var(--mut); padding: 0 .35em; margin-left: .3em; }

.board-plain{ list-style: none; padding: 0; margin: 5vh 0 0; font-size: 18px; line-height: 2; }

/* ---- the Index on phones: lock-screen banner (assets/home-lock.js) ---------
   html.home-lock: the banner fills 80% of the screen, title low on it.
   html.home-anim: present only while it's changing size, so the resize
   animates but ordinary layout changes don't. */
@media (max-width: 760px){
  .hero-home{ grid-template-rows: 1fr auto; }
  .hero-home .hero-title{ align-self: end; }
  .home-lock .hero-home{ height: 80svh; }
  .home-lock .hero-home .hero-title{ padding-bottom: 74px; }
  .home-anim .hero-home{ transition: height 560ms var(--carriage); }
  .home-anim .hero-home .hero-title{ transition: padding-bottom 560ms var(--carriage); }
  .home-lock body{ overscroll-behavior-y: none; }

  .home-arrows{
    position: absolute; left: 50%; bottom: 16px; z-index: 2;
    transform: translateX(-50%);
    display: flex; flex-direction: column; align-items: center; gap: 0;
    width: 64px; height: 44px; padding: 6px 0 0; border: 0; background: none; cursor: pointer;
    color: var(--ink); opacity: 0; pointer-events: none;
    transition: opacity 700ms ease;
  }
  .home-hint .home-arrows{ opacity: .6; pointer-events: auto; }
  .home-arrows svg{
    width: 22px; height: 10px; fill: none; stroke: currentColor;
    stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round;
    animation: kr-chevron 2s cubic-bezier(.45,0,.35,1) infinite;
  }
  .home-arrows svg + svg{ margin-top: -2px; animation-delay: .18s; }
  .home-arrows:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; opacity: .8; }
}
.home-arrows{ display: none; }
@media (max-width: 760px){ .home-arrows{ display: flex; } }
@keyframes kr-chevron{
  0%       { transform: translateY(-3px); opacity: 0; }
  35%      { opacity: 1; }
  78%, 100%{ transform: translateY(5px);  opacity: 0; }
}
@media (prefers-reduced-motion: reduce){
  .home-anim .hero-home, .home-anim .hero-home .hero-title{ transition: none; }
  .home-arrows svg{ animation: none; opacity: 1; }
}
