/* Lake Fever mix reel — CD player.
 *
 * A closed-tray compact disc deck: tray on top, digital readout below it,
 * transport buttons below that, and a leaning stack of jewel cases to the
 * right whose spines carry artist and title.
 *
 * Every colour and edge is a variable so each design can skin it. Override
 * these on any ancestor:
 *
 *   --cd-face      deck faceplate
 *   --cd-face-2    faceplate lowlight (used for the gradient)
 *   --cd-edge      hairline/border colour
 *   --cd-legend    printed legend text on the faceplate
 *   --cd-legend-dim
 *   --cd-screen    readout background
 *   --cd-lit       readout text + active lamp (the "on" colour)
 *   --cd-accent    record/active accent
 *   --cd-key       button face
 *   --cd-key-lip   button top highlight
 *   --cd-radius    corner radius on the shell (0 for a hard-edged look)
 *   --cd-spine-h   height of one jewel-case spine
 */

.cdp{
  --cd-face:#211d1a; --cd-face-2:#141110;
  --cd-edge:rgba(0,0,0,.75);
  --cd-legend:#cfc6bc; --cd-legend-dim:#7d746a;
  --cd-screen:#0b0908; --cd-lit:#A8D5C8;
  --cd-accent:#C8502A;
  --cd-key:#2c2723; --cd-key-lip:rgba(255,255,255,.14);
  --cd-radius:3px; --cd-spine-h:30px;

  display:grid; gap:clamp(14px,2vw,26px);
  grid-template-columns:minmax(0,1fr);
  color:var(--cd-legend);
  font-family:inherit;
}
/* per-disc spine art (set as inline custom properties by cdplayer.js when a
   `spineArt` map is passed to mount). Every one falls back to the deck skin,
   so a deck mounted without artwork looks exactly as it did before. */
.cdp__case{
  --sp-bg:var(--cd-face); --sp-fg:var(--cd-legend); --sp-dim:var(--cd-legend-dim);
  --sp-tab:var(--cd-accent); --sp-font:inherit; --sp-weight:700; --sp-track:.14em;
  --sp-case:uppercase; --sp-rule:rgba(0,0,0,.22);
}
/* The stack sits beside the deck as soon as there's room for both, and is
   capped to the deck's own height so the two read as one unit. Below that it
   falls under the deck and gets its own scroll cap. The inner wrapper is
   absolutely positioned in the side-by-side case so the list's length can't
   stretch the grid row — the deck alone sets the height. */
.cdp__shelf{ min-width:0; }
.cdp__shelfin{ display:flex; flex-direction:column; min-height:0; }
@media(min-width:1080px){
  .cdp{
    grid-template-columns:minmax(340px,1fr) minmax(300px,1fr);
    align-items:stretch;
  }
  .cdp__shelf{ position:relative; }
  .cdp__shelfin{ position:absolute; inset:0; }
  .cdp__shelfin .cdp__stack{ flex:1 1 auto; max-height:none; min-height:0; }
}

/* ── the deck ──────────────────────────────────────────────── */
.cdp__deck{
  position:relative; overflow:hidden;
  border-radius:var(--cd-radius);
  border:1px solid var(--cd-edge);
  background:linear-gradient(180deg,var(--cd-face),var(--cd-face-2));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.06), 0 18px 40px -26px rgba(0,0,0,.9);
  padding:clamp(14px,1.8vw,22px);
  display:grid; gap:0;
}
.cdp__brand{
  display:flex; align-items:center; gap:10px;
  margin-bottom:clamp(12px,1.5vw,18px);
  font-size:10px; letter-spacing:.22em; text-transform:uppercase;
  color:var(--cd-legend-dim);
}
.cdp__brand b{ color:var(--cd-legend); font-weight:700; letter-spacing:.2em; }
.cdp__brand .cdp__model{ margin-left:auto; letter-spacing:.16em; }

/* tray — closed. It stays closed; the lip and seam do the work.
   The tray sits flush on the lower half of the deck: no gap, a shared edge,
   and a shadow cast down onto it, so the two read as one chassis. */
.cdp__tray{
  position:relative; z-index:2; height:clamp(58px,7vw,78px);
  border-radius:2px 2px 0 0; border:1px solid var(--cd-edge);
  background:linear-gradient(180deg,#191512,#0e0c0a);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05), inset 0 -8px 14px -10px #000;
  display:flex; align-items:center; justify-content:center;
  overflow:hidden;
}
.cdp__tray::before{            /* the seam where the tray meets the shell */
  content:""; position:absolute; left:0; right:0; bottom:22%;
  height:1px; background:rgba(0,0,0,.85);
  box-shadow:0 1px 0 rgba(255,255,255,.05);
}
.cdp__tray::after{             /* a slow sheen that sweeps while playing */
  content:""; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(105deg,transparent 42%,rgba(255,255,255,.07) 50%,transparent 58%);
  transform:translateX(-120%);
}
.cdp.is-playing .cdp__tray::after{ animation:cdpSheen 5.5s linear infinite; }
@keyframes cdpSheen{ to{ transform:translateX(120%); } }

/* the lower half of the chassis: readout + transport, tucked up under the
   tray. The seam and the inset shadow are the only things separating them. */
.cdp__lower{
  position:relative; z-index:1;
  display:grid; gap:clamp(12px,1.5vw,18px);
  padding:clamp(10px,1.2vw,14px) 0 0;
  box-shadow:inset 0 14px 16px -12px rgba(0,0,0,1);
}
.cdp__lower::before{
  content:""; position:absolute; left:0; right:0; top:0; height:1px;
  background:var(--cd-edge); opacity:.55;
}

.cdp__disclogo{
  width:clamp(42px,5.5vw,62px); color:var(--cd-legend-dim);
  opacity:.7; transition:opacity .4s ease, color .4s ease;
}
.cdp__disclogo svg{ width:100%; height:auto; display:block; }
.cdp.is-playing .cdp__disclogo{ opacity:1; color:var(--cd-lit); }

/* readout */
.cdp__screen{
  border-radius:2px; border:1px solid var(--cd-edge);
  background:var(--cd-screen);
  box-shadow:inset 0 2px 10px rgba(0,0,0,.8);
  padding:clamp(11px,1.4vw,16px) clamp(12px,1.6vw,18px);
  display:grid; gap:6px; min-height:92px; align-content:center;
}
.cdp__row{ display:flex; align-items:baseline; gap:10px; min-width:0; }
.cdp__no{
  font-variant-numeric:tabular-nums; font-size:clamp(22px,3vw,30px); line-height:1;
  color:var(--cd-lit); letter-spacing:.04em; flex:none;
}
.cdp__title{
  font-size:clamp(13px,1.5vw,16px); letter-spacing:.12em; text-transform:uppercase;
  color:var(--cd-lit); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.cdp__artist{
  font-size:11px; letter-spacing:.18em; text-transform:uppercase;
  color:var(--cd-legend-dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.cdp__meta{
  display:flex; align-items:center; gap:12px; margin-top:2px;
  font-size:10.5px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--cd-legend-dim);
}
.cdp__time{ font-variant-numeric:tabular-nums; color:var(--cd-lit); }
.cdp__lamp{
  display:inline-flex; align-items:center; gap:6px; margin-left:auto;
  color:var(--cd-legend-dim);
}
.cdp__lamp i{
  width:7px; height:7px; border-radius:50%; background:#2a2521;
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.7);
}
.cdp.is-playing .cdp__lamp i{ background:var(--cd-accent); box-shadow:0 0 8px 1px var(--cd-accent); }
.cdp.is-playing .cdp__lamp{ color:var(--cd-legend); }

/* a thin seek line — not a waveform */
.cdp__seek{
  -webkit-appearance:none; appearance:none; width:100%; height:16px;
  background:transparent; cursor:pointer; margin:2px 0 0; display:block;
}
.cdp__seek::-webkit-slider-runnable-track{
  height:3px; background:rgba(255,255,255,.12);
  background-image:linear-gradient(var(--cd-accent),var(--cd-accent));
  background-repeat:no-repeat; background-size:var(--p,0%) 100%;
}
.cdp__seek::-moz-range-track{ height:3px; background:rgba(255,255,255,.12); }
.cdp__seek::-moz-range-progress{ height:3px; background:var(--cd-accent); }
.cdp__seek::-webkit-slider-thumb{
  -webkit-appearance:none; width:11px; height:11px; border-radius:50%;
  background:var(--cd-lit); border:0; margin-top:-4px;
}
.cdp__seek::-moz-range-thumb{
  width:11px; height:11px; border-radius:50%; background:var(--cd-lit); border:0;
}
.cdp__seek:focus-visible{ outline:2px solid var(--cd-accent); outline-offset:3px; }

/* transport */
.cdp__keys{ display:flex; flex-wrap:wrap; gap:7px; align-items:center; }
.cdp__key{
  appearance:none; cursor:pointer;
  min-width:46px; height:34px; padding:0 11px;
  border-radius:2px; border:1px solid var(--cd-edge);
  background:linear-gradient(180deg,var(--cd-key),#1a1613);
  box-shadow:inset 0 1px 0 var(--cd-key-lip), 0 2px 0 rgba(0,0,0,.55);
  color:var(--cd-legend);
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  transition:transform .09s ease, box-shadow .09s ease, color .18s ease;
}
.cdp__key svg{ width:13px; height:13px; fill:currentColor; }
.cdp__key:hover{ color:#fff; }
.cdp__key:active,.cdp__key[aria-pressed="true"]{
  transform:translateY(2px); box-shadow:inset 0 1px 0 var(--cd-key-lip), 0 0 0 rgba(0,0,0,.55);
}
.cdp__key[aria-pressed="true"]{ color:var(--cd-lit); }
.cdp__key:focus-visible{ outline:2px solid var(--cd-accent); outline-offset:3px; }
.cdp__key--wide{ min-width:64px; }
.cdp__keylabel{
  font-size:9.5px; letter-spacing:.16em; text-transform:uppercase;
}
.cdp__vol{ display:flex; align-items:center; gap:8px; margin-left:auto; }
.cdp__vol label{ font-size:9.5px; letter-spacing:.16em; text-transform:uppercase; color:var(--cd-legend-dim); }
.cdp__vol input{ width:74px; accent-color:var(--cd-accent); }

/* ── the stack of jewel cases ──────────────────────────────── */
/* --lean is the gutter the pulled case slides out into. The list NEVER scrolls
   sideways: the incompressible parts of a spine (number, artist cap, LFS block,
   running time) can add up to more than a narrow column, and the vertical
   scrollbar appearing used to tip it over the edge. overflow-x is clipped
   outright and the gutter is reserved whether or not the bar is showing. */
.cdp__stack{
  --lean:16px;
  list-style:none;
  /* the gutter is carved out of the column on BOTH sides rather than out of
     the rows — taking it from the row width cost ~14px of title and started
     truncating names that used to fit. It's what the case grows into when it
     comes forward, so it has to be even left and right. Spines still line up
     with the stack heading; only the clipping box moves. */
  margin:0 calc(var(--lean) * -1);
  padding:0 var(--lean);
  max-height:min(60vh,460px);
  overflow-x:hidden; overflow-y:auto; overscroll-behavior:contain;
  scrollbar-width:thin; scrollbar-gutter:stable;
  perspective:900px;
}
.cdp__stack::-webkit-scrollbar{ width:8px; }
.cdp__stack::-webkit-scrollbar-thumb{ background:rgba(0,0,0,.28); }

.cdp__case{ position:relative; margin:0 0 2px; }
.cdp__spine{
  position:relative; width:100%; display:flex; align-items:center; gap:8px;
  height:var(--cd-spine-h); padding:0 10px 0 12px;
  cursor:pointer; text-align:left; appearance:none;
  border:1px solid var(--cd-edge);
  border-left:5px solid var(--sp-tab);
  background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(0,0,0,.10)),var(--sp-bg);
  color:var(--sp-fg);
  font-family:var(--sp-font);
  transform-origin:center center;
  box-shadow:0 1px 0 rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.10);
  transition:transform .22s cubic-bezier(.2,.85,.25,1), box-shadow .22s ease,
             background .22s ease, color .22s ease;
  overflow:hidden;
}
/* A case comes STRAIGHT OUT of the shelf toward you: it grows evenly on every
   side — type and all — and throws a heavier shadow onto the case below. A
   plain scale, not translateZ: the list's perspective origin is its centre, so
   translateZ would sling rows near the ends sideways instead of forward. */
.cdp__spine:hover,.cdp__spine:focus-visible{
  transform:scale(1.045);
  box-shadow:0 1px 0 rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.10),
             0 13px 22px -6px rgba(0,0,0,.62);
}
.cdp__case:hover,.cdp__case:focus-within{ z-index:2; }
.cdp__spine:focus-visible{ outline:2px solid var(--cd-accent); outline-offset:2px; }
.cdp__case.is-current{ z-index:3; }
.cdp__case.is-current .cdp__spine{
  transform:scale(1.065);
  background:linear-gradient(180deg,rgba(255,255,255,.14),rgba(0,0,0,.06)),var(--cd-accent);
  color:#fff; border-left-color:var(--cd-lit);
  box-shadow:0 1px 0 rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.10),
             0 17px 28px -8px rgba(0,0,0,.68);
}
.cdp__case.is-current .cdp__n,.cdp__case.is-current .cdp__slen{ color:rgba(255,255,255,.78); }
/* On a deck with artwork the loaded case keeps its own printed spine — it is
   marked by the pull, the accent tab and the ring instead of a repaint. */
.cdp--art .cdp__case.is-current .cdp__spine{
  background:linear-gradient(180deg,rgba(255,255,255,.10),rgba(0,0,0,.10)),var(--sp-bg);
  color:var(--sp-fg);
  border-left-color:var(--cd-accent); border-left-width:8px;
  box-shadow:0 1px 0 rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.10),
             0 0 0 2px var(--cd-accent), 0 17px 28px -8px rgba(0,0,0,.68);
}
.cdp--art .cdp__case.is-current .cdp__n,
.cdp--art .cdp__case.is-current .cdp__slen{ color:var(--sp-dim); }

.cdp__n{
  font-variant-numeric:tabular-nums; font-size:10px; letter-spacing:.1em;
  color:var(--sp-dim); flex:none; width:2ch;
}
/* the catalogue-number and running-time blocks are ruled off from the
   artwork, the way a printed spine is — only on decks that carry art */
.cdp--art .cdp__n{
  width:auto; padding-right:9px; margin-right:1px;
  border-right:1px solid var(--sp-rule);
}
.cdp--art .cdp__slen{ padding-left:9px; border-left:1px solid var(--sp-rule); }
.cdp__sartist{
  font-size:11px; font-weight:var(--sp-weight); letter-spacing:var(--sp-track);
  text-transform:var(--sp-case);
  white-space:nowrap; flex:none; max-width:46%; overflow:hidden; text-overflow:ellipsis;
}
.cdp__stitle{
  font-size:11px; letter-spacing:.06em;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  opacity:.86; min-width:0;
}
/* Rows that run long get their lettering squeezed instead of going straight to
   an ellipsis — the artist's printed tracking comes most of the way in, the
   title tightens to slightly negative. It doesn't rescue a genuinely long
   title, it just buys back several characters before the cut. Applied per row
   by cdplayer.js, so the spines that DO fit keep their proper letterfit. */
.cdp__case--tight .cdp__sartist{ letter-spacing:calc(var(--sp-track) * .4); }
.cdp__case--tight .cdp__stitle{ letter-spacing:-.008em; }
.cdp__slen{
  margin-left:auto; font-variant-numeric:tabular-nums;
  font-size:10px; color:var(--sp-dim); flex:none;
}
/* the Lake Fever Sessions block, printed toward the right of the spine just
   before the running time — a red bar running the full depth of the spine,
   the way a catalogue flash is printed right across a case edge. */
.cdp__lfs{
  flex:none; margin-left:auto; align-self:stretch;
  display:flex; align-items:center; padding:0 6px;
  background:var(--cd-lfs-bg,#C41E15); color:var(--cd-lfs-fg,#F8F3EA);
  box-shadow:inset 0 0 0 1px rgba(0,0,0,.3);
  font-family:inherit; font-size:8.5px; font-weight:700; line-height:1;
  letter-spacing:.14em; text-transform:none;
}
.cdp__lfs + .cdp__slen{ margin-left:8px; }
.cdp__stackhead{
  display:flex; align-items:baseline; gap:10px; margin:0 0 8px;
  font-size:10px; letter-spacing:.2em; text-transform:uppercase; color:var(--cd-legend-dim);
}

/* ── fixed transport bar (optional: mount with bar:true) ───── */
.cdp__bar{
  --cd-face:#211d1a; --cd-face-2:#141110;
  --cd-edge:rgba(0,0,0,.85);
  --cd-legend:#cfc6bc; --cd-legend-dim:#7d746a;
  --cd-lit:#A8D5C8; --cd-accent:#C8502A;
  --cd-key:#2c2723; --cd-key-lip:rgba(255,255,255,.14);

  position:fixed; left:0; right:0; bottom:0; z-index:120;
  height:52px; display:flex; align-items:center; gap:12px; padding:0 14px;
  background:linear-gradient(180deg,var(--cd-face),var(--cd-face-2));
  border-top:1px solid var(--cd-edge);
  box-shadow:0 -1px 0 rgba(255,255,255,.06), 0 -12px 26px -20px #000;
  color:var(--cd-legend);
}
.cdp__prog{
  position:absolute; left:0; top:-1px; height:2px; width:0;
  background:var(--cd-accent); transition:width .2s linear;
}
.cdp__barinfo{
  min-width:0; flex:1 1 auto; display:flex; align-items:baseline; gap:10px; overflow:hidden;
}
.cdp__barinfo b{
  font-size:11.5px; font-weight:700; letter-spacing:.18em; text-transform:uppercase;
  white-space:nowrap; flex:none;
}
.cdp__barinfo span{
  font-size:11px; letter-spacing:.08em; color:var(--cd-legend-dim);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.cdp__bartime{
  font-variant-numeric:tabular-nums; font-size:10.5px; letter-spacing:.08em;
  color:var(--cd-legend-dim); flex:none;
}
@media (max-width:560px){ .cdp__bartime{ display:none; } }

@media (prefers-reduced-motion: reduce){
  .cdp__spine{ transition:none; }
  .cdp .cdp__tray::after{ animation:none; }
  .cdp__prog{ transition:none; }
}
