/* Album Anniversaries.

   Referent: a turntable platter seen from directly above. It is not decoration
   — an album *turning* twenty, drawn on a record that turns, with the milestone
   number printed where the playing speed belongs. 33 1/3, 45 and 78 live in
   that spot on a real label; here it is 10, 20, 25, 30, 40, 50. Every other
   decision on this page serves that substitution.

   PLAYBOOK section 12 is why a referent exists at all: warm off-white, a book
   serif, muted earth tones and generous whitespace are a house style rather
   than neutrality, and this page has to be unmistakable for a reading app.

   The record is CSS, not SVG and not a photograph. Grooves are one
   repeating-radial-gradient rather than sixty circles, which costs nothing and
   scales to any diameter. There are no album covers anywhere on this site:
   those are copyrighted, and a pressing is a handful of circles anyway.

   Anything drawn on the vinyl is LIGHTER than it. A near-black shape on
   near-black vinyl reads as a compression artifact, not a silhouette. */

:root {
  --vinyl:    #0B0B0E;
  --sheen:    #6E7684;
  --felt:     #23201C;
  --alu:      #8C9099;
  --label:    #E8401F;
  --ink-blue: #16346B;
  --cream:    #EFE7D2;
  --acid:     #D6FF3E;
  --dust:     #8A8378;

  --sign: "Barlow Condensed", "Archivo Narrow", system-ui, sans-serif;
  --num:  "Anton", "Barlow Condensed", system-ui, sans-serif;
  --body: "Archivo", system-ui, -apple-system, sans-serif;

  --gutter: 16px;
  --measure: 660px;
  --disc: min(86vw, 420px);
}

* { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--felt);
  /* the felt of a slipmat, which is a texture and not a flat colour */
  background-image:
    repeating-linear-gradient(48deg, rgba(255,255,255,.012) 0 2px, transparent 2px 5px),
    repeating-linear-gradient(-41deg, rgba(0,0,0,.05) 0 3px, transparent 3px 7px);
  color: var(--cream);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.55;
}

main {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

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

.hero { padding: 26px 0 8px; }

.masthead {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.today {
  margin: 0 0 6px;
  font-family: var(--sign);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--acid);
  min-height: 1.2em;
}

.hero h1 {
  margin: 0;
  max-width: 11em;
  font-family: var(--sign);
  font-weight: 900;
  font-size: clamp(2.1rem, 9vw, 3.1rem);
  line-height: .98;
  letter-spacing: -.005em;
  color: var(--cream);
}

.intro {
  margin: 12px 0 0;
  font-size: .95rem;
  color: rgba(239, 231, 210, .6);
}

/* ------------------------------------------------------------- the platter */

/* The arm's pivot sits outside the platter, which is where a pivot is — and
   that overhang was enough to give a 373px viewport a scrollbar. The wrapper
   clips it rather than the page doing so, because `overflow: clip` on the root
   would hide the overhang on every screen instead of only the narrow ones. */
.platter-wrap {
  position: relative;
  overflow: hidden;
  padding: 0 var(--gutter);
}

.platter {
  position: relative;
  width: var(--disc);
  height: var(--disc);
  margin: 26px auto 0;
}

.record,
.grooves,
.sheen,
.strobe,
.label {
  position: absolute;
  border-radius: 50%;
}

.record {
  inset: 0;
  background: var(--vinyl);
  box-shadow: 0 22px 44px -12px rgba(0, 0, 0, .75);
}

/* Sixty concentric rings for the price of one declaration.

   The period is 5px and the contrast is low on purpose. At 3px the rings beat
   against the pixel grid and the whole surface swims with moire — which looks
   like a rendering fault rather than like vinyl. Wider and fainter reads as a
   pressing; tighter reads as a bug. */
.grooves {
  inset: 0;
  background: repeating-radial-gradient(circle closest-side at 50% 50%,
    rgba(110, 118, 132, .11) 0 0.6px,
    rgba(110, 118, 132, .03) 0.6px 2px,
    transparent 2px 5px);
  -webkit-mask-image: radial-gradient(circle closest-side at 50% 50%, transparent 0 53%, #000 53.5%);
          mask-image: radial-gradient(circle closest-side at 50% 50%, transparent 0 53%, #000 53.5%);
}

/* the band of light that crosses a pressing under a lamp */
.sheen {
  inset: 0;
  background: linear-gradient(118deg,
    transparent 0 32%,
    rgba(110, 118, 132, .20) 44%,
    rgba(160, 170, 190, .30) 50%,
    rgba(110, 118, 132, .20) 56%,
    transparent 68% 100%);
  -webkit-mask-image: radial-gradient(circle closest-side at 50% 50%, transparent 0 53%, #000 53.5%);
          mask-image: radial-gradient(circle closest-side at 50% 50%, transparent 0 53%, #000 53.5%);
}

/* the strobe ring a pitch lamp flickers against */
.strobe {
  inset: 2.5%;
  background: repeating-conic-gradient(from 0deg,
    rgba(140, 144, 153, .55) 0deg 1.1deg,
    transparent 1.1deg 5deg);
  -webkit-mask-image: radial-gradient(circle closest-side at 50% 50%, transparent 0 92%, #000 93% 98%, transparent 99%);
          mask-image: radial-gradient(circle closest-side at 50% 50%, transparent 0 92%, #000 93% 98%, transparent 99%);
}

/* The label. The spindle hole is dead centre because that is where a spindle
   is, so the number sits ABOVE it rather than on it — the first comp punched
   the hole straight through the numeral. */
.label {
  inset: 26%;
  background: var(--label);
  box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .42);
  text-align: center;
}

.lab-top,
.lab-bot {
  position: absolute;
  left: 0;
  right: 0;
  margin: 0;
  font-family: var(--sign);
  font-weight: 600;
  font-size: clamp(.62rem, 2.6vw, .8rem);
  letter-spacing: .34em;
  text-indent: .34em;
  text-transform: uppercase;
  color: rgba(239, 231, 210, .85);
}

.lab-top { top: 11%; }
.lab-bot { bottom: 12%; }

.lab-num {
  position: absolute;
  left: 0;
  right: 0;
  top: 20%;
  margin: 0;
  font-family: var(--num);
  font-weight: 400;
  font-size: clamp(2.6rem, 13vw, 4rem);
  line-height: .86;
  color: var(--acid);
}

.hole {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 4.2%;
  height: 4.2%;
  margin: -2.1% 0 0 -2.1%;
  border-radius: 50%;
  background: var(--felt);
  box-shadow: 0 0 0 2.4% rgba(239, 231, 210, .22);
}

/* the arm, coming in over the right shoulder of the platter */
.tonearm {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.tonearm .pivot {
  position: absolute;
  top: -7%;
  right: -9%;
  width: 15%;
  height: 15%;
  border-radius: 50%;
  background: #3A3E47;
  box-shadow: inset 0 0 0 4px var(--alu);
}

/* The arm is sized so the stylus lands on the GROOVES, not on the label. The
   label runs from 26% to 74%, so anything the arm touches inside that is a
   needle sitting on the paper — which is what the first pass drew. At 55% long
   and 22 degrees off vertical the tip reaches about 79% across, out on the
   playing surface where it belongs. */
.tonearm .arm {
  position: absolute;
  top: 0;
  right: 0;
  width: 2.1%;
  height: 55%;
  border-radius: 2px;
  background: linear-gradient(90deg, #5E636D, var(--alu) 45%, #5E636D);
  transform-origin: 50% 0;
  transform: rotate(22deg);
}

.tonearm .head {
  position: absolute;
  top: 49%;
  right: 16%;
  width: 10%;
  height: 4.5%;
  border-radius: 2px;
  background: var(--cream);
  transform: rotate(22deg);
}

/* The sleeve leaning against the deck. It sits low and to the left, clear of
   the label and on the opposite side from the tonearm, the way a sleeve
   actually ends up when the record is out of it and playing.

   No cover is stored here or served from this domain; `src` points at the
   Cover Art Archive and the reader's browser fetches it. D10. */
.prop {
  position: absolute;
  left: 1%;
  /* inside the wrap, which clips: a sleeve with its bottom edge cut off reads
     as a rendering fault, not as one resting on the plinth */
  bottom: 3%;
  width: 34%;
  max-width: 158px;
  margin: 0;
  aspect-ratio: 1;
  transform: rotate(-6deg);
  opacity: 0;
  transition: opacity .4s ease-out;
  pointer-events: none;
}

.prop[hidden] { display: none; }

/* Only once the picture has decoded. An empty square leaning on the deck
   would read as a loading bug rather than as a sleeve. */
.prop.has-art { opacity: 1; }

.prop img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #14161C;
  box-shadow:
    0 2px 0 rgba(255, 255, 255, .10),
    0 18px 30px -12px rgba(0, 0, 0, .9);
}

/* what is actually playing, set on the vinyl below the label */
.now {
  max-width: var(--measure);
  margin: 22px auto 0;
  padding: 0 var(--gutter);
  text-align: center;
}

.now-title {
  margin: 0;
  font-family: var(--sign);
  font-weight: 900;
  font-size: clamp(1.5rem, 7vw, 2.1rem);
  line-height: 1.05;
  color: var(--cream);
}

.now-artist {
  margin: 4px 0 0;
  font-size: 1rem;
  color: rgba(239, 231, 210, .62);
}

.now-date {
  margin: 6px 0 0;
  font-size: .82rem;
  color: var(--dust);
}

/* --------------------------------------------------------- milestone picks */

.picks { margin: 40px 0 0; }

.picks-label {
  margin: 0 0 10px;
  font-family: var(--sign);
  font-weight: 600;
  font-size: .9rem;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: rgba(239, 231, 210, .45);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
}

/* each one a label sticker: a disc with a number on it */
.chip {
  width: 58px;
  height: 58px;
  border: 0;
  border-radius: 50%;
  background: #14161C;
  box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .2);
  color: rgba(239, 231, 210, .8);
  cursor: pointer;
  font-family: var(--num);
  font-size: 1.45rem;
  line-height: 1;
  transition: background .15s, color .15s, box-shadow .15s;
}

.chip:hover { box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .5); }

.chip[aria-pressed="true"] {
  background: var(--label);
  box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .5);
  color: var(--acid);
}

.chip.is-empty { opacity: .38; }

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

/* ----------------------------------------------------------- today's albums */

.listing { margin: 26px 0 0; }

.row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 14px 0;
  border-top: 1px solid rgba(239, 231, 210, .12);
}

.listing .row:last-child { border-bottom: 1px solid rgba(239, 231, 210, .12); }

.row-year {
  flex: 0 0 auto;
  font-family: var(--num);
  font-size: 1.1rem;
  color: var(--acid);
}

.row-main { flex: 1 1 auto; min-width: 0; }

.row-title {
  margin: 0;
  font-family: var(--sign);
  font-weight: 900;
  font-size: 1.22rem;
  line-height: 1.12;
  color: var(--cream);
}

.row-artist {
  margin: 2px 0 0;
  font-size: .9rem;
  color: rgba(239, 231, 210, .58);
}

.row-share {
  flex: 0 0 auto;
  padding: 7px 12px;
  border: 0;
  background: transparent;
  box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .26);
  border-radius: 2px;
  color: rgba(239, 231, 210, .8);
  cursor: pointer;
  font-family: var(--sign);
  font-weight: 600;
  font-size: .82rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}

.row-share:hover { box-shadow: inset 0 0 0 1.5px var(--acid); color: var(--acid); }
.row-share.done { background: var(--acid); color: #14161C; box-shadow: none; }

.nothing {
  margin: 20px 0;
  font-size: 1.02rem;
  color: rgba(239, 231, 210, .5);
}

/* ------------------------------------------------------------- the long tail */

.tail { margin: 48px 0 0; }

.tail h2 {
  margin: 0 0 16px;
  font-family: var(--sign);
  font-weight: 900;
  font-size: 1.4rem;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: rgba(239, 231, 210, .9);
}

.sleeves {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(146px, 1fr));
  gap: 12px;
}

/* a 12-inch sleeve: square, one flat colour, type and nothing else */
.sleeve {
  position: relative;
  aspect-ratio: 1;
  padding: 13px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  overflow: hidden;
  background: var(--ink-blue);
  box-shadow: 0 6px 14px -6px rgba(0, 0, 0, .6);
}

/* the ring a record wears through its own sleeve after enough years */
.sleeve::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 86%;
  height: 86%;
  margin: -43% 0 0 -43%;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .07);
}

/* The art sits under the type rather than replacing it, so the two in ten
   with no cover lose a picture and nothing else. The scrim is what keeps the
   title legible over whatever the sleeve happens to be. */
.sleeve-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .35s ease-out;
}

.sleeve.has-art .sleeve-art { opacity: 1; }

.sleeve.has-art::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(11, 11, 14, .55) 0 22%,
    rgba(11, 11, 14, 0) 46%,
    rgba(11, 11, 14, .72) 78%,
    rgba(11, 11, 14, .92) 100%);
}

/* the ring-wear is the drawn sleeve's detail; over a real cover it is noise */
.sleeve.has-art::after { display: none; }

.sleeve-year,
.sleeve-title,
.sleeve-artist { position: relative; }

.sleeve-year {
  position: absolute;
  top: 11px;
  left: 13px;
  font-family: var(--num);
  font-size: 1rem;
  color: rgba(239, 231, 210, .5);
}

.sleeve-title {
  margin: 0;
  font-family: var(--sign);
  font-weight: 900;
  font-size: 1.02rem;
  line-height: 1.1;
  color: var(--cream);
}

.sleeve-artist {
  margin: 3px 0 0;
  font-size: .8rem;
  line-height: 1.25;
  color: rgba(239, 231, 210, .55);
}

.tail-count {
  margin: 16px 0 0;
  font-size: .86rem;
  color: var(--dust);
}

/* ---------------------------------------------------------------- pick a day */

.pickday {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin: 40px 0 0;
  padding: 18px;
  background: rgba(11, 11, 14, .5);
}

.pickday label {
  font-family: var(--sign);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(239, 231, 210, .6);
}

.pickday input {
  padding: 9px 12px;
  border: 0;
  box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .26);
  background: transparent;
  color: var(--cream);
  font: inherit;
  font-size: .95rem;
  color-scheme: dark;
}

.pickday input:focus-visible { outline: 2px solid var(--acid); outline-offset: 2px; }

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

.deep { margin: 56px 0 0; }

.deep-eyebrow {
  margin: 0 0 4px;
  font-family: var(--sign);
  font-weight: 600;
  font-size: .86rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--acid);
}

.deep-head {
  margin: 0 0 20px;
  font-family: var(--sign);
  font-weight: 900;
  font-size: 1.55rem;
  line-height: 1.1;
  color: var(--cream);
}

.deep-item { border-top: 1px solid rgba(239, 231, 210, .13); }
.deep-item:last-of-type { border-bottom: 1px solid rgba(239, 231, 210, .13); }

.deep-item > summary {
  position: relative;
  padding: 15px 30px 15px 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--sign);
  font-weight: 600;
  font-size: 1.1rem;
  color: rgba(239, 231, 210, .88);
}

.deep-item > summary::-webkit-details-marker { display: none; }

.deep-item > summary::after {
  content: "";
  position: absolute;
  right: 6px;
  top: 50%;
  width: 9px;
  height: 9px;
  margin-top: -6px;
  border-right: 2px solid var(--acid);
  border-bottom: 2px solid var(--acid);
  transform: rotate(45deg);
}

.deep-item[open] > summary::after { transform: rotate(-135deg); margin-top: -2px; }

.deep-body {
  padding: 0 0 18px;
  font-size: .95rem;
  line-height: 1.62;
  color: rgba(239, 231, 210, .72);
}

.deep-body p { margin: 0 0 .9em; }
.deep-body p:last-child { margin-bottom: 0; }
.deep-body b { color: var(--cream); font-weight: 500; }

/* ------------------------------------------------------------------ sharing */

.share { margin: 40px 0 0; }
.share[hidden] { display: none; }

.share-heading {
  margin: 0 0 10px;
  font-family: var(--sign);
  font-weight: 600;
  font-size: .92rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: rgba(239, 231, 210, .5);
}

.share-row { display: flex; flex-wrap: wrap; gap: 8px; }

.share-btn {
  display: inline-flex;
  align-items: center;
  padding: 10px 15px;
  border: 0;
  border-radius: 2px;
  background: var(--brand, #3A3E47);
  color: #fff;
  cursor: pointer;
  font-family: var(--sign);
  font-weight: 600;
  font-size: .95rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  text-decoration: none;
  transition: transform .12s, filter .12s;
}

.share-btn:hover, .share-btn:focus-visible { transform: translateY(-2px); filter: brightness(1.12); }

.share-copy, .share-more {
  background: transparent;
  color: rgba(239, 231, 210, .82);
  box-shadow: inset 0 0 0 1.5px rgba(239, 231, 210, .3);
}

.share-copy.done { background: var(--acid); color: #14161C; box-shadow: none; }

/* --------------------------------------------------------------------- ads */

.ad-slot { margin: 40px 0 0; min-height: 280px; }
.ad-slot[hidden] { display: none; }

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

footer {
  margin: 56px calc(var(--gutter) * -1) 0;
  padding: 28px var(--gutter) 34px;
  background: rgba(11, 11, 14, .62);
  border-top: 1px solid rgba(239, 231, 210, .12);
}

.foot-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 18px;
  margin: 0 0 14px;
}

.foot-nav a {
  font-family: var(--sign);
  font-weight: 600;
  font-size: .92rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(239, 231, 210, .5);
  text-decoration: none;
}

.foot-nav a:hover { color: var(--cream); }

.credit {
  margin: 0 0 8px;
  font-size: .82rem;
  color: rgba(239, 231, 210, .45);
}

.disclaimer {
  margin: 0;
  max-width: 46em;
  font-size: .66rem;
  line-height: 1.55;
  color: rgba(239, 231, 210, .26);
  transition: color .18s;
}

.disclaimer:hover { color: rgba(239, 231, 210, .6); }

@media (min-width: 720px) {
  :root { --gutter: 28px; }
  footer { margin-left: -28px; margin-right: -28px; }
}

/* ------------------------------------------------------------------ motion

   The vinyl turns and the label does not. That is a lie about physics and a
   deliberate one: at any speed fast enough to read as motion, text riding the
   label is unreadable, and the label is the part of this page people have to
   read. So the grooves, the sheen and the strobe rotate; the number stays put.

   Everything here is what prefers-reduced-motion exists to switch off, so it
   is opt-in rather than opt-out — the default below is a still record. */

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

  .grooves { animation: spin 18s linear infinite; }
  .sheen   { animation: spin 26s linear infinite reverse; }

  /* a hair off the grooves, which is exactly what a strobe ring shows you
     when the platter is running fractionally fast */
  .strobe  { animation: spin 17.4s linear infinite; }

  @keyframes spin { to { transform: rotate(360deg); } }

  /* the arm settles rather than arriving, the way a real one does */
  .tonearm .arm,
  .tonearm .head { transition: transform .75s cubic-bezier(.34, 1.4, .5, 1); }

  .picked .tonearm .arm  { transform: rotate(17deg); }
  .picked .tonearm .head { transform: rotate(17deg) translate(-14%, 8%); }

  .sleeve { animation: pull .5s ease-out both; }

  @keyframes pull {
    from { opacity: 0; transform: translateY(14px) rotate(-1.4deg); }
    to   { opacity: 1; transform: none; }
  }

  .label { transition: background .3s; }
}
