/* Spotify — crate rows with cover art, and the now-playing bar */

/* ===== CRATE ROWS (now buttons, generated from the crate array) ===== */
.crate-row{
  width:100%;background:none;border:none;color:inherit;font:inherit;
  text-align:left;cursor:pointer;gap:14px;
}
.cr-left{display:flex;align-items:center;gap:13px;min-width:0;flex:1;}

.cr-art{
  position:relative;width:42px;height:42px;flex-shrink:0;border-radius:3px;
  overflow:hidden;background:linear-gradient(145deg,#2A211B,#141110);
  box-shadow:0 4px 12px -4px rgba(0,0,0,.7),inset 0 0 0 1px rgba(227,211,179,.12);
}
.cr-art img{width:100%;height:100%;object-fit:cover;display:block;}
/* vinyl placeholder when no art is set */
.cr-art.no-art::after{
  content:'';position:absolute;inset:22%;border-radius:50%;
  background:repeating-radial-gradient(circle at center,#0a0807 0 2px,#241d19 2px 4px);
  box-shadow:inset 0 0 0 1px rgba(227,211,179,.15);
}
.cr-play{
  position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:rgba(10,8,7,.62);color:var(--panel-ink);font-size:11px;
  opacity:0;transition:opacity .25s var(--ease);backdrop-filter:blur(1px);
}
.crate-row:hover .cr-play,
.crate-row:focus-visible .cr-play{opacity:1;}
.crate-row.is-playing .cr-play{opacity:1;color:var(--brass);}

.cr-meta{display:flex;flex-direction:column;gap:2px;min-width:0;}
.cr-name{
  font-weight:600;font-size:15px;line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.cr-artist{
  font-family:'Courier Prime',monospace;font-size:11px;color:var(--manila-dim);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.crate-row.is-playing .cr-name{color:var(--sec,var(--brass-ink));}

/* little animated bars on the row that's playing */
.cr-eq{display:none;align-items:flex-end;gap:2px;height:11px;margin-left:8px;flex-shrink:0;}
.crate-row.is-playing .cr-eq{display:flex;}
.cr-eq i{
  width:2px;background:var(--sec,var(--brass-ink));border-radius:1px;display:block;
  animation:crEq .7s ease-in-out infinite alternate;
}
.cr-eq i:nth-child(2){animation-delay:.18s;}
.cr-eq i:nth-child(3){animation-delay:.36s;}
@keyframes crEq{from{height:3px;}to{height:11px;}}

/* ===== NOW PLAYING BAR ===== */
.np-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:120;
  transform:translateY(115%);transition:transform .45s var(--ease);
  /* Both layers, in one declaration. These used to be two: a `background`
     shorthand carrying the walnut gradient, then `background-image` on the
     next line — which replaced it, since the shorthand only sets
     background-image. The bar was left with nothing but the translucent
     grain and the page showed straight through it. */
  background-color:var(--walnut);
  background-image:var(--grain),
    linear-gradient(180deg,var(--walnut-hi),var(--walnut) 40%,var(--walnut-lo));
  border-top:1px solid rgba(0,0,0,.6);
  box-shadow:0 -18px 44px -20px rgba(0,0,0,.9);
  padding:9px 0 calc(9px + env(safe-area-inset-bottom,0px));
}
.np-bar.show{transform:translateY(0);}

.np-inner{
  max-width:1060px;margin:0 auto;padding:0 18px;
  display:flex;align-items:center;gap:14px;
}
.np-art{
  width:44px;height:44px;flex-shrink:0;border-radius:3px;overflow:hidden;
  background:linear-gradient(145deg,#2A211B,#141110);
  box-shadow:0 4px 12px -4px rgba(0,0,0,.8),inset 0 0 0 1px rgba(227,211,179,.14);
}
.np-art img{width:100%;height:100%;object-fit:cover;display:block;}
.np-meta{display:flex;flex-direction:column;gap:2px;min-width:0;width:170px;flex-shrink:0;}
.np-title{
  font-weight:600;font-size:13.5px;color:var(--panel-ink);line-height:1.25;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.np-artist{
  font-family:'Courier Prime',monospace;font-size:10.5px;color:rgba(227,211,179,.65);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* the Spotify iframe mounts here and provides play/pause + scrubbing */
.np-embed{flex:1;min-width:0;}
.np-embed iframe{display:block;border-radius:8px;}

.np-btn{
  width:32px;height:32px;flex-shrink:0;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  background:linear-gradient(180deg,#C6CACE,#9DA1A7);
  border:1px solid rgba(0,0,0,.35);color:var(--engrave);
  font-size:15px;line-height:1;
  box-shadow:0 1px 0 rgba(255,255,255,.6) inset,0 2px 5px rgba(0,0,0,.35);
  transition:transform .12s var(--ease);
}
.np-btn:hover{transform:translateY(-1px);}
.np-btn:active{transform:translateY(1px);box-shadow:0 1px 4px rgba(0,0,0,.5) inset;}
.np-close{
  background:rgba(0,0,0,.25);border-color:rgba(0,0,0,.4);color:var(--panel-ink);
  box-shadow:none;font-size:12px;
}

@media(max-width:760px){
  .np-meta{display:none;}
  .np-inner{gap:10px;padding:0 12px;}
  .np-art{width:38px;height:38px;}
}
@media(max-width:460px){
  .np-art{display:none;}
}

/* keep the bar from covering the scope controls */
body.np-open .scope-ctl{bottom:104px;}
@media(max-width:700px){
  body.np-open .scope-ctl{bottom:96px;}
}

/* rows with no track ID yet: readable, just not clickable */
.crate-row.no-track{cursor:default;}
.crate-row.no-track .cr-play{display:none;}
.crate-row.no-track .cr-name{color:var(--manila-dim);}
/* ===== GENRE FILTER + SHUFFLE ===== */
.crate-head{
  display:flex;align-items:center;justify-content:space-between;
  gap:14px;margin-bottom:14px;flex-wrap:wrap;
}
.crate-genres{display:flex;gap:6px;flex-wrap:wrap;}
.genre-chip{
  display:inline-flex;align-items:center;
  font-family:'Courier Prime',monospace;font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--manila-dim);
  background:var(--fill-2);
  border:1px solid var(--rule);border-radius:100px;
  padding:7px 13px;line-height:1;
  transition:color .25s var(--ease),border-color .25s var(--ease),
             background .25s var(--ease),transform .15s var(--ease);
}
.genre-chip:hover:not(:disabled){
  color:var(--manila);border-color:var(--rule-hover);transform:translateY(-1px);
}
/* The selected genre takes the section's colour rather than a fixed
   gold, so the one lit control in the crate agrees with the nav pill
   and the rail that are lit at the same moment. */
.genre-chip.on{
  color:var(--sec,var(--brass-ink));
  border-color:color-mix(in srgb, var(--sec,var(--brass-ink)) 50%, transparent);
  background:color-mix(in srgb, var(--sec,var(--brass-ink)) 12%, transparent);
}
.genre-chip:disabled{opacity:.32;cursor:default;}

.crate-shuffle{
  display:inline-flex;align-items:center;gap:8px;flex-shrink:0;
  font-family:'Courier Prime',monospace;font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--manila-dim);
  background:var(--fill-1);
  border:1px solid var(--rule);border-radius:100px;
  padding:7px 14px;line-height:1;
  transition:color .25s var(--ease),border-color .25s var(--ease),
             background .25s var(--ease),transform .15s var(--ease),opacity .25s var(--ease);
}
.crate-shuffle:hover:not(:disabled){
  color:var(--brass-ink);border-color:var(--brass-line);
  background:var(--brass-tint);transform:translateY(-1px);
}
.crate-shuffle:active:not(:disabled){transform:translateY(1px);}
.crate-shuffle:disabled{opacity:.3;cursor:not-allowed;}
.cs-icon{display:inline-block;font-size:13px;line-height:1;}
.crate-shuffle.spin .cs-icon{animation:csSpin .6s var(--ease);}
@keyframes csSpin{
  0%{transform:rotate(0) scale(1);}
  50%{transform:rotate(180deg) scale(1.25);}
  100%{transform:rotate(360deg) scale(1);}
}

.crate-empty{
  padding:26px 4px;text-align:center;
  font-family:'Courier Prime',monospace;font-size:12px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--manila-dim);opacity:.6;
  border-bottom:1px solid var(--rule);
}

/* the crate is re-rendered on filter/shuffle, so cover more rows
   than the original five in case CRATE_DISPLAY_COUNT is raised */
.crate.is-visible .crate-row:nth-child(6){transition-delay:.50s;}
.crate.is-visible .crate-row:nth-child(7){transition-delay:.59s;}
.crate.is-visible .crate-row:nth-child(8){transition-delay:.68s;}

@media(max-width:520px){
  .crate-head{gap:10px;}
  .genre-chip{padding:6px 10px;font-size:10px;letter-spacing:.06em;}
  .crate-shuffle{padding:6px 12px;font-size:10px;}
}
/* ===== WHEN SPOTIFY CAN'T LOAD =====
   Ad blockers, tracker-blocking browsers and Spotify CDN outages all stop
   the embed script from arriving. 10-spotify.js sets .sp-blocked on <body>
   when that happens; the player is swapped for a direct link so the bar
   still does something useful instead of sitting there pretending. */
.np-fallback{display:none;}
body.sp-blocked .np-embed{display:none;}
body.sp-blocked .np-fallback{
  flex:1;min-width:0;
  display:flex;flex-direction:column;justify-content:center;gap:2px;
  padding:7px 13px;border-radius:8px;
  /* This one really is on the walnut bar, which does not flip with the
     mode — so neither can these. Token values would invert onto it. */
  background:rgba(0,0,0,.22);
  border:1px solid rgba(227,211,179,.18);
  transition:border-color .25s var(--ease),background .25s var(--ease);
}
body.sp-blocked .np-fallback:hover{
  border-color:rgba(217,167,76,.45);background:rgba(217,167,76,.13);
}
.npf-msg{
  font-family:'Courier Prime',monospace;font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--panel-ink-dim);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.npf-cta{
  font-size:13px;font-weight:600;color:var(--brass);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* skip buttons are meaningless with no player behind them */
body.sp-blocked #npPrev,
body.sp-blocked #npNext{display:none;}
@media(max-width:460px){
  .npf-msg{display:none;}
}