/* ─── Tokens ──────────────────────────────────────────────────────── */
:root{
  --bg:#12100e;
  --bg-2:#1a1715;
  --raised:#221e1b;
  --line:#332d28;
  --ink:#f3ede6;
  --ink-2:#a89c90;
  --ink-3:#6f645b;
  --accent:#d97a45;
  --accent-soft:#3a251a;
  --danger:#e0604f;
  --radius:14px;
  --shadow:0 18px 40px -12px rgba(0,0,0,.75);
  color-scheme:dark;
}

*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
html{background:var(--bg)}
body{
  margin:0;
  padding:env(safe-area-inset-top,0) 0 env(safe-area-inset-bottom,0);
  background:none;
  color:var(--ink);
  font:15px/1.5 ui-sans-serif,-apple-system,"Segoe UI",Inter,system-ui,sans-serif;
  min-height:100vh;
}
img{max-width:100%;display:block}
[hidden]{display:none !important}
h1,h2{margin:0;font-weight:650;letter-spacing:-.02em}
/* Every icon in the app is a line drawing, so they're reset in one go. The
   exception is a brand mark like Google's G, which is filled and multi-colour
   and has to keep its own fills — hence the :not(). */
svg:not(.brandmark){width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.brandmark{flex:none}

/* ─── Backdrop ────────────────────────────────────────────────────── */
/* A fixed photo layer plus a scrim. The scrim is doing real work: the record
   sleeves have to stay the brightest thing on screen, so the photo is dimmed,
   desaturated and softened until it reads as depth rather than detail. */
.backdrop{position:fixed;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.backdrop::before{
  content:"";position:absolute;inset:-4%;
  background:url("assets/crates.jpg") center 38%/cover no-repeat;
  filter:saturate(.85) brightness(.95) blur(1px);
}
.backdrop::after{
  content:"";position:absolute;inset:0;
  background:
    radial-gradient(125% 85% at 50% 0%, rgba(18,16,14,.10), rgba(18,16,14,.62) 74%),
    linear-gradient(180deg, rgba(18,16,14,.30) 0%, rgba(18,16,14,.56) 45%, rgba(18,16,14,.80) 100%);
}
@media (max-width:760px){
  .backdrop::before{background-image:url("assets/crates-small.jpg")}
}
/* Someone who asked for less motion/effect still gets a readable page. */
@media (prefers-reduced-transparency:reduce){
  .backdrop::after{background:rgba(18,16,14,.94)}
}

/* ─── Buttons & fields ────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;gap:7px;
  border:1px solid var(--line);background:var(--raised);color:var(--ink);
  padding:9px 14px;border-radius:10px;font:inherit;font-weight:550;
  cursor:pointer;white-space:nowrap;transition:background .15s,border-color .15s,transform .1s;
}
.btn:hover{background:#2b2622;border-color:#463e37}
.btn:active{transform:translateY(1px)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#1a0e07}
.btn.primary:hover{background:#e68a55;border-color:#e68a55}
.btn.ghost{background:transparent}
.btn.ghost:hover{background:#ffffff0d}
.btn.danger{color:var(--danger);border-color:transparent}
.btn.danger:hover{background:#e0604f1a}
.btn.icon{padding:9px}
.btn.big{padding:12px 20px;font-size:16px}

.field{
  display:flex;align-items:center;gap:8px;
  background:var(--bg-2);border:1px solid var(--line);border-radius:10px;
  padding:0 12px;color:var(--ink-3);min-width:0;
}
.field:focus-within{border-color:var(--accent);color:var(--ink-2)}
.field input{
  border:0;background:none;color:var(--ink);font:inherit;
  padding:9px 0;outline:none;width:180px;min-width:0;
}
.field.grow{flex:1}
.field.grow input{width:100%;font-size:17px;padding:14px 0}
input[type=search]::-webkit-search-cancel-button{filter:invert(.6)}

select{
  background:var(--bg-2);border:1px solid var(--line);color:var(--ink);
  font:inherit;padding:9px 10px;border-radius:10px;cursor:pointer;outline:none;
}
select:focus{border-color:var(--accent)}

.hint{color:var(--ink-3);margin:0}

/* ─── Top bar ─────────────────────────────────────────────────────── */
.topbar{
  position:sticky;top:env(safe-area-inset-top,0);z-index:30;
  display:flex;flex-wrap:wrap;gap:14px;align-items:center;justify-content:space-between;
  padding:14px clamp(16px,4vw,36px);
  background:#12100eb8;backdrop-filter:blur(16px) saturate(.9);
  border-bottom:1px solid var(--line);
}
.brand{display:flex;align-items:center;gap:11px;min-width:0}
.brand h1{font-size:19px}
.count{color:var(--ink-3);font-variant-numeric:tabular-nums;font-size:13px}
.controls{display:flex;flex-wrap:wrap;gap:9px;align-items:center}

.disc{
  width:22px;height:22px;border-radius:50%;flex:none;
  background:
    radial-gradient(circle at 50% 50%, var(--accent) 0 14%, #12100e 15% 22%, transparent 23%),
    repeating-radial-gradient(circle at 50% 50%, #2a2521 0 1.5px, #171412 1.5px 3px);
  box-shadow:inset 0 0 0 1px #000;
}
.disc.big{width:64px;height:64px}

/* ─── Shelf grid ──────────────────────────────────────────────────── */
.shelf{
  position:relative;z-index:1;
  display:grid;gap:clamp(16px,2.4vw,30px);
  grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  padding:clamp(20px,4vw,40px) clamp(16px,4vw,36px) 80px;
  max-width:1680px;margin:0 auto;
}
@media (min-width:700px){.shelf{grid-template-columns:repeat(auto-fill,minmax(190px,1fr))}}

.record{
  all:unset;cursor:pointer;display:block;position:relative;
  border-radius:4px;
}
.record:focus-visible{outline:2px solid var(--accent);outline-offset:6px}

.sleeve{
  position:relative;aspect-ratio:1;border-radius:3px;
  background:var(--bg-2);
  box-shadow:var(--shadow), inset 0 0 0 1px #ffffff12;
  transition:transform .35s cubic-bezier(.2,.8,.3,1), box-shadow .35s;
}
.sleeve img{
  width:100%;height:100%;object-fit:cover;border-radius:3px;
  position:relative;z-index:2;background:var(--bg-2);
}
/* the record sliding out from behind the sleeve */
.vinyl{
  position:absolute;inset:6% 0 6% auto;right:0;aspect-ratio:1;z-index:1;
  border-radius:50%;
  background:
    radial-gradient(circle at 50% 50%, #9c8a7a 0 4%, #0d0b0a 5% 9%, transparent 10%),
    repeating-radial-gradient(circle at 50% 50%, #221e1b 0 2px, #100e0d 2px 4px),
    #15120f;
  box-shadow:0 8px 20px rgba(0,0,0,.6);
  transition:transform .4s cubic-bezier(.2,.8,.3,1);
  transform:translateX(0) rotate(0deg);
}
.record:hover .sleeve, .record:focus-visible .sleeve{transform:translateY(-6px)}
.record:hover .vinyl, .record:focus-visible .vinyl{transform:translateX(26%) rotate(45deg)}

.record .label{margin-top:11px;display:flex;gap:8px;align-items:flex-start}
.record .label .txt{min-width:0;flex:1}
.record .title{
  font-weight:600;font-size:14px;line-height:1.3;
  text-shadow:0 1px 4px rgba(0,0,0,.55);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.record .artist{
  color:var(--ink-2);font-size:13px;
  text-shadow:0 1px 4px rgba(0,0,0,.55);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.pip{
  flex:none;margin-top:4px;width:7px;height:7px;border-radius:50%;
  background:var(--accent);box-shadow:0 0 0 3px var(--accent-soft);
}

/* ─── Empty state ─────────────────────────────────────────────────── */
.empty{
  position:relative;z-index:1;
  display:grid;justify-items:center;gap:10px;text-align:center;
  padding:12vh 24px;color:var(--ink-2);
}
.empty h2{font-size:22px;color:var(--ink);margin-top:6px;text-shadow:0 2px 12px rgba(0,0,0,.6)}
.empty p{margin:0;max-width:34ch;text-shadow:0 2px 10px rgba(0,0,0,.6)}
.empty .btn{margin-top:14px}

/* ─── Dialogs ─────────────────────────────────────────────────────── */
.scrim{
  position:fixed;inset:0;z-index:50;
  display:flex;align-items:flex-start;justify-content:center;
  padding:clamp(12px,5vh,64px) 16px;
  background:#08070699;backdrop-filter:blur(8px);
  overflow-y:auto;overscroll-behavior:contain;
  animation:fade .18s ease;
}
@keyframes fade{from{opacity:0}}
@keyframes rise{from{opacity:0;transform:translateY(14px)}}

.sheet{
  width:min(760px,100%);background:var(--bg-2);
  border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);animation:rise .22s cubic-bezier(.2,.8,.3,1);
  display:flex;flex-direction:column;overflow:hidden;
}
.sheet.narrow{width:min(460px,100%)}
.sheet-head{display:flex;gap:10px;align-items:center;padding:12px;border-bottom:1px solid var(--line)}
.sheet-head h2{font-size:17px;flex:1;padding-left:4px}
.sheet-foot{
  display:flex;gap:10px;align-items:center;padding:12px 16px;
  border-top:1px solid var(--line);background:#00000026;
}
.sheet-foot.end{justify-content:flex-end}

/* search results */
.results{
  padding:14px;min-height:140px;max-height:min(58vh,560px);overflow-y:auto;
  display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));
  align-content:start;
}
.results .hint,.results .spinner{grid-column:1/-1;text-align:center;padding:36px 0}
.result{all:unset;cursor:pointer;display:block;border-radius:4px}
.result:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.result img{
  width:100%;aspect-ratio:1;object-fit:cover;border-radius:3px;background:var(--raised);
  box-shadow:0 8px 18px -6px #000;transition:transform .2s;
}
.result:hover img{transform:scale(1.04)}
/* Fixed heights for the three text lines, so the covers in every row sit on
   the same baseline however long the titles are. A title runs to two lines
   before it gets cut. */
.result .t{
  font-size:13px;font-weight:550;margin-top:8px;line-height:1.3;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;
  overflow:hidden;min-height:2.6em;
}
.result .a{
  font-size:12px;color:var(--ink-2);line-height:1.35;min-height:1.35em;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.result .y{font-size:11px;color:var(--ink-3);line-height:1.4;min-height:1.4em}
.result.owned{opacity:.4;pointer-events:none}
.result.owned .t::after{content:" · on shelf";color:var(--accent);font-weight:400}

.spinner::after{
  content:"";display:inline-block;width:22px;height:22px;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--accent);
  animation:spin .7s linear infinite;
}
@keyframes spin{to{transform:rotate(1turn)}}

/* manual form */
.form-body{padding:16px;display:grid;gap:14px}
.stack{display:grid;gap:6px}
.stack>span{font-size:12px;color:var(--ink-2);text-transform:uppercase;letter-spacing:.07em}
.stack input,.stack textarea{
  background:var(--bg);border:1px solid var(--line);border-radius:9px;
  color:var(--ink);font:inherit;padding:10px 12px;outline:none;width:100%;
}
.stack input:focus,.stack textarea:focus{border-color:var(--accent)}
.stack textarea{resize:vertical;line-height:1.6}
.row{display:grid;gap:14px;grid-template-columns:1fr 1fr}
.cover-preview img{width:120px;aspect-ratio:1;object-fit:cover;border-radius:4px}

/* ─── Detail view ─────────────────────────────────────────────────── */
.scrim.detail{align-items:center;padding:clamp(12px,4vh,40px) 12px}
.detail-card{
  position:relative;width:min(1320px,calc(100% - 116px));
  /* A definite height lets each column scroll on its own, so a 40-track
     reissue can't push the notes box off the bottom of the panel. */
  height:min(92vh,1000px);max-height:calc(100vh - 40px);
  background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);animation:rise .22s cubic-bezier(.2,.8,.3,1);
  display:grid;grid-template-columns:minmax(0,.82fr) minmax(0,1.18fr);
  overflow:hidden;
}

.detail-art{
  padding:clamp(20px,2.6vw,32px);
  display:flex;flex-direction:column;align-items:center;gap:clamp(16px,2vw,22px);
  background:radial-gradient(90% 60% at 50% 22%, #2a241f, #171412);
  overflow-y:auto;overscroll-behavior:contain;min-width:0;
}
.detail-art .sleeve{
  width:100%;max-width:276px;flex:none;      /* 40% down from 460px */
  box-shadow:0 22px 44px -16px #000, inset 0 0 0 1px #ffffff14;
}
.detail-art .vinyl{transform:translateX(18%) rotate(12deg)}
.detail-art .sleeve:hover{transform:none}

.detail-body{
  padding:clamp(20px,2.6vw,32px);display:flex;flex-direction:column;gap:14px;
  min-width:0;overflow-y:auto;overscroll-behavior:contain;
}

/* Stacked on a phone: one scroller for the whole panel. */
@media (max-width:900px){
  .detail-card{grid-template-columns:1fr;width:100%;height:auto;max-height:calc(100vh - 24px);overflow-y:auto}
  .detail-art,.detail-body{overflow:visible}
}
.eyebrow{margin:0;color:var(--accent);font-weight:600;font-size:13px;letter-spacing:.05em;text-transform:uppercase}
.detail-body h2{font-size:clamp(23px,3vw,31px);line-height:1.15}
.meta{margin:0;color:var(--ink-2);font-size:14px}
.thread{margin-top:2px;display:flex;flex-direction:column}
.thread h3{
  margin:0 0 10px;font-size:12px;font-weight:600;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-2);
  display:flex;align-items:baseline;gap:8px;
  padding-bottom:9px;border-bottom:1px solid var(--line);
}


/* The sleeve stays small and centred; the tracklist spans the whole column. */
.tracks{width:100%;align-self:stretch;flex:none}
.tracks h3{
  margin:0 0 10px;font-size:12px;font-weight:600;letter-spacing:.07em;
  text-transform:uppercase;color:var(--ink-2);
  display:flex;align-items:baseline;gap:8px;
  padding-bottom:9px;border-bottom:1px solid var(--line);
}
.tracks .tcount{font-weight:400;letter-spacing:0;text-transform:none;color:var(--ink-3)}
.tracks ol{
  margin:0;padding:0;list-style:none;counter-reset:trk;
  color:var(--ink-2);font-size:14px;display:grid;gap:1px;
}
.tracks li{border-radius:8px;line-height:1.35}
.tracks li:nth-child(odd) .track-row{background:#ffffff08}

.track-row{display:flex;gap:8px;align-items:center;border-radius:8px;padding-right:4px}
.track-row::before{
  counter-increment:trk;content:counter(trk);
  flex:none;width:22px;text-align:right;padding-left:4px;
  color:var(--ink-3);font-variant-numeric:tabular-nums;font-size:12px;
}
.track.is-open .track-row,.track-row:hover{background:#ffffff14}

/* the star */
.fav{
  all:unset;cursor:pointer;flex:none;
  width:24px;height:24px;display:grid;place-items:center;border-radius:6px;
  font-size:14px;line-height:1;color:var(--ink-3);opacity:.35;
  transition:opacity .15s,color .15s,transform .15s;
}
.track-row:hover .fav{opacity:.75}
.fav:hover{transform:scale(1.2);color:var(--accent);opacity:1}
.fav:focus-visible{outline:2px solid var(--accent);opacity:1}
.track.is-fav .fav{color:var(--accent);opacity:1}

/* the clickable body of the row */
.track-open{
  all:unset;cursor:pointer;flex:1;min-width:0;
  display:flex;gap:10px;align-items:baseline;padding:8px 0;
}
.track-open:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:6px}
.track .tname{flex:1;min-width:0;color:var(--ink)}
.track.is-fav .tname{color:var(--ink);font-weight:550}
.track .dur{color:var(--ink-3);font-variant-numeric:tabular-nums;flex:none;font-size:12px}

/* a dot when a track carries a note */
.note-pip{flex:none;width:5px;height:5px;border-radius:50%;background:transparent}
.track.has-note .note-pip{background:var(--accent);box-shadow:0 0 0 2px var(--accent-soft)}

/* the note itself */
.track-note{padding:4px 8px 10px 34px;display:grid;gap:7px}
.track-note textarea{
  width:100%;background:var(--bg);border:1px solid var(--accent);border-radius:8px;
  color:var(--ink);font:inherit;font-size:13px;padding:9px 11px;outline:none;
  resize:vertical;line-height:1.55;
}
.track-note-foot{display:flex;align-items:center;justify-content:space-between;gap:10px}
.track-note-foot em{font-style:normal;font-size:12px;color:var(--accent);opacity:0;transition:opacity .3s}
.track-note-foot em.show{opacity:1}
.btn.small{padding:5px 11px;font-size:12px}

.track-note-read{
  margin:0;padding:2px 10px 9px 34px;
  font-size:12.5px;line-height:1.55;color:var(--ink-2);
}
.tracks .tname{flex:1;min-width:0;color:var(--ink)}
.tracks .dur{color:var(--ink-3);font-variant-numeric:tabular-nums;flex:none}
.tracks .loading{color:var(--ink-3);padding:7px 10px}
.tracks .loading::before,.tracks .hint::before{content:none}
.tracks .loading::after{
  content:"";display:inline-block;vertical-align:-2px;margin-left:8px;
  width:12px;height:12px;border-radius:50%;
  border:2px solid var(--line);border-top-color:var(--accent);
  animation:spin .7s linear infinite;
}
.tracks .hint{padding:7px 10px}

.detail-foot{
  margin-top:auto;padding-top:12px;border-top:1px solid var(--line);
  display:flex;justify-content:flex-end;align-items:center;gap:12px;flex-wrap:wrap;
}
/* Leaving is on the right, so the way further in sits on the left. */
#dToBook{margin-right:auto;color:var(--ink-2);border-color:transparent}
#dToBook:hover{color:var(--ink)}
#dToBook svg{width:17px;height:17px;stroke-width:1.6}
.close.floating{position:absolute;top:10px;right:10px;z-index:5;background:#0f0d0cbf;backdrop-filter:blur(6px)}

.nav{
  all:unset;cursor:pointer;flex:none;align-self:center;
  width:44px;height:44px;display:grid;place-items:center;border-radius:50%;
  background:#ffffff12;color:var(--ink);margin:0 6px;transition:background .15s;
}
.nav:hover{background:#ffffff24}
.nav:disabled{opacity:.2;cursor:default}
.nav svg{width:22px;height:22px}
@media (max-width:820px){.nav{position:fixed;bottom:18px;z-index:60;background:#241f1ce6}.nav.prev{left:18px}.nav.next{right:18px}}

/* ─── Menu & toast ────────────────────────────────────────────────── */
.menu-wrap{position:relative}
.menu{
  position:absolute;right:0;top:calc(100% + 8px);z-index:40;
  background:var(--raised);border:1px solid var(--line);border-radius:11px;
  box-shadow:var(--shadow);padding:5px;display:grid;min-width:210px;
}
.menu button{
  all:unset;cursor:pointer;padding:9px 12px;border-radius:7px;font-size:14px;
}
.menu button:hover{background:#ffffff12}
.menu-who{
  margin:0;padding:8px 12px 9px;font-size:12px;color:var(--ink-3);
  border-bottom:1px solid var(--line);margin-bottom:4px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.menu button.sep{
  border-top:1px solid var(--line);border-radius:0 0 7px 7px;margin-top:4px;padding-top:11px;
}
/* The small print, kept small — findable from inside the app without being
   the first thing anyone opening this menu reads. */
.menu-legal{margin:2px 0 0;padding:6px 12px 4px;font-size:11.5px;color:var(--ink-3)}
.menu-legal a{color:var(--ink-3);text-decoration:none}
.menu-legal a:hover{color:var(--ink-2);text-decoration:underline}

/* ─── Signed in ───────────────────────────────────────────────────── */
/* Whose shelf this is, kept quiet — the menu carries the address. */
.avatar{
  width:30px;height:30px;border-radius:50%;object-fit:cover;flex:none;
  border:1px solid var(--line);background:var(--bg-2);
}

/* ─── Sign in ─────────────────────────────────────────────────────── */
/* Until /api/me answers, the app chrome stays down: a signed-in visitor
   should land on their shelf, not watch a sign-in screen flash past. */
body.booting>.topbar,
body.booting>.shelf,
body.booting>.crate,
body.booting>.empty{visibility:hidden}

/* Signed out there is no collection to put chrome around, so the toolbar goes
   rather than sitting greyed out behind the card. */
body.signed-out>.topbar,
body.signed-out>.shelf,
body.signed-out>.crate,
body.signed-out>.empty{display:none}

.gate{
  position:fixed;inset:0;z-index:90;display:grid;place-items:center;
  padding:24px;background:color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter:blur(3px);
}
.gate-card{
  display:grid;justify-items:center;gap:14px;text-align:center;
  max-width:400px;width:100%;
  background:var(--raised);border:1px solid var(--line);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:40px 28px 28px;
}
.gate-card h1{margin:0;font-size:26px;font-weight:650;letter-spacing:.06em}
/* Spells out the acronym once, on the way in. */
.expansion{
  margin:-8px 0 0;color:var(--accent);font-size:13px;
  letter-spacing:.04em;text-transform:lowercase;
}
.gate-sub{margin:0;color:var(--ink-2);font-size:14px;line-height:1.5}

/* What signing in signs you up to, said where the signing in happens. */
.gate-legal{margin:2px 0 0;color:var(--ink-3);font-size:12.5px;line-height:1.5}
.gate-legal a{color:var(--ink-2)}

.gate-error{
  margin:0;width:100%;padding:10px 12px;border-radius:9px;font-size:13px;line-height:1.45;
  background:var(--accent-soft);border:1px solid #5a3a28;color:#f0c9ae;
}

/* Google asks that its button carry its own colours rather than the app's. */
.btn.google{
  display:inline-flex;align-items:center;gap:11px;text-decoration:none;
  background:#fff;color:#1f1f1f;border:1px solid #dadce0;
  border-radius:10px;padding:11px 20px;font-size:15px;font-weight:500;
  margin-top:4px;
}
.btn.google:hover{background:#f6f8fc;border-color:#d2d6db}
.btn.google .brandmark{width:18px;height:18px}
.btn.google[aria-disabled="true"]{opacity:.45;pointer-events:none}

@media (max-width:480px){
  .gate-card{padding:32px 20px 24px}
}

.toast{
  position:fixed;left:50%;bottom:28px;transform:translateX(-50%);z-index:80;
  background:var(--raised);border:1px solid var(--line);border-radius:11px;
  padding:11px 18px;box-shadow:var(--shadow);animation:rise .2s;
  max-width:calc(100vw - 32px);
}

.results .spinner.more{grid-column:1/-1;padding:18px 0}
.results .hint.foot{grid-column:1/-1;text-align:center;font-size:12px;padding:4px 0 0}

/* ─── The age you were ────────────────────────────────────────────── */
.age{
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  font-size:14px;color:var(--ink-2);
}
.age label{cursor:pointer}
.age input{
  width:74px;background:var(--bg);border:1px solid var(--line);border-radius:9px;
  color:var(--ink);font:inherit;font-weight:600;font-size:16px;
  padding:7px 10px;outline:none;text-align:center;
  font-variant-numeric:tabular-nums;
}
.age input:focus{border-color:var(--accent)}
.age input::placeholder{color:var(--ink-3);font-weight:400}
.clear-age{
  all:unset;cursor:pointer;font-size:12px;color:var(--ink-3);
  padding:4px 8px;border-radius:6px;
}
.clear-age:hover{color:var(--ink);background:#ffffff0d}

/* the chip on each shelf tile */
.record .marks{display:flex;align-items:center;gap:7px;margin-top:3px;flex-wrap:wrap}
.age-chip{
  font-size:10px;font-weight:600;letter-spacing:.03em;
  color:var(--accent);background:var(--accent-soft);
  border:1px solid #4d2f1e;padding:1px 7px;border-radius:999px;
  white-space:nowrap;text-shadow:none;
}

/* ─── View switcher ───────────────────────────────────────────────── */
.views{display:flex;gap:2px;background:var(--bg-2);border:1px solid var(--line);border-radius:10px;padding:2px}
.view-btn{
  all:unset;cursor:pointer;display:inline-flex;align-items:center;gap:6px;
  padding:7px 11px;border-radius:8px;font-size:13px;font-weight:550;color:var(--ink-2);
  transition:background .15s,color .15s;
}
.view-btn:hover{color:var(--ink);background:#ffffff0d}
.view-btn.is-on{background:var(--raised);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line)}
.view-btn:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.view-btn svg{width:15px;height:15px}
@media (max-width:640px){.view-btn span{display:none}.view-btn{padding:7px 9px}}

/* ─── Crate view ──────────────────────────────────────────────────── */
.crate{
  position:relative;z-index:1;
  display:grid;grid-template-columns:minmax(0,1fr) clamp(300px,27vw,400px);
  gap:clamp(18px,3vw,34px);
  padding:clamp(20px,3.5vw,36px) clamp(16px,4vw,36px) 60px;
  max-width:1680px;margin:0 auto;align-items:start;
}
@media (max-width:900px){.crate{grid-template-columns:1fr}}

.rack-wrap{min-width:0}
.rack-hint{
  margin:14px 2px 0;font-size:12px;color:var(--ink-3);
  transition:opacity .3s;
}
.rack-hint.gone{opacity:0}

/* The crate itself: spines standing on a base, leaning slightly. */
.rack{
  display:flex;align-items:flex-end;gap:1px;
  height:clamp(300px,48vh,430px);
  /* hug the records rather than leaving an empty box beside them */
  width:max-content;max-width:100%;min-width:min(560px,100%);
  padding:26px 18px 0;
  border-radius:6px;
  background:
    linear-gradient(180deg,#0000 0 58%,#00000059 100%),
    linear-gradient(90deg,#00000066,#0000 5%,#0000 95%,#00000066),
    #14110f8f;
  box-shadow:
    inset 0 -16px 30px -14px #000,
    inset 0 0 0 1px #ffffff12,
    0 22px 44px -22px #000;
  overflow-x:auto;overflow-y:hidden;
  scrollbar-width:thin;scrollbar-color:var(--line) transparent;
}

.spine{
  all:unset;cursor:pointer;position:relative;flex:none;
  align-self:flex-end;transform-origin:50% 100%;
  border-radius:2px 2px 1px 1px;
  background-repeat:no-repeat;
  box-shadow:
    1px 0 3px -1px #000b,          /* the shadow it casts on its neighbour */
    inset -1px 0 2px -1px #000d,
    inset 1px 0 1px -1px #ffffff40;
  transition:transform .22s cubic-bezier(.2,.8,.3,1), filter .22s, box-shadow .22s;
  filter:brightness(.82) saturate(.92);
  overflow:hidden;
}
/* paper grain and the darkening down in the crate */
.spine::before{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(180deg,#ffffff12 0 1.5%,#0000 4% 46%,#00000066 100%),
    linear-gradient(90deg,#00000077 0,#0000 30%,#ffffff14 52%,#0000 72%,#00000088 100%);
}
/* the pale edge of an inner sleeve poking out past the card */
.spine.paper::after{
  content:"";position:absolute;top:2%;bottom:0;right:0;width:2px;
  background:linear-gradient(180deg,#e8dcc8b0,#c9b99cd0);
  box-shadow:-1px 0 2px #0009;
}

.spine:hover,.spine.is-on{
  filter:brightness(1.12) saturate(1.05);
  box-shadow:4px 0 14px -2px #000c, inset 2px 0 2px -2px #ffffff55;
  z-index:2;
}
/* pulled part-way out of the crate, the way you'd thumb through them */
.spine.is-on{transform:translateY(-30px) !important}
.spine:focus-visible{outline:2px solid var(--accent);outline-offset:3px;z-index:3}

/* ─── Crate preview panel ─────────────────────────────────────────── */
.preview{
  position:sticky;top:calc(84px + env(safe-area-inset-top,0));
  background:#1a1715d9;backdrop-filter:blur(14px);
  border:1px solid var(--line);border-radius:var(--radius);
  padding:clamp(16px,1.8vw,22px);
  box-shadow:var(--shadow);min-width:0;
}
@media (max-width:900px){.preview{position:static}}

.preview .sleeve{
  width:100%;aspect-ratio:1;margin-bottom:16px;
  box-shadow:0 22px 44px -16px #000, inset 0 0 0 1px #ffffff14;
}
.preview .sleeve img{width:100%;height:100%;object-fit:cover;border-radius:3px}
.preview .eyebrow{margin:0 0 3px}
.preview h2{font-size:clamp(18px,1.7vw,22px);line-height:1.2;margin:0 0 7px}
.preview .meta{margin:0 0 12px}
.preview .marks{display:flex;align-items:center;gap:8px;margin-bottom:12px;flex-wrap:wrap}
.preview .note{
  margin:0 0 14px;font-size:13px;line-height:1.55;color:var(--ink-2);
  border-left:2px solid var(--accent-soft);padding-left:11px;
  display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden;
}
.preview .open{width:100%;justify-content:center}
.preview .placeholder{text-align:center;color:var(--ink-3);padding:40px 10px}
.preview .placeholder .disc{margin:0 auto 14px}


/* ─── Comment threads ─────────────────────────────────────────────── */
.comments{
  list-style:none;margin:0;padding:0;display:grid;gap:9px;align-content:start;
}
.comments:empty{display:none}
.thread .comments{max-height:none}
.empty-thread{padding:10px 2px;font-size:13px}

.comment{
  background:#ffffff09;border:1px solid var(--line);border-radius:10px;
  padding:11px 13px;
}
.comment .body{margin:0;font-size:14px;line-height:1.6;white-space:pre-wrap;word-break:break-word}
.comment .stamp{
  margin:7px 0 0;font-size:11.5px;color:var(--ink-3);
  display:flex;align-items:center;gap:9px;
}
.comment.editing{border-color:var(--accent);background:#ffffff0d}
.edit-box,.composer textarea{
  width:100%;background:var(--bg);border:1px solid var(--line);border-radius:9px;
  color:var(--ink);font:inherit;font-size:14px;padding:10px 12px;outline:none;
  resize:none;overflow-y:hidden;line-height:1.6;
}
.edit-box{border-color:var(--accent)}
.composer textarea:focus{border-color:var(--accent)}

.link{
  all:unset;cursor:pointer;color:var(--accent);font-size:11.5px;
  padding:1px 4px;border-radius:4px;
}
.link:hover{background:var(--accent-soft)}
.link:focus-visible{outline:2px solid var(--accent)}

.comment-foot,.composer-foot{display:flex;align-items:center;gap:8px;margin-top:9px}
.comment-foot .spacer,.composer-foot .spacer{flex:1}
.composer{flex:none;margin-top:14px}
.composer-foot em{
  font-style:normal;font-size:12px;color:var(--accent);opacity:0;transition:opacity .3s;
}
.composer-foot em.show{opacity:1}
.btn.ghost.danger{color:var(--danger)}
.btn.ghost.danger:hover{background:#e0604f1a}

/* per-track threads */
.track-thread{padding:6px 10px 12px 34px}
.track-thread .comments{gap:8px}
.track-thread .comment{padding:9px 11px}
.track-thread .comment .body{font-size:13px}
.note-count{
  flex:none;min-width:17px;height:17px;padding:0 5px;border-radius:9px;
  background:var(--accent-soft);color:var(--accent);
  font-size:10.5px;font-weight:650;display:grid;place-items:center;
}
.preview .more-notes{margin:-8px 0 14px;font-size:11.5px;padding-left:11px}


/* ─── Previewing one search result ────────────────────────────────── */
.results.previewing{display:block;padding:16px}

.hit-preview{display:grid;gap:18px}
.hit-head{display:grid;grid-template-columns:150px minmax(0,1fr);gap:18px;align-items:start}
@media (max-width:520px){.hit-head{grid-template-columns:1fr}}
.hit-head img{
  width:100%;aspect-ratio:1;object-fit:cover;border-radius:4px;background:var(--raised);
  box-shadow:0 16px 32px -14px #000, inset 0 0 0 1px #ffffff14;
}
.hit-meta{display:grid;gap:5px;align-content:start;min-width:0}
.hit-meta h3{margin:0;font-size:19px;line-height:1.22;font-weight:650;letter-spacing:-.01em}
.hit-meta .meta{margin:0 0 6px;color:var(--ink-2);font-size:13px}
.hit-meta .btn{justify-self:start;margin-top:2px}
.hit-preview .btn[data-back]{justify-self:start}

.hit-tracks{max-width:none}
.hit-tracks ol{max-height:min(38vh,320px);overflow-y:auto;padding-right:4px}
.hit-tracks li{
  display:flex;gap:14px;align-items:baseline;
  padding:6px 10px;border-radius:7px;
}
.hit-tracks li:nth-child(odd){background:#ffffff08}
.hit-tracks li::before{
  counter-increment:trk;content:counter(trk);
  flex:none;width:20px;text-align:right;
  color:var(--ink-3);font-variant-numeric:tabular-nums;font-size:12px;
}
.hit-tracks .loading::before,.hit-tracks .hint::before{content:none}

/* ─── Book view ───────────────────────────────────────────────────── */
/* An architectural monograph rather than a novel: white paper, a large plate,
   wide margins and small grotesque type set against a lot of air.

   The white palette is declared on .book and inherited, so it can't leak into
   the dark chrome — but the selectors below are ordinary global ones that
   simply have no match outside the book. .page, .entry and .caption are
   therefore spoken for; anything else wanting those names needs its own. */
.book{
  --paper:#fff;
  --ink-b:#111;
  --ink-b2:#5e5e5e;
  --ink-b3:#9b9b9b;
  --rule:#e6e6e6;
  --grotesque:"Helvetica Neue",Helvetica,Inter,ui-sans-serif,system-ui,sans-serif;

  position:relative;z-index:1;
  display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:8px clamp(10px,2vw,22px) 10px;
}

.book-bar{display:flex;justify-content:center;width:100%}
.written-only{
  display:inline-flex;align-items:center;gap:8px;cursor:pointer;
  color:var(--ink-2);font-size:12px;letter-spacing:.01em;
  background:#00000047;border:1px solid var(--line);border-radius:999px;
  padding:6px 14px 6px 11px;backdrop-filter:blur(8px);
}
.written-only:hover{color:var(--ink);border-color:#463e37}
.written-only input{accent-color:var(--accent);margin:0;width:14px;height:14px}

/* The book takes the room it can get — this is the coffee-table format. */
.spread{position:relative;width:100%;max-width:min(1720px,97vw)}

.pages{
  position:relative;
  display:grid;grid-template-columns:1fr 1fr;grid-template-rows:minmax(0,1fr);
  overflow:hidden;
  background:var(--paper);
  box-shadow:0 34px 70px -24px rgba(0,0,0,.8), 0 2px 6px rgba(0,0,0,.45);
  perspective:2400px;
  height:min(80vh,1000px);
}

/* The fold: tighter and paler than on cream stock, because a white spread
   shows the gutter shadow far more readily. */
.gutter{
  position:absolute;top:0;bottom:0;left:50%;width:min(4.5%,44px);
  transform:translateX(-50%);pointer-events:none;
  background:linear-gradient(90deg,
    transparent 0%, rgba(0,0,0,.045) 42%, rgba(0,0,0,.075) 49.5%,
    rgba(0,0,0,.02) 50.5%, rgba(0,0,0,.028) 60%, transparent 100%);
}

.page{
  display:flex;flex-direction:column;min-width:0;min-height:0;
  padding:clamp(24px,3.4vw,58px) clamp(22px,3.4vw,62px) clamp(18px,2vw,34px);
  color:var(--ink-b);font-family:var(--grotesque);
}
.page-body{flex:1;min-height:0;display:flex;flex-direction:column}

/* The turn arrows ride over the outer edge of the paper, so the outer margin
   is never allowed to be narrower than they are — no title or track number
   ends up printed underneath one. An outer margin wider than the inner one is
   how a book is set anyway. */
@media (min-width:821px){
  .page.verso{padding-left:max(clamp(22px,3.4vw,62px), calc(clamp(12px,1.4vw,26px) + 48px))}
  .page.recto{padding-right:max(clamp(22px,3.4vw,62px), calc(clamp(12px,1.4vw,26px) + 48px))}
}

/* ── left page: the plate and the tracklist ── */
/* Plate and caption share the top of the page: the sleeve at a fixed, modest
   height with the record's name set beside it, both standing on the same
   rule. A square cover is wider than the writing is tall, and stacking the
   two left a column of white where the tracklist wanted to be. */
.plate-head{
  flex:none;display:flex;align-items:flex-end;gap:clamp(14px,1.8vw,28px);
  padding-bottom:13px;border-bottom:1px solid var(--ink-b);
}
.plate{
  flex:none;min-height:0;display:flex;align-items:flex-end;justify-content:flex-start;
  height:clamp(118px,19vh,208px);
}
.book-sleeve{
  all:unset;cursor:pointer;display:block;height:100%;max-width:100%;
}
.book-sleeve img{
  height:100%;width:auto;max-width:100%;object-fit:contain;
  box-shadow:0 2px 3px rgba(0,0,0,.08), 0 14px 30px -16px rgba(0,0,0,.4);
  transition:opacity .25s;
}
.book-sleeve:hover img{opacity:.9}
.book-sleeve:focus-visible{outline:1px solid var(--ink-b);outline-offset:10px}

/* A record added by hand has no catalogue entry and so no tracklist to set
   under it. Nothing else wants that room, so the plate takes it back and the
   block sits in the middle of the page rather than stranded at the top. */
.page-body:not(:has(.track-page)) .plate{height:clamp(200px,42vh,420px)}
.page-body:not(:has(.track-page)) .plate-head{margin-block:auto}

.caption{
  flex:1;min-width:0;
  display:flex;flex-direction:column;gap:5px;
}
.book-artist{
  margin:0;font-size:9.5px;font-weight:500;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-b2);
}
.book-title{
  margin:0;font:400 clamp(17px,1.5vw,23px)/1.2 var(--grotesque);
  letter-spacing:-.018em;color:var(--ink-b);
}
.book-meta{
  margin:1px 0 0;font-size:11px;letter-spacing:.02em;color:var(--ink-b3);
}
.book-meta .book-age{color:var(--accent)}

/* The tracklist under the caption, set as a contents page: numbers in a
   narrow gutter, times out in the margin, and a favourite or a count of notes
   between them — so the left page says which tracks the right page is about.
   A double album scrolls inside the covers rather than stretching the book. */
.track-page{
  flex:1;min-height:0;display:flex;flex-direction:column;
  margin-top:clamp(16px,2vw,28px);
}
.book-tracks{
  list-style:none;margin:0;padding:0;overflow-y:auto;flex:1;min-height:0;
  scrollbar-width:thin;scrollbar-color:#d8d8d8 transparent;
}
.book-tracks li{
  display:flex;align-items:baseline;gap:9px;line-height:1.45;
  padding:6px 0;border-bottom:1px solid var(--rule);
  font-size:11.5px;color:var(--ink-b);
}
.book-tracks li:last-child{border-bottom:0}
.book-tracks .no{
  flex:none;width:2.1em;font-size:9.5px;letter-spacing:.1em;
  color:var(--ink-b3);font-variant-numeric:tabular-nums;
}
.book-tracks .tt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.book-tracks .fav{flex:none;color:var(--accent);font-size:10px}
.book-tracks .noted{
  flex:none;font-size:9px;letter-spacing:.13em;text-transform:uppercase;color:var(--accent);
}
.book-tracks .dur{
  flex:none;font-size:10.5px;color:var(--ink-b3);font-variant-numeric:tabular-nums;
}
.page-note{margin:14px 0 0;font-size:11px;letter-spacing:.02em;color:var(--ink-b3)}

/* ── right page: the notes ── */
/* A running head with a hairline under it, then the entries one under the
   next, each in a measure that stays readable however wide the book gets. */
.rule-head{
  flex:none;display:flex;justify-content:space-between;align-items:baseline;
  padding-bottom:13px;border-bottom:1px solid var(--ink-b);
  font-size:9.5px;font-weight:500;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink-b2);
}

.entries{
  list-style:none;margin:0;padding:0;overflow-y:auto;flex:1;min-height:0;
  scrollbar-width:thin;scrollbar-color:#d8d8d8 transparent;
}
.paper-scroll.has-more{
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 40px),transparent);
  mask-image:linear-gradient(to bottom,#000 calc(100% - 40px),transparent);
}

.entry{
  min-width:0;max-width:62ch;
  padding:clamp(16px,1.7vw,24px) 0;border-bottom:1px solid var(--rule);
}
.entry:last-child{border-bottom:0}
.entry .track-of{
  margin:0 0 5px;font-size:9.5px;font-weight:500;letter-spacing:.13em;
  text-transform:uppercase;color:var(--accent);
}
.entry p.said{
  margin:0;font-size:12.5px;line-height:1.75;letter-spacing:.004em;
  color:var(--ink-b);white-space:pre-wrap;overflow-wrap:anywhere;
}

.page-blank{
  margin:auto;text-align:center;color:var(--ink-b3);
  display:flex;flex-direction:column;align-items:center;
}
.page-blank p{margin:0;font-size:12.5px;letter-spacing:.01em}
.page-blank .btn{margin-top:16px}
.btn.on-paper{
  background:transparent;border-color:#d4d4d4;color:var(--ink-b2);
  font-family:var(--grotesque);font-size:11px;font-weight:500;
  letter-spacing:.11em;text-transform:uppercase;border-radius:0;padding:9px 16px;
}
.btn.on-paper:hover{background:var(--ink-b);border-color:var(--ink-b);color:#fff}

/* Folios in the outer bottom corners, as small as they can usefully be. */
.folio{
  flex:none;margin:clamp(16px,1.8vw,26px) 0 0;
  font-size:9.5px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--ink-b3);font-variant-numeric:tabular-nums;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
}
.page.verso .folio{text-align:left}
.page.recto .folio{text-align:right}

/* ── turning ── */
/* Over the outer edge of each page rather than beside the book, so the paper
   gets the whole width. */
.leaf-nav{
  all:unset;cursor:pointer;position:absolute;z-index:4;
  top:50%;transform:translateY(-50%);
  width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;color:#3a3a3a;
  background:#fff;border:1px solid #dcdcdc;box-shadow:0 1px 4px rgba(0,0,0,.1);
  transition:background .15s,color .15s,opacity .15s;
}
.leaf-nav.prev{left:clamp(12px,1.4vw,26px)}
.leaf-nav.next{right:clamp(12px,1.4vw,26px)}
.leaf-nav:hover{background:var(--ink-b);border-color:var(--ink-b);color:#fff}
.leaf-nav:focus-visible{outline:1px solid var(--ink-b);outline-offset:3px}
.leaf-nav[disabled]{opacity:.22;pointer-events:none}
.leaf-nav svg{width:17px;height:17px;stroke-width:1.6}

/* The page caught mid-turn — no content, because at this speed a lit sheet of
   paper is entirely convincing and it costs one element. */
.leaf{
  position:absolute;top:0;bottom:0;width:50%;z-index:3;
  background:linear-gradient(90deg,#fff 0%,#ededed 100%);
  box-shadow:0 0 30px rgba(0,0,0,.22);
  backface-visibility:hidden;pointer-events:none;
}
.leaf.fwd{right:0;transform-origin:left center;animation:turn-fwd .42s ease-in forwards}
.leaf.back{left:0;transform-origin:right center;animation:turn-back .42s ease-in forwards}
@keyframes turn-fwd{ from{transform:rotateY(0deg)} to{transform:rotateY(-172deg)} }
@keyframes turn-back{ from{transform:rotateY(0deg)} to{transform:rotateY(172deg)} }

.book-hint{
  margin:0;color:var(--ink-3);font-size:10.5px;letter-spacing:.06em;text-align:center;
  text-transform:uppercase;
  text-shadow:0 1px 6px rgba(0,0,0,.7);
}

/* One page at a time once there isn't room for two side by side. */
@media (max-width:820px){
  .pages{grid-template-columns:1fr;grid-template-rows:auto auto;height:auto;overflow:visible}
  .gutter{display:none}
  .page{padding:26px 22px 20px}
  .page.recto{border-top:1px solid var(--rule)}
  /* Stacked, the page is as tall as it needs to be, so nothing scrolls inside
     it: the lists run their full length and the plate shrinks to leave the
     caption beside it room to wrap. */
  .plate{min-height:0;height:clamp(96px,26vw,150px)}
  .page-body:not(:has(.track-page)) .plate{height:clamp(150px,46vw,260px)}
  .entries,.book-tracks{overflow:visible}
  .paper-scroll.has-more{-webkit-mask-image:none;mask-image:none}
  .track-page{flex:none}
  .leaf{display:none}

  /* Stacked, the pages are taller than the screen, so buttons pinned to the
     spread's edges end up somewhere you have to scroll to find. They go above
     the book instead — off the paper, so they take the dark treatment. */
  .spread{display:flex;flex-wrap:wrap;justify-content:center;gap:10px}
  .pages{order:2;flex:1 0 100%}
  .leaf-nav{
    position:static;transform:none;order:1;
    width:40px;height:40px;
    background:#00000047;border-color:var(--line);color:var(--ink-2);
    backdrop-filter:blur(8px);box-shadow:none;
  }
  .leaf-nav:hover{background:#0000006b;border-color:#463e37;color:var(--ink)}
}

/* A turning page is decoration; anyone who asked for less motion gets none. */
@media (prefers-reduced-motion:reduce){
  .leaf{display:none}
  .book-sleeve img{transition:none}
}
