/* Chasing Arcadia.
 *
 * A dark ground, because this is a rock band's archive and every photograph on
 * it was shot on a stage. Two typefaces would be one too many for 33 pages, so
 * the system stack does the work and the display weight carries the headings.
 *
 * Theme-aware is deliberately not attempted: the site commits to one look
 * rather than trying to be legible over a light ground it was never designed
 * for, so the colours are declared once and painted explicitly.
 */
/* Anton, SIL Open Font Licence 1.1 (src/fonts/OFL.txt). One file, one weight,
   headings only. A band's name set in the system UI font is the single thing
   that made this read as a CMS rather than a record sleeve, and a 56 KB
   download fixes it. swap, so the text is never invisible while it loads. */
@font-face {
  font-family: "Anton";
  src: url("/fonts/anton.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

:root {
  --ink: #ece8e3;
  --ink-dim: #a29c95;
  --ground: #121114;
  --ground-raised: #1c1a1f;
  --line: #2e2b33;
  --accent: #d8813f;
  --accent-quiet: #8a5527;
  --measure: 34rem;
  --wide: 68rem;
  --sans: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --display: "Anton", "Haettenschweiler", "Arial Narrow Bold", var(--sans);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font: 400 clamp(1rem, 0.96rem + 0.2vw, 1.0625rem)/1.65 var(--sans);
  -webkit-font-smoothing: antialiased;
}

.skip {
  position: absolute; left: -9999px;
  background: var(--accent); color: #17130f; padding: .6rem 1rem; z-index: 10;
}
.skip:focus { left: 1rem; top: 1rem; }

a { color: var(--accent); text-underline-offset: .18em; }
a:hover { color: var(--ink); }

img { max-width: 100%; height: auto; display: block; }

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

.masthead {
  display: flex; flex-wrap: wrap; gap: 1rem 2rem;
  align-items: baseline; justify-content: space-between;
  max-width: var(--wide); margin: 0 auto; padding: 1.75rem 1.25rem 1.25rem;
  border-bottom: 1px solid var(--line);
}
.wordmark {
  margin: 0; font-family: var(--display); font-weight: 400;
  font-size: 1.6rem; letter-spacing: .02em; text-transform: uppercase;
}
.wordmark a { color: var(--ink); text-decoration: none; }
.masthead nav ul {
  display: flex; flex-wrap: wrap; gap: 0 1.25rem;
  list-style: none; margin: 0; padding: 0; font-size: .9375rem;
}
.masthead nav a { color: var(--ink-dim); text-decoration: none; }
.masthead nav a:hover, .masthead nav [aria-current="page"] { color: var(--accent); }

/* --- prose -------------------------------------------------------------- */

.prose { max-width: var(--wide); margin: 0 auto; padding: 2.5rem 1.25rem 4rem; }
.prose h1 {
  font-family: var(--display); font-weight: 400; text-transform: uppercase;
  font-size: clamp(2.2rem, 1.5rem + 3vw, 3.8rem);
  line-height: 1; letter-spacing: .01em; margin: 0 0 1.25rem;
}
.prose h2 { font-size: 1.4rem; line-height: 1.25; margin: 2.5rem 0 .75rem; }
.prose h3 { font-size: 1.15rem; margin: 2rem 0 .5rem; }
.prose p, .prose li { max-width: var(--measure); }
.prose > p:first-of-type { font-size: 1.0625em; color: var(--ink); }
.dateline { color: var(--ink-dim); font-size: .9375rem; margin-top: -.75rem; }
.back { margin-top: 3rem; }

/* --- gallery ------------------------------------------------------------ */

.gallery {
  list-style: none; margin: 2rem 0; padding: 0; max-width: none;
  display: grid; gap: .75rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.gallery li, .gallery figure { margin: 0; max-width: none; }
.gallery img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: 3px; background: var(--ground-raised);
  transition: opacity .15s ease;
}
.gallery a:hover img { opacity: .78; }

/* --- player ------------------------------------------------------------- */

.player {
  background: var(--ground-raised); border: 1px solid var(--line);
  border-radius: 5px; margin: 1.5rem 0; overflow: hidden; max-width: 46rem;
}
.viz { display: block; width: 100%; height: 96px; background: #131117; }
.transport {
  display: grid; grid-template-columns: auto 1fr auto;
  grid-template-areas: "play now time" "play seek time";
  gap: .1rem .9rem; align-items: center; padding: .8rem 1rem;
}
.transport .play {
  grid-area: play; width: 2.75rem; height: 2.75rem; border-radius: 50%;
  border: 0; background: var(--accent); color: #17130f;
  font-size: 1rem; cursor: pointer; line-height: 1;
}
.transport .play:hover { filter: brightness(1.1); }
.transport .now { grid-area: now; margin: 0; font-size: .9375rem; max-width: none; }
.transport .time { grid-area: time; color: var(--ink-dim); font-variant-numeric: tabular-nums; font-size: .875rem; }
.transport .seek { grid-area: seek; width: 100%; accent-color: var(--accent); }

.tracklist {
  list-style: none; counter-reset: t; margin: 1.5rem 0; padding: 0;
  max-width: 46rem; border-top: 1px solid var(--line);
}
.tracklist li {
  display: flex; gap: 1rem; align-items: baseline; max-width: none;
  padding: .55rem .75rem; border-bottom: 1px solid var(--line);
}
.tracklist li.track { cursor: pointer; }
.tracklist li.track:hover { background: var(--ground-raised); }
.tracklist li.playing { background: var(--ground-raised); box-shadow: inset 3px 0 0 var(--accent); }
.tracklist li.playing .track-title { color: var(--accent); }
.tracklist .track-title { margin: 0; flex: 1; max-width: none; }
.tracklist .track-length { margin: 0; color: var(--ink-dim); font-variant-numeric: tabular-nums; font-size: .875rem; }
/* Without JS every row keeps its own native player, which is the fallback. */
.tracklist audio { width: 100%; max-width: 18rem; }

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

.footer {
  max-width: var(--wide); margin: 0 auto;
  padding: 2rem 1.25rem 3rem; border-top: 1px solid var(--line);
  color: var(--ink-dim); font-size: .875rem;
}
.footer p { margin: .2rem 0; }
.footer .fine { color: #6d6a72; }

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

/* --- post listing ------------------------------------------------------- */

.postlist { list-style: none; margin: 2rem 0 0; padding: 0; max-width: var(--measure); }
.postlist li { max-width: none; padding: 1rem 0; border-bottom: 1px solid var(--line); }
.postlist-date { margin: 0 0 .15rem; color: var(--ink-dim); font-size: .8125rem; letter-spacing: .02em; text-transform: uppercase; }
.postlist h2 { margin: 0; font-size: 1.15rem; line-height: 1.3; }
.postlist h2 a { color: var(--ink); text-decoration: none; }
.postlist h2 a:hover { color: var(--accent); }

/* --- album hero --------------------------------------------------------- */

.album-hero { position: relative; overflow: hidden; border-bottom: 1px solid var(--line); }
.album-hero-bg {
  position: absolute; inset: -12%;
  background-size: cover; background-position: center;
  filter: blur(64px) saturate(1.5) brightness(.55);
  transform: scale(1.15);
}
/* The blur alone leaves the type sitting on whatever the sleeve happened to
   be; this guarantees the contrast rather than hoping for it. */
.album-hero::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgb(18 17 20 / .55) 0%, rgb(18 17 20 / .82) 62%, var(--ground) 100%);
}
.album-hero-inner {
  position: relative; z-index: 1;
  max-width: var(--wide); margin: 0 auto;
  padding: 3rem 1.25rem 2.5rem;
  display: flex; flex-wrap: wrap; gap: 2rem; align-items: flex-end;
}
.sleeve {
  width: 250px; height: 250px; flex: none; border-radius: 4px;
  box-shadow: 0 18px 50px rgb(0 0 0 / .6), 0 0 0 1px rgb(255 255 255 / .07);
}
.album-meta { min-width: 15rem; }
.eyebrow {
  margin: 0 0 .35rem; font-size: .75rem; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--accent);
}
.album-meta h1 {
  margin: 0 0 .5rem; line-height: .95; letter-spacing: .01em;
  font-family: var(--display); font-weight: 400; text-transform: uppercase;
  font-size: clamp(2.4rem, 1.3rem + 4.6vw, 4.6rem);
  text-shadow: 0 2px 24px rgb(0 0 0 / .55);
}
.album-year { margin: 0; color: var(--ink-dim); font-size: .9375rem; }
.album-year .sep { margin: 0 .5rem; opacity: .55; }
.album-body { padding-top: 2rem; }
.album-body .tracklist { margin-top: 0; }

@media (max-width: 34rem) {
  .sleeve { width: 180px; height: 180px; }
  .album-hero-inner { padding-top: 2rem; gap: 1.25rem; }
}

/* --- hero visualiser ----------------------------------------------------- */

/* Sits between the blurred sleeve and the gradient, so the bars come up
   *through* the artwork's colour rather than sitting on top of the type. */
.viz-hero {
  position: absolute; inset: auto 0 0 0; z-index: 0;
  width: 100%; height: 260px; display: block;
  opacity: .85; mix-blend-mode: screen; pointer-events: none;
}

/* --- record shelf -------------------------------------------------------- */

.shelf {
  list-style: none; margin: 2.5rem 0 0; padding: 0; max-width: none;
  display: grid; gap: 2rem 1.5rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr));
}
.shelf li { max-width: none; margin: 0; }
.shelf a { display: block; text-decoration: none; color: inherit; }
.shelf-art {
  position: relative; border-radius: 4px; overflow: hidden;
  box-shadow: 0 12px 34px rgb(0 0 0 / .5), 0 0 0 1px rgb(255 255 255 / .07);
  transition: transform .22s cubic-bezier(.2,.7,.3,1), box-shadow .22s ease;
}
.shelf-art img { width: 100%; aspect-ratio: 1; object-fit: cover; }
.shelf a:hover .shelf-art, .shelf a:focus-visible .shelf-art {
  transform: translateY(-6px) scale(1.02);
  box-shadow: 0 22px 46px rgb(0 0 0 / .62), 0 0 0 1px var(--album-accent, var(--accent));
}
/* The play affordance only appears on approach; the sleeve is the subject. */
.shelf-art::after {
  content: "▶"; position: absolute; right: .6rem; bottom: .6rem;
  width: 2.4rem; height: 2.4rem; border-radius: 50%;
  display: grid; place-items: center; font-size: .8rem;
  background: var(--album-accent, var(--accent)); color: #17130f;
  opacity: 0; transform: translateY(6px); transition: opacity .2s ease, transform .2s ease;
}
.shelf a:hover .shelf-art::after, .shelf a:focus-visible .shelf-art::after { opacity: 1; transform: none; }
.shelf-title {
  margin: .85rem 0 .1rem; font-family: var(--display); font-weight: 400;
  text-transform: uppercase; letter-spacing: .015em; font-size: 1.1rem; line-height: 1.15;
}
.shelf a:hover .shelf-title { color: var(--album-accent, var(--accent)); }
.shelf-meta { margin: 0; color: var(--ink-dim); font-size: .8125rem; }

.lede { font-size: 1.15rem; color: var(--ink); max-width: var(--measure); }

/* The remix's name, set under the record it remixes rather than beside it.
   Inside the h1 so the heading still reads as one name to a screen reader,
   and display:block so the big line keeps the same measure the other four
   albums have — a wrapped h1 was what pushed the sleeve off the baseline. */
.album-subtitle {
  display: block;
  font-family: var(--sans);
  font-size: clamp(.95rem, .8rem + .6vw, 1.35rem);
  font-weight: 500;
  letter-spacing: .01em;
  text-transform: none;
  color: var(--accent);
  margin-top: .35rem;
  text-shadow: 0 1px 10px rgb(0 0 0 / .6);
}
.shelf-subtitle {
  display: block;
  font-family: var(--sans);
  font-size: .8125rem; font-weight: 500;
  text-transform: none; letter-spacing: 0;
  color: var(--ink-dim); margin-top: .1rem;
}
.shelf a:hover .shelf-subtitle { color: var(--album-accent, var(--accent)); }

/* --- home hero ---------------------------------------------------------- */

.hero { position: relative; isolation: isolate; overflow: hidden; }
.hero-img { position: absolute; inset: 0; z-index: -2; }
.hero-img img { width: 100%; height: 100%; object-fit: cover; object-position: center 38%; }
/* The photograph is a mid-tone colour shot and the type is white; without a
   scrim the headline lands wherever the exposure happened to fall. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgb(18 17 20 / .35) 0%, rgb(18 17 20 / .55) 45%, var(--ground) 100%),
    linear-gradient(90deg, rgb(18 17 20 / .6) 0%, rgb(18 17 20 / .1) 60%);
}
.hero-inner {
  position: relative; max-width: var(--wide); margin: 0 auto;
  padding: clamp(5rem, 14vh, 9rem) 1.25rem clamp(3rem, 8vh, 5rem);
}
.hero-eyebrow {
  margin: 0 0 .6rem; color: var(--accent); font-size: .8125rem;
  font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
}
.hero-title {
  margin: 0; font-family: var(--display); font-weight: 400; text-transform: uppercase;
  font-size: clamp(3rem, 1.4rem + 9vw, 8rem); line-height: .88; letter-spacing: .005em;
  text-shadow: 0 4px 40px rgb(0 0 0 / .7);
}
.hero-sub { margin: 1rem 0 0; font-size: clamp(1rem, .9rem + .5vw, 1.3rem); color: var(--ink); max-width: 30ch; }
.hero-cta { margin: 1.75rem 0 0; }
.btn {
  display: inline-block; background: var(--accent); color: #17130f;
  padding: .7rem 1.6rem; border-radius: 3px; text-decoration: none;
  font-weight: 700; letter-spacing: .06em; text-transform: uppercase; font-size: .875rem;
}
.btn:hover { filter: brightness(1.12); color: #17130f; }

/* --- home sections ------------------------------------------------------ */

.home-intro { padding-top: 2.5rem; padding-bottom: 1rem; }
.home-section { max-width: var(--wide); margin: 0 auto; padding: 1.5rem 1.25rem 3rem; }
.section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 1rem; border-bottom: 1px solid var(--line); padding-bottom: .6rem;
}
.section-head h2 {
  margin: 0; font-family: var(--display); font-weight: 400; text-transform: uppercase;
  letter-spacing: .02em; font-size: 1.5rem;
}
.section-more { font-size: .875rem; text-decoration: none; white-space: nowrap; }
.home-section .postlist { margin-top: .5rem; max-width: none; }
.home-section .postlist h3 { margin: 0; font-size: 1.05rem; }
.home-section .postlist h3 a { color: var(--ink); text-decoration: none; }
.home-section .postlist h3 a:hover { color: var(--accent); }

/* --- lightbox ----------------------------------------------------------- */

/* The layout is on [open], not on .lightbox. A <dialog> is hidden by the UA
   rule `dialog:not([open]) { display: none }`, and any author `display` beats
   a UA rule regardless of specificity -- so declaring `display: grid` here
   left the panel on screen permanently, open or closed. That one line
   produced every symptom: the photograph never vanished, the fixed-position
   close button never left, and the first click on it appeared to do nothing
   because it had closed a dialog that stayed visible. */
.lightbox {
  border: 0; padding: 0; background: transparent;
  max-width: 100vw; max-height: 100vh; width: 100vw; height: 100vh;
  color: var(--ink);
}
.lightbox[open] {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center;
}
.lightbox::backdrop { background: rgb(8 7 10 / .92); }
.lb-figure { grid-column: 2; margin: 0; display: grid; justify-items: center; gap: .75rem; padding: 1rem; }
.lb-figure img {
  max-width: 100%; max-height: 82vh; width: auto; border-radius: 3px;
  box-shadow: 0 24px 60px rgb(0 0 0 / .6);
}
.lb-count { color: var(--ink-dim); font-size: .8125rem; letter-spacing: .06em; }
.lightbox button {
  background: rgb(255 255 255 / .07); color: var(--ink); border: 0;
  cursor: pointer; border-radius: 50%; width: 3rem; height: 3rem;
  font-size: 1.5rem; line-height: 1; display: grid; place-items: center;
  transition: background .15s ease;
}
.lightbox button:hover { background: var(--accent); color: #17130f; }
.lb-prev { grid-column: 1; margin-left: .75rem; }
.lb-next { grid-column: 3; margin-right: .75rem; }
.lb-close { position: fixed; top: 1rem; right: 1rem; font-size: 1.1rem; }

@media (max-width: 40rem) {
  .lightbox { grid-template-columns: 1fr; }
  .lb-figure { grid-column: 1; }
  /* Arrows would crowd a phone; the swipe handler covers it. */
  .lb-prev, .lb-next { display: none; }
}

/* --- press clippings ---------------------------------------------------- */

.clipping {
  border-top: 1px solid var(--line);
  padding: 2rem 0 .5rem;
  max-width: 44rem;
}
.clipping:first-of-type { border-top: 0; }
.clipping-head { display: flex; flex-wrap: wrap; gap: .9rem 1.25rem; align-items: center; margin-bottom: 1rem; }
/* The mastheads arrived at wildly different aspect ratios -- a 200x200 square
   next to a 375x75 banner -- so they are bounded by height rather than width
   and sit on a light plate, since most are dark artwork on transparency. */
.clipping-logo {
  height: 2.6rem; width: auto; max-width: 11rem; object-fit: contain;
  background: rgb(255 255 255 / .92); border-radius: 3px; padding: .3rem .5rem;
}
.clipping-meta { margin: 0; max-width: none; display: grid; gap: .15rem; }
.clipping-meta cite { font-style: normal; font-weight: 600; font-size: 1rem; }
.clipping-meta cite a { text-decoration: none; }
.clipping-meta cite a:hover { text-decoration: underline; }
.byline { color: var(--ink-dim); font-size: .8125rem; }
.clipping blockquote {
  margin: 0; padding-left: 1.1rem;
  border-left: 2px solid var(--accent);
}
.clipping blockquote p { margin: 0 0 .9rem; }
.clipping-caption {
  margin: .25rem 0 0 1.1rem; color: var(--ink-dim);
  font-size: .8125rem; font-style: italic; max-width: var(--measure);
}

/* --- lineup chart -------------------------------------------------------- */

/* Spans the same width as the roster below it. It was capped at 46rem while
   the cards filled the full measure, so the chart read as a narrower, unrelated
   thing sitting above them. */
.lineup { margin: 2.5rem 0 3.5rem; }
.lineup h2 {
  font-family: var(--display); font-weight: 400; text-transform: uppercase;
  letter-spacing: .02em; font-size: 1.35rem; margin: 0 0 1rem;
}
.chart { list-style: none; margin: 0; padding: 0; max-width: none; }

/* `.prose li` sets the reading measure at (0,1,1) specificity, which outranks
   a bare `.chart-row` and was capping every row at 34rem inside a section
   1048px wide -- the chart looked narrow while its container was not. Scoped
   here to win rather than raised globally, because the measure is right for
   the prose it was written for. */
.prose .chart,
.prose .chart-row,
.prose .roster,
.prose .roster > li { max-width: none; }

/* One row template, used by the member rows and by the axis, so the year
   labels cannot drift out of step with the columns they label. */
.chart-row {
  display: grid; grid-template-columns: minmax(6.5rem, 9rem) 1fr;
  gap: .75rem; align-items: center; margin-bottom: .4rem; max-width: none;
}
.chart-name { font-size: .875rem; color: var(--ink-dim); }
.chart-track {
  display: grid; grid-template-columns: repeat(8, 1fr);
  background: linear-gradient(90deg, var(--line) 1px, transparent 1px) 0 0 / calc(100% / 8) 100%;
  border-radius: 3px; min-height: 2rem; align-items: center;
}
.chart-bar {
  /* Placement comes from the template as literal grid lines -- see the note
     in content/pages/members.html. */
  height: 1.85rem; border-radius: 3px;
  background: color-mix(in srgb, var(--accent) 30%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
  display: flex; align-items: center; padding: 0 .55rem;
  transition: background .18s ease;
}
.chart-bar.is-founder { background: color-mix(in srgb, var(--accent) 62%, transparent); }
.chart-row:hover .chart-bar { background: var(--accent); }
.chart-years { font-size: .75rem; font-variant-numeric: tabular-nums; color: var(--ink); white-space: nowrap; }
.chart-row:hover .chart-years { color: #17130f; font-weight: 600; }

.chart-axis { margin-top: .1rem; margin-bottom: 0; }
.chart-axis .chart-track {
  background: none; min-height: 0;
  border-top: 1px solid var(--line); padding-top: .35rem;
}
.chart-year {
  font-size: .6875rem; color: var(--ink-dim);
  font-variant-numeric: tabular-nums;
  /* Sits on its column's left edge, which is the year the column begins. */
  justify-self: start;
}

@media (max-width: 34rem) {
  .chart-row { grid-template-columns: 1fr; gap: .2rem; }
  .chart-axis .chart-name { display: none; }
  .chart-years { font-size: .6875rem; }
  .chart-year { font-size: .625rem; }
}

/* --- roster -------------------------------------------------------------- */

.roster {
  list-style: none; margin: 0; padding: 0; max-width: none;
  display: grid; gap: 1.25rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
}
.member {
  max-width: none; display: grid; grid-template-columns: auto 1fr; gap: 1.1rem;
  background: var(--ground-raised); border: 1px solid var(--line);
  border-radius: 5px; padding: 1.1rem;
  transition: border-color .18s ease, transform .18s ease;
}
.member:hover { border-color: color-mix(in srgb, var(--accent) 55%, transparent); transform: translateY(-2px); }
.member-photo {
  width: 5.5rem; height: 5.5rem; border-radius: 50%; object-fit: cover;
  box-shadow: 0 0 0 1px rgb(255 255 255 / .08);
}
.member-body { min-width: 0; }
.member h2 {
  margin: 0 0 .2rem; font-size: 1.15rem; line-height: 1.2;
  font-family: var(--display); font-weight: 400; text-transform: uppercase; letter-spacing: .015em;
}
.member-years {
  margin: 0 0 .45rem; color: var(--ink-dim); font-size: .8125rem;
  font-variant-numeric: tabular-nums; display: flex; flex-wrap: wrap; gap: .5rem; align-items: center;
}
.chip {
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
  border-radius: 100px; padding: .1rem .55rem; font-size: .6875rem;
  letter-spacing: .04em; text-transform: uppercase; font-weight: 700;
}
.member-role { margin: 0 0 .5rem; font-size: .9375rem; max-width: none; }
.member-gear { list-style: none; margin: 0; padding: 0; max-width: none; display: flex; flex-wrap: wrap; gap: .3rem; }
.member-gear li {
  max-width: none; font-size: .75rem; color: var(--ink-dim);
  background: rgb(255 255 255 / .045); border-radius: 3px; padding: .15rem .45rem;
}

/* ========================================================================
   Movement
   ------------------------------------------------------------------------
   The first version of this was scroll-driven throughout, and it was close to
   invisible. Measuring the pages explains why: /music/ has 263px of scrollable
   distance, /members/ 393px, /broken/ 446px. At 1.3 to 1.5 screens tall almost
   everything is already in view when the page paints, so a view() timeline
   renders it at its final state and no animation is ever seen. Scroll-driven
   animation needs scroll, and this site is an archive of a band that released
   five records -- it does not have long pages and should not grow them to
   justify an effect.

   So entrances run on load instead. Ordinary CSS animations, supported
   everywhere, which also fixes the other half of the problem: scroll timelines
   are still behind a flag in Firefox, so a fifth of visitors were getting
   nothing at all.

   fill-mode is `backwards`, not `both`. Backwards applies the opening frame
   before the animation starts and then hands the element back to its normal
   styles, so a card that has finished animating is free to be moved by :hover.
   With `both` the final frame persists and outranks the hover rule, which is
   how the member cards ended up looking interactive while refusing to move.
   ======================================================================== */

/* Cross-document transitions. One rule, and navigation stops being a white
   flash between pages. Browsers without it just navigate. */
@view-transition { navigation: auto; }

/* The sleeve is lit by the low end. --pulse is written by player.js from the
   analyser's bass bins, 0 when nothing is playing, so the artwork sits dark
   until the record starts.
                                                                
   The first version of this moved the sleeve 4.5% at full pulse and nothing
   else. Measured mid-playback that is scale(1.028) -- real, and invisible.
   Size is the wrong channel here: the sleeve sits against a blurred copy of
   itself with no fixed edge to measure against, so a few percent of scale has
   nothing to read as. Light does have somewhere to go, so the glow does the
   work and the scale is left as a small assist. */
.sleeve {
  transform: scale(calc(1 + var(--pulse, 0) * 0.05));
  /* Three layers, because one wide blur reads as fog rather than as light.
     A hot rim gives the edge, a tight core gives the source, and the wide
     halo gives the throw -- together they have a centre, which is what makes
     it look focused. All three ride --glow rather than --pulse, so they are
     dark between hits instead of permanently half-lit. */
  box-shadow:
    0 18px 50px rgb(0 0 0 / .6),
    0 0 0 calc(1px + var(--glow, 0) * 2px)
      color-mix(in srgb, var(--accent) calc(var(--glow, 0) * 100%), rgb(255 255 255 / .09)),
    0 0 calc(4px + var(--glow, 0) * 26px) calc(var(--glow, 0) * 5px)
      color-mix(in srgb, var(--accent) calc(var(--glow, 0) * 95%), transparent),
    0 0 calc(var(--glow, 0) * 96px) calc(var(--glow, 0) * 20px)
      color-mix(in srgb, var(--accent) calc(var(--glow, 0) * 40%), transparent);
  filter: brightness(calc(1 + var(--glow, 0) * 0.3))
          saturate(calc(1 + var(--glow, 0) * 0.45))
          contrast(calc(1 + var(--glow, 0) * 0.12));
  transition: transform .05s linear, box-shadow .05s linear, filter .05s linear;
  will-change: transform, filter, box-shadow;
}
.album-hero-bg {
  filter: blur(64px) saturate(calc(1.5 + var(--pulse, 0) * 1.1))
          brightness(calc(.5 + var(--glow, 0) * 0.55));
}
/* The title lifts with it, so the whole header reads as lit rather than just
   the one square in the corner of it. */
.album-meta h1 {
  text-shadow: 0 2px 24px rgb(0 0 0 / .55),
               0 0 calc(var(--glow, 0) * 34px)
                 color-mix(in srgb, var(--accent) calc(var(--glow, 0) * 85%), transparent);
}

@media (prefers-reduced-motion: no-preference) {

  /* Page furniture arrives first. */
  .album-hero-inner > *,
  .hero-inner > *,
  .prose > h1 {
    animation: rise .6s cubic-bezier(.2,.75,.3,1) backwards;
  }
  .hero-inner > *:nth-child(2) { animation-delay: .07s; }
  .hero-inner > *:nth-child(3) { animation-delay: .14s; }
  .hero-inner > *:nth-child(4) { animation-delay: .21s; }
  .album-hero-inner > *:nth-child(2) { animation-delay: .08s; }

  .sleeve { animation: sleeve-in .7s cubic-bezier(.2,.75,.3,1) backwards; }

  /* Collections stagger, so a grid assembles rather than appearing. */
  .shelf > li,
  .gallery > li,
  .postlist > li,
  .member,
  .clipping,
  .home-section {
    animation: rise .5s cubic-bezier(.2,.75,.3,1) backwards;
  }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(1) { animation-delay: .05s; }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(2) { animation-delay: .11s; }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(3) { animation-delay: .17s; }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(4) { animation-delay: .23s; }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(5) { animation-delay: .29s; }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(6) { animation-delay: .35s; }
  :is(.shelf, .gallery, .postlist, .roster) > li:nth-child(n+7) { animation-delay: .41s; }
  .clipping:nth-of-type(2) { animation-delay: .1s; }
  .clipping:nth-of-type(3) { animation-delay: .2s; }
  .clipping:nth-of-type(n+4) { animation-delay: .3s; }

  /* The chart is about time, so it draws along it -- left to right, in the
     order the members joined. */
  .chart-bar {
    transform-origin: left center;
    animation: draw .75s cubic-bezier(.25,.8,.3,1) backwards;
  }
  .chart-row:nth-child(1) .chart-bar { animation-delay: .15s; }
  .chart-row:nth-child(2) .chart-bar { animation-delay: .25s; }
  .chart-row:nth-child(3) .chart-bar { animation-delay: .35s; }
  .chart-row:nth-child(4) .chart-bar { animation-delay: .45s; }
  .chart-row:nth-child(5) .chart-bar { animation-delay: .55s; }
  .chart-row:nth-child(n+6) .chart-bar { animation-delay: .65s; }

  /* Parallax stays scroll-driven, and only on the home page -- the one page
     with enough scrollable distance (1395px) for it to read as movement. */
  @supports (animation-timeline: scroll()) {
    .hero-img img {
      animation: drift linear both;
      animation-timeline: scroll();
      animation-range: 0 100vh;
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .sleeve { transform: none; }
  .album-hero-bg { filter: blur(64px) saturate(1.5) brightness(.55); }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(1.1rem); }
}
@keyframes sleeve-in {
  from { opacity: 0; transform: translateY(1.5rem) scale(.94); }
}
@keyframes draw {
  from { transform: scaleX(0); opacity: 0; }
}
@keyframes drift {
  from { transform: translateY(0) scale(1.06); }
  to   { transform: translateY(7%) scale(1.06); }
}
