/* Shared look for the account, diary and club pages. Same Full Bleed design
   as the spinner. Dark is the default theme and light is a choice
   (data-theme on <html>, set by theme.js). Pages that show one album, the
   spinner and a club's round, also take their colors from its cover: script
   overrides these same variables. */
/* The two typefaces, served from this site (public/fonts, from Fontsource;
   SIL Open Font License) so the first paint does not wait on another
   company's servers. Accented letters beyond Latin-1 load only when a page
   uses them. */
@font-face { font-family: "Bricolage Grotesque"; font-style: normal; font-weight: 200 800; font-display: swap; src: url(/fonts/bricolage-grotesque-latin-v5.woff2) format("woff2"); unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: "Bricolage Grotesque"; font-style: normal; font-weight: 200 800; font-display: swap; src: url(/fonts/bricolage-grotesque-latin-ext-v5.woff2) format("woff2"); unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
@font-face { font-family: "Instrument Sans"; font-style: normal; font-weight: 400 700; font-display: swap; src: url(/fonts/instrument-sans-latin-v5.woff2) format("woff2"); unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; }
@font-face { font-family: "Instrument Sans"; font-style: normal; font-weight: 400 700; font-display: swap; src: url(/fonts/instrument-sans-latin-ext-v5.woff2) format("woff2"); unicode-range: U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF; }
:root {
  color-scheme: dark;
  --bg: #131313; --fg: #f6f4ee; --soft: rgba(246,244,238,.75); --line: rgba(246,244,238,.22); --chip: rgba(246,244,238,.06);
  --disp: "Bricolage Grotesque", "Helvetica Neue", Arial, sans-serif;
  --body: "Instrument Sans", system-ui, sans-serif;
}
:root[data-theme="light"] {
  color-scheme: light;
  --bg: #f1efe9; --fg: #121212; --soft: rgba(18,18,18,.68); --line: rgba(18,18,18,.2); --chip: rgba(18,18,18,.05);
}
* { box-sizing: border-box; }
html, body { min-height: 100%; }
/* Reserve the scrollbar's space so short and long pages line up. */
html { scrollbar-gutter: stable; }
body {
  margin: 0; background: var(--bg); color: var(--fg); font: 16px/1.4 var(--body);
  transition: background .6s ease, color .6s ease;
  padding: max(24px, env(safe-area-inset-top)) 16px max(40px, env(safe-area-inset-bottom));
}
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: inherit; }
:focus-visible { outline: 3px solid var(--fg); outline-offset: 3px; }
[hidden] { display: none !important; }

/* minmax(0, 1fr) lets wide content shrink to the screen instead of pushing the page wider. */
.wrap {
  max-width: 1240px; margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px; align-content: start;
}
/* Narrow pages keep the full-width header, so it sits in the same place everywhere. */
main.narrow { max-width: 760px; width: 100%; margin-inline: auto; }
/* Under an album (the album of the day) the column lines up with the cover's left edge instead. */
.hero + main.narrow { margin-inline: 0; }
/* Same height on every page, with or without the spinner's Filters button. */
header { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; min-height: 40px; }
/* The logo: the record mark, drawn in the text color by using the image as
   a mask so it follows the cover's palette, then the name. */
.brand {
  display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; text-decoration: none;
  font: 800 23px/1 var(--disp); letter-spacing: -.045em;
}
.brand::before {
  content: ""; flex: none; width: 27px; height: 27px; background: currentColor;
  -webkit-mask: url(/spin-mark.svg) center / contain no-repeat; mask: url(/spin-mark.svg) center / contain no-repeat;
}
.nav { display: flex; align-items: center; gap: 4px 18px; flex-wrap: wrap; font-size: 14px; font-weight: 600; }
.nav a { text-decoration: none; padding: 6px 0; }
.nav a:hover, .nav a[aria-current="page"] { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1.5px; }
/* The account: a circle with the person's initial. To look centered the
   letter is centered by its capital height alone (text-box trims the empty
   room fonts leave above capitals and below the baseline), and the sizes
   leave a whole number of pixels on every side: a 30px circle whose ring is
   drawn inside it, around a 14px letter whose capitals are 10px tall. */
.nav .me {
  width: 30px; height: 30px; padding: 0; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--line);
  display: inline-grid; place-items: center; font-size: 14px; font-weight: 700; line-height: 1; text-decoration: none !important;
}
.nav .me span { display: block; text-box: trim-both cap alphabetic; }
.nav .me:hover, .nav .me[aria-current="page"] { background: var(--fg); color: var(--bg); box-shadow: none; }

.pill {
  background: transparent; color: var(--fg); border: 1.5px solid var(--line); border-radius: 999px;
  padding: 8px 16px; font-weight: 600; font-size: 14px; text-decoration: none; display: inline-block;
}
.pill:hover { border-color: var(--fg); }
.pill.solid, .pill.active { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.pill:disabled { opacity: .45; cursor: default; }
.linkish { background: none; border: 0; padding: 0; font-size: 14px; font-weight: 600; text-decoration: underline; text-underline-offset: 3px; color: var(--soft); }
.linkish:hover { color: var(--fg); }
/* The Account page's footer: credits, privacy and the theme switch (Spin.footer in social.js). */
.foot {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 24px;
  border-top: 1.5px solid var(--line); padding-top: 16px; font-size: 13px; color: var(--soft);
}
.foot .linkish { font-size: 13px; }
.foot-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; min-width: 0; }

/* ---------- album hero ---------- */
/* Shared by the spinner and the club pages (Spin.albumHero in social.js).
   The cover is as large as the window allows while the spinner's button stays in view. */
.hero { display: grid; grid-template-columns: min(45%, max(260px, calc(100vh - 376px))) minmax(0, 1fr); gap: clamp(20px, 4vw, 56px); align-items: end; }
.cover {
  aspect-ratio: 1; width: 100%; overflow: hidden; display: grid; place-items: center;
  background: var(--line); box-shadow: 0 30px 60px -20px rgba(0,0,0,.45);
  transition: transform .5s cubic-bezier(.2,.8,.2,1), opacity .25s;
}
.cover.out { transform: translateY(16px) rotate(-2deg); opacity: 0; }
/* Cover still downloading: a tile with the album's title that gently pulses in place. */
.cover.waiting { transform: none; opacity: 1; animation: pulse 1.2s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .45; } }
.cover img { width: 100%; height: 100%; object-fit: cover; display: block; animation: arrive .35s ease-out; }
@keyframes arrive { from { opacity: 0; } }
.cover .none { padding: 12%; font: 800 clamp(22px, 4vw, 44px)/.95 var(--disp); letter-spacing: -.03em; text-wrap: balance; overflow-wrap: anywhere; opacity: .55; }
.txt { display: grid; gap: 14px; min-width: 0; }
.eyebrow { font-size: 14px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; color: var(--soft); font-variant-numeric: tabular-nums; }
h1 {
  font: 800 clamp(40px, 7vw, 112px)/.88 var(--disp); font-variation-settings: "opsz" 96;
  letter-spacing: -.045em; margin: 0; text-wrap: balance; overflow-wrap: anywhere;
}
h1.long { font-size: clamp(30px, 4.4vw, 68px); line-height: .94; letter-spacing: -.035em; }
h1.xlong { font-size: clamp(24px, 3vw, 44px); line-height: 1; letter-spacing: -.03em; }
h1.page { font-size: clamp(40px, 7vw, 88px); line-height: .9; }
.artist { font: 500 clamp(20px, 2.6vw, 32px)/1.1 var(--disp); margin: 0; letter-spacing: -.01em; overflow-wrap: anywhere; }
.tags { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 15px; color: var(--soft); min-height: 21px; }
.tags span::before, .tags button::before { content: "#"; opacity: .6; }
/* Tags as buttons (the spinner): plain text until pointed at. */
.tags button { background: none; border: 0; padding: 0; font: inherit; color: inherit; letter-spacing: inherit; text-align: left; }
/* The "#" is fainter than the word, so an underline through both looks
   uneven: as an inline block it stays out of the underline, which then runs
   under the word alone. */
.tags button::before { display: inline-block; }
.tags button:hover { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
.listen { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 14px; font-weight: 600; min-height: 20px; }
/* "Listen" and "Read" in front of each row of links. */
.listen .lead-in { color: var(--soft); font-weight: 500; min-width: 44px; }
.listen.about { margin-top: -6px; }
.listen:empty { display: none; }

/* ---------- sections ---------- */
.section { border-top: 1.5px solid var(--line); padding-top: 20px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
.section > h2, .label {
  margin: 0; font: 700 13px var(--body); letter-spacing: .1em; text-transform: uppercase; color: var(--soft);
}
.lead { font: 600 clamp(20px, 2.4vw, 28px)/1.15 var(--disp); letter-spacing: -.015em; margin: 0; text-wrap: balance; }
.muted { color: var(--soft); font-size: 14px; margin: 0; }
.error { font-weight: 600; margin: 0; }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.cols { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 28px clamp(24px, 4vw, 56px); align-items: start; }
.stack { display: grid; grid-template-columns: minmax(0, 1fr); gap: 28px; min-width: 0; }

/* The spin button is a record pressed from the current cover: vinyl marbled
   from the cover's strongest colors, around a label in the page's background
   color that carries the button's words and stays still. Spin.record in
   social.js adds the disc and keeps it turning; Spin.pressRecord sets --vinyl
   whenever a cover is shown. Before any cover the disc is the text color. */
.spin {
  position: relative; isolation: isolate; flex: none; width: 136px; height: 136px; padding: 0; border: 0; border-radius: 50%;
  background: none; color: var(--fg); font: 800 15px/1.05 var(--disp); letter-spacing: -.01em;
  display: grid; place-items: center; white-space: pre-line; text-align: center;
  filter: drop-shadow(0 14px 22px rgba(0,0,0,.4));
  transition: transform .35s cubic-bezier(.3,1.6,.5,1), color .6s ease;
}
.spin .disc {
  position: absolute; inset: 0; z-index: -2; border-radius: 50%; box-shadow: 0 0 0 1.5px var(--line);
  background:
    /* two soft bands of light across the grooves */
    conic-gradient(from 25deg, transparent 0 7%, rgba(255,255,255,.26) 14%, transparent 21% 53%, rgba(255,255,255,.18) 62%, transparent 70%),
    repeating-radial-gradient(circle, transparent 0 2.5px, rgba(0,0,0,.18) 2.5px 3.5px),
    var(--vinyl, var(--fg));
}
/* The label in the middle, under the words. */
.spin::before {
  content: ""; position: absolute; inset: 25%; z-index: -1; border-radius: 50%; background: var(--bg);
  box-shadow: 0 0 0 3px rgba(0,0,0,.3);
  transition: background .6s ease;
}
.spin:hover { transform: scale(1.06); }
.spin:active { transform: scale(.95); }
.spin:disabled { opacity: .4; transform: none; cursor: default; }

/* ---------- forms ---------- */
.field { display: grid; gap: 6px; }
.field > span, .field > legend { font-size: 14px; font-weight: 600; padding: 0; }
.field > legend { margin-bottom: 6px; }
fieldset.field { border: 0; margin: 0; padding: 0; min-width: 0; }
input[type="text"], input[type="email"], input[type="number"], input[type="date"], textarea, select {
  width: 100%; background: transparent; border: 1.5px solid var(--line); border-radius: 12px; padding: 10px 12px;
}
input::placeholder, textarea::placeholder { color: var(--soft); opacity: 1; }
textarea { min-height: 96px; resize: vertical; }
select { appearance: none; }
input:focus, textarea:focus, select:focus { border-color: var(--fg); outline: none; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chips button {
  background: transparent; color: var(--fg); border: 1.5px solid var(--line); border-radius: 999px;
  padding: 7px 13px; font-size: 14px; font-weight: 500; display: inline-flex; gap: 6px; align-items: baseline;
}
.chips button:hover:not(:disabled) { border-color: var(--fg); }
.chips button[aria-pressed="true"] { background: var(--fg); color: var(--bg); border-color: var(--fg); }
/* Album counts on filter chips. */
.chips button small { color: var(--soft); font-size: 12px; font-variant-numeric: tabular-nums; }
.chips button small:empty { display: none; }
.chips button[aria-pressed="true"] small { color: inherit; opacity: .75; }
.chips button:disabled { opacity: .4; cursor: default; }
.scores { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 6px; max-width: 520px; }
.scores button {
  aspect-ratio: 1; min-width: 0; padding: 0; border-radius: 50%; border: 1.5px solid var(--line); background: transparent;
  font: 700 clamp(14px, 2vw, 18px) var(--disp); font-variant-numeric: tabular-nums;
}
.scores button[aria-pressed="true"] { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.inline { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.inline input { flex: 1 1 200px; width: auto; }
.inline input[type="number"] { flex: 0 0 90px; }

/* ---------- lists ---------- */
.big { font: 800 clamp(56px, 9vw, 120px)/.85 var(--disp); letter-spacing: -.05em; font-variant-numeric: tabular-nums; }
.stats { display: flex; flex-wrap: wrap; gap: 20px 48px; align-items: end; }
.review { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 4px 16px; align-items: start; }
.review .score { font: 800 40px/1 var(--disp); letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.review .name { font-weight: 700; }
.review p { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.comment { display: grid; gap: 4px; }
.comment p { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.comment .replies { display: grid; gap: 12px; margin: 8px 0 0 20px; padding-left: 16px; border-left: 1.5px solid var(--line); }
.rows { display: grid; gap: 12px; list-style: none; margin: 0; padding: 0; }
.rows li { display: flex; gap: 12px; align-items: center; justify-content: space-between; min-width: 0; }
.albumrow { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; gap: 14px; align-items: center; text-decoration: none; }
.albumrow img, .albumrow .ph { width: 56px; height: 56px; object-fit: cover; background: var(--line); display: block; }
.albumrow b { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.albumrow span { display: block; color: var(--soft); font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.albumrow .num { font: 800 28px/1 var(--disp); letter-spacing: -.04em; font-variant-numeric: tabular-nums; }
.albumrow.skipped b { text-decoration: line-through; }
/* Lines up with the text of an album row, past its cover. */
.indent { margin-left: 70px; }
.section > .stack + .stack { border-top: 1.5px solid var(--line); padding-top: 14px; }
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 16px; }
.card { border: 1.5px solid var(--line); border-radius: 18px; padding: 18px; display: grid; gap: 10px; text-decoration: none; }
.card:hover { border-color: var(--fg); }
.card h3 { font: 800 24px/1 var(--disp); letter-spacing: -.03em; margin: 0; overflow-wrap: anywhere; }
/* The status lines sit at the bottom, so cards in a row line up whatever their album. */
.card { align-content: start; }
.box { border: 1.5px solid var(--line); border-radius: 18px; padding: 18px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
.copy { display: flex; gap: 10px; align-items: center; }
.copy input { flex: 1; min-width: 0; font-size: 14px; }
details > summary { cursor: pointer; font-weight: 600; }
details[open] > summary { margin-bottom: 16px; }

@media (max-width: 760px) {
  .hero, .cols { grid-template-columns: minmax(0, 1fr); }
  .hero .cover { width: min(100%, 420px); }
  .spin { width: 124px; height: 124px; font-size: 14px; }
}
/* Phones: keep the header on one line, so it is the same height everywhere. */
@media (max-width: 480px) {
  .nav { gap: 4px 12px; }
  .nav .home { display: none; }
  .brand { font-size: 20px; gap: 6px; }
  .brand::before { width: 24px; height: 24px; }
}
/* Phones up to the widest: the mark alone, since five tabs and the name do
   not fit on one line. The narrowest also close up the tabs a little. */
@media (max-width: 429px) { .brand { font-size: 0; gap: 0; } }
@media (max-width: 345px) { .nav { gap: 4px 9px; } }
/* Each page's content (see "tabs" in social.js), and a page kept for later
   while another one is on screen. */
.view { display: contents; }
.view-off { display: none !important; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 0s !important; animation: none !important; }
}
/* The pages that still load in full (signing in, an invite, privacy) fade
   into the next instead of flashing blank, and the header holds still. The
   main tabs swap in place instead (see social.js). Kept short so it reads
   as quick, and left out for anyone who asks for less motion. */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  header { view-transition-name: header; }
  ::view-transition-group(*) { animation-duration: .15s; }
}

/* ---------- text pages (privacy) ---------- */
.prose p, .prose ul { margin: 0; max-width: 64ch; }
.prose ul { padding-left: 20px; display: grid; gap: 6px; }

/* Score spread: ten thin bars over the scores 1 to 10 (Spin.scoreBars). */
.bars { display: grid; grid-template-columns: repeat(10, minmax(0, 1fr)); gap: 6px; max-width: 520px; height: 96px; }
.bar { display: grid; grid-template-rows: minmax(0, 1fr) auto; gap: 6px; justify-items: center; }
.bar i { align-self: end; width: min(100%, 22px); background: var(--fg); border-radius: 4px 4px 0 0; }
.bar span { font-size: 12px; color: var(--soft); font-variant-numeric: tabular-nums; }

/* Signed-out Diary and Clubs: what the page is for, before the sign-in wall. */
.steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; list-style: none; margin: 0; padding: 0; counter-reset: step; }
.steps li { border: 1.5px solid var(--line); border-radius: 18px; padding: 18px; display: grid; gap: 6px; align-content: start; counter-increment: step; }
.steps li::before { content: counter(step); font: 800 34px/1 var(--disp); letter-spacing: -.04em; }
.steps b { font: 700 18px/1.15 var(--disp); letter-spacing: -.01em; }
.steps span { color: var(--soft); font-size: 14px; }

/* Loading: grey shapes that pulse where content is on its way (Spin.skeleton). */
.sk { background: var(--line); border-radius: 10px; animation: pulse 1.2s ease-in-out infinite; }
.sks { gap: 16px; }
.sk.lead { height: 30px; width: min(100%, 440px); }
.sk.line { height: 14px; width: min(70%, 320px); }
/* Lines of text, by the size of the text they stand for, and an album row's cover. */
.sk.text { height: 13px; border-radius: 7px; }
.sk.heading { height: 24px; border-radius: 8px; }
.sk.w40 { width: 40%; } .sk.w60 { width: 60%; } .sk.w80 { width: 80%; }
.sk.cover-sm { width: 56px; height: 56px; border-radius: 0; }
.sk.pill { height: 38px; width: 124px; border-radius: 999px; }
/* A text box, a page title and a paragraph's worth of lines. */
.sk.input { height: 44px; border-radius: 12px; flex: 1 1 200px; }
.sk.title { height: clamp(36px, 6.3vw, 79px); border-radius: 12px; }
.sk.pill.wide { width: 196px; }
.sk.pill.small { width: 76px; }
.sks.para { gap: 7px; }
/* A club card's outline keeps the real card's border; only its contents pulse. */
.card.loading { pointer-events: none; }
/* Each bar takes the room of the line of text it stands for, so the card is the real card's height. */
.card.loading > .sk.text { margin: 3.5px 0; }
.sk.box { height: 220px; border-radius: 18px; }
.sk.scores { height: 44px; width: min(100%, 520px); border-radius: 999px; }
.nav .me.sk { box-shadow: none; }
