/* ── The directory's side column (views/listing_side.php) ─────────────────
   Under the scope card, desktop only: ONE box (.lside-stage) that holds either
   the idle stack or the preview of the marked row, swapped in place, with the
   keys pinned under it. Every slot of the preview has a fixed size, so the
   skeleton and the loaded card stand on the same pixels. */

@media (max-width: 991.98px) {
  .lside { display: none; }
}
@media (min-width: 992px) {
  /* The column holds still at every desktop height and ends above the player
     (--pb-room). Not the frozen copy listing-filter.js lays over a scope
     switch, which is positioned on its own. */
  .listing-sidebar:not(.listing-sidebar-ghost):has(> .lside) {
    position: sticky;
    top: calc(var(--nav-h, 72px) + 1rem);
    height: calc(100vh - var(--nav-h, 72px) - 2rem - var(--pb-room, 0px));
    max-height: none;
    display: flex;
    flex-direction: column;
    overflow-y: hidden;
  }
  .listing-sidebar:has(> .lside) > .listing-hero { margin-top: 0; flex: none; }
  /* Advanced open: the filters take the column, and it scrolls as before */
  .listing-sidebar:not(.listing-sidebar-ghost):has(#listingAdvancedPanel:not([hidden])) { overflow-y: auto; }
  .listing-sidebar:has(#listingAdvancedPanel:not([hidden])) > .lside { display: none; }
}

.lside { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.lside-stage { position: relative; flex: 1 1 auto; min-height: 0; }
.lside-layer { position: absolute; inset: 0; transition: opacity .14s ease; }
.lside-layer.is-off { opacity: 0; visibility: hidden; pointer-events: none; transition: opacity .14s ease, visibility 0s linear .14s; }
:root[data-motion="reduce"] .lside-layer { transition: none; }
.lside-idle { display: flex; flex-direction: column; gap: 1.6rem; padding: .5rem 0 0; overflow: hidden; }
.lside-idle > [hidden] { display: none; }
.lside-pv { overflow: hidden; }

.lside-head {
  display: flex;
  align-items: center;
  gap: .75rem;
  margin: 0 0 .7rem;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
/* in the idle stack: in line with the set lines' text, the rule out to the card's edge */
.lside-idle .lside-head { padding-inline: .55rem; }
.lside-head::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* ── a set as one line (render_side_set_line()) ── */
.lside-line {
  --cover-w: 43px;   /* cover art: square */
  position: relative;
  display: grid;
  grid-template-columns: var(--cover-w) minmax(0, 1fr) auto;
  align-items: center;
  gap: .8rem;
  padding: .45rem .55rem;   /* the hover plate spans the column: as wide as the scope card */
  border-radius: var(--radius-sm);
}
.lside-line--wide { --cover-w: 76px; }   /* a video's thumb: 16:9 */
.lside-line:hover { background: var(--bg-card-hover); }
.lside-line__cover {
  position: relative;
  width: var(--cover-w);
  aspect-ratio: 1;
  padding: 0;
  border: 0;
  border-radius: 5px;
  overflow: hidden;
  background: var(--bg-card);
  cursor: pointer;
}
.lside-line--wide .lside-line__cover { aspect-ratio: 16 / 9; }
.lside-line__cover img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* The overlay and its play/pause states are the row's (.roster-play-overlay,
   listing.css, which names .lside-line__cover beside .roster-logo--playable);
   the platform badge is the row's too, made small for the small cover. */
.lside-line:hover .roster-play-overlay { opacity: 1; }
.lside-line__cover .roster-platform-badge { top: 2px; right: 2px; width: 14px; height: 14px; font-size: .5rem; }
.lside-line__text { min-width: 0; display: flex; flex-direction: column; gap: .1rem; color: inherit; text-decoration: none; }
.lside-line__title { font-size: .86rem; font-weight: 600; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lside-line__text:hover .lside-line__title { text-decoration: underline; text-underline-offset: 3px; }
.lside-line__meta { font-size: .76rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.lside-line__side { font-size: .74rem; color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.lside-line__bar {
  position: absolute;
  left: calc(var(--cover-w) + .8rem + .55rem);
  right: .55rem;
  bottom: .15rem;
  height: 2px;
  border-radius: 2px;
  background: var(--border);
}
.lside-line__bar > span { display: block; height: 100%; border-radius: inherit; background: var(--listing-scope-color, var(--accent)); }

/* ── Flavor of the Week: the home slide's top in miniature ──
   The sash (render_fotw_tag(), .fotw-tag in components.css) with its striped
   band run across the column like a tape, the plate slapped on it. The
   wrapper stays level and unfiltered (as .fotw-tag--corner does) so the band
   can be laid out against the strip, not the plate. */
.lside-fw { padding-inline: 1.4rem; --title-dot: var(--fotw-sash, var(--fotw-color, var(--fotw-color-default))); }
.lside-fw__strip {
  position: relative;
  display: flex;
  align-items: center;
  height: 3.6rem;
  margin: -.2rem -1.4rem .55rem;
  padding-left: 2.2rem;
}
.lside-fw .fotw-tag--strip {
  position: static;
  margin: 0;
  rotate: none;   /* any rotate but none would hold the band to the plate */
  filter: none;
  isolation: auto;
  transition: none;
}
.lside-fw .fotw-tag--strip:hover { rotate: none; }
.lside-fw .fotw-tag--strip .fotw-tag-body {
  rotate: var(--ft-rest);
  transition: rotate .4s cubic-bezier(.3, 1.5, .5, 1);
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .4));
}
.lside-fw .fotw-tag--strip:hover .fotw-tag-body { rotate: -.5deg; }
.lside-fw .fotw-tag--strip .fotw-tag-band {
  inset: 50% 0 auto 0;
  height: 1.5rem;
  margin-top: -.75rem;
  transform: rotate(-2.2deg);
  -webkit-mask: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
          mask: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.lside-fw .fotw-tag--strip .fotw-tag-label { font-size: .66rem; padding: .55rem 1.05rem; }
.lside-fw .fotw-tag--strip .fotw-tag-tape { font-size: .47rem; padding: .28rem .6rem; margin: -6px -16px 0 0; }
.lside-fw__name {
  margin: 0;
  font-size: 1.75rem;
  font-weight: 900;
  letter-spacing: -.035em;
  line-height: 1.02;
  color: var(--text);
  text-wrap: balance;
}
.lside-fw__name a { color: inherit; text-decoration: none; }
.lside-fw__name a:hover { opacity: .85; }
.lside-fw__slug {
  display: inline-block;
  margin: .3rem 0 .55rem;
  font-family: var(--bs-font-monospace);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .04em;
  color: color-mix(in srgb, var(--fotw-sash, var(--fotw-color, var(--fotw-color-default))) 50%, var(--text));
  text-decoration: none;
}
.lside-fw__slug:hover { color: var(--text); }
.lside-fw__slug span { color: var(--text-muted); font-weight: 400; }
/* The entrance, once per page view (listing-side.js sets .is-in): a quiet
   echo of the home slide's - the band fades in as it slides a little way
   along, then the plate settles onto it. No slap: in a side column the
   slide's full motion was too much. */
.lside-fw.is-in .fotw-tag-band { animation: lside-band .6s cubic-bezier(.2, .7, .3, 1) backwards; }
.lside-fw.is-in .fotw-tag-body { animation: lside-settle .5s cubic-bezier(.2, .7, .3, 1) .15s backwards; }
@keyframes lside-band   { from { opacity: 0; translate: -18px 0; } }
@keyframes lside-settle { from { opacity: 0; translate: 0 -4px; } }
:root[data-motion="reduce"] .lside-fw .fotw-tag-band,
:root[data-motion="reduce"] .lside-fw .fotw-tag-body { animation: none; transition: none; }

/* ── the keys, under the box in both states ── */
.lside-keys {
  flex: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: .5rem 1rem;
  margin: 1rem 0 0;   /* flush with the scope card, like the stack above */
  padding: .85rem .55rem 0;   /* the keys in line with the headings, the rule edge to edge */
  border-top: 1px solid var(--border);
}
.lside-key { display: flex; align-items: center; gap: .5rem; min-width: 0; font-size: .78rem; color: var(--text-dim); white-space: nowrap; }
.lside-key b { display: inline-flex; align-items: center; gap: .2rem; flex: none; font-weight: 400; }
.lside-key .vrcdj-kbd { font-size: .64rem; padding: .12rem .38rem; min-width: 1.35rem; }
/* Shift+Enter plays a set: only where the list has sets */
#listingContainer:is([data-scope="artist"], [data-scope="community"]) .lside-key--play { display: none; }

/* ── the preview card: every slot a fixed size ── */
.lside-card { border: 1px solid var(--border); border-radius: 18px; overflow: hidden; background: var(--bg-card); }
.lside-card__banner { position: relative; height: 116px; background: color-mix(in srgb, var(--listing-scope-color, var(--accent)) 12%, var(--bg-card)); }
.lside-card[data-fit="compact"] .lside-card__banner { height: 76px; }
.lside-card__banner > div { position: absolute; inset: 0; background-size: cover; background-position: center; }
.lside-card__banner::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 40%, rgba(0, 0, 0, .4)); pointer-events: none; }
.lside-fill { position: absolute; inset: 0; border-radius: 0; }
.lside-card__body { padding: 0 1.3rem 1.15rem; }
.lside-card__head { position: relative; z-index: 1; display: flex; align-items: flex-start; gap: .9rem; margin-top: -30px; }
.lside-card__logo { flex: none; }
.lside-card__logo .roster-logo { width: 72px; height: 72px; }
/* A picture is cut out of the banner by a ring of the page; a logo stands on it bare */
.lside-card__logo .roster-logo--opaque img { border-radius: 14px; box-shadow: 0 0 0 3px var(--bg-base); }
.lside-card__id { flex: 1; min-width: 0; padding-top: 34px; }
.lside-card__name {
  display: flex;
  align-items: center;
  gap: .4rem;
  height: 1.6rem;
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
}
.lside-card__name:hover { text-decoration: underline; text-underline-offset: 3px; }
.lside-card__name .roster-name__t { overflow: hidden; text-overflow: ellipsis; }
.lside-card__meta { display: flex; align-items: center; height: 1.2rem; font-size: .78rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; }
.lside-card__bio {
  margin: .75rem 0 0;
  height: calc(1.55em * 3);
  overflow: hidden;
  font-size: .86rem;
  line-height: 1.55;
  color: var(--text-soft);
  white-space: pre-line;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}
.lside-card__bio.is-none { color: var(--text-muted); font-style: italic; }
.lside-card__tags.roster-tags { margin-top: .7rem; height: calc(var(--lside-chip-h, 22px) * 2 + .25rem); overflow: hidden; align-content: flex-start; }
.lside-card__links { display: flex; align-items: center; gap: .3rem 1rem; height: 1.25rem; margin-top: .65rem; overflow: hidden; }
/* The page's own link buttons (render_profile_link()), as plain words here */
.lside-card__links .btn-profile-link {
  gap: .4rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-dim);
  font-size: .8rem;
  white-space: nowrap;
}
.lside-card__links .btn-profile-link:hover { background: none; color: var(--text); }
.lside-card__links .btn-profile-link .btn-icon { width: 16px; height: 16px; color: inherit; }
.lside-card__links .btn-profile-link .btn-icon svg { width: 15px; height: 15px; }
.lside-card__links .btn-link-url { display: none; }
.lside-card__set { margin-top: 1rem; }
.lside-card__set .lside-head { margin-bottom: .5rem; }
.lside-card__latest { height: 88px; overflow: hidden; }
.lside-card__latest .roster { margin: 0 -.5rem; }
.lside-card__latest .roster-item-skel { border: 0; padding: .85rem .5rem; }
.lside-card__latest.is-none { display: flex; align-items: center; height: auto; min-height: 88px; color: var(--text-muted); font-size: .84rem; }
.lside-card[data-fit="compact"] .lside-card__set { display: none; }

/* text bones sit on the text's own line boxes */
.lside-bones > .skel-bone { display: block; height: .72em; margin: .415em 0; }
.lside-bones > .skel-bone:nth-child(2) { width: 93%; animation-delay: .15s; }
.lside-bones > .skel-bone:nth-child(3) { width: 64%; animation-delay: .3s; }
.lside-bones > .skel-bone:nth-child(4) { width: 80%; animation-delay: .45s; }
.lside-bone-i { display: inline-block; height: .7rem; border-radius: 4px; vertical-align: middle; }
.lside-in { animation: lside-in .2s ease both; }
@keyframes lside-in { from { opacity: 0; } }
:root[data-motion="reduce"] .lside-in { animation: none; }

/* a set: the cover large, a blurred thumb until the real one has loaded */
.lside-card__cover { position: relative; display: block; aspect-ratio: 16 / 9; background: #000; overflow: hidden; }
.lside-card[data-fit="compact"] .lside-card__cover { aspect-ratio: auto; height: 180px; }
.lside-card__cover img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.lside-card__lo { filter: blur(12px); transform: scale(1.12); }
/* Cover art (not a video): the square sits whole on its own blur, the box
   keeps its size */
.lside-card--square .lside-card__hi { object-fit: contain; }
.lside-card--square .lside-card__lo { filter: blur(18px) brightness(.7); }
.lside-card__hi { opacity: 0; transition: opacity .2s ease; }
.lside-card__hi.is-in { opacity: 1; }
.lside-card__play {
  position: absolute;
  left: 50%;
  top: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 58px;
  height: 58px;
  border: 1px solid rgba(255, 255, 255, .35);
  border-radius: 50%;
  background: rgba(0, 0, 0, .55);
  color: #fff;   /* on the cover photo in both themes */
  font-size: 1.7rem;
  pointer-events: none;
}
.lside-card__play .bi { translate: 2px 0; }
.lside-card--set .lside-card__body { display: flex; flex-direction: column; height: 16rem; padding-top: .95rem; }
.lside-card--set .lside-card__body > * { flex: none; }
.lside-card__title {
  max-height: 2.6em;
  overflow: hidden;
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text);
  text-decoration: none;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.lside-card__title:hover { text-decoration: underline; text-underline-offset: 3px; }
.lside-card__credits { display: flex; align-items: center; gap: .35rem; height: 1.6rem; margin-top: .2rem; overflow: hidden; font-size: .86rem; color: var(--text-dim); }
.lside-card--set .lside-card__meta { margin-top: .2rem; }
.lside-card--set .lside-card__tags.roster-tags { height: var(--lside-chip-h, 22px); margin-top: .55rem; }
.lside-card--set .lside-card__bio { flex: 1 1 0; height: auto; min-height: 0; margin-top: .6rem; white-space: normal; }

/* ── Spotlights (listing_side_artist_spotlight(), _community_spotlight()) ───
   Each scope's stack opens on its highlight. The Artist Spotlight is the home
   hero's stage in miniature: the artist's backdrop dimmed, a follow spot from
   above, the cut-out press photo standing in its pool of light, and the
   marquee sign with the countdown to the next pick. The stage and the sign are
   a stage and a sign in both themes; what sits under them follows the theme. */
.lside-sp, .lside-cs {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: color-mix(in srgb, var(--bg-elevated) 50%, transparent);
}
.lside-sp { --title-dot: var(--scope-color-artist); }
.lside-cs { --title-dot: var(--scope-color-community); }
.lside-sp__stage {
  position: relative;
  display: block;
  height: 184px;
  overflow: hidden;
  background: #0d0812;
}
.lside-sp__bg {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  filter: saturate(.7) brightness(.32) blur(1.5px);
  transform: scale(1.04);
}
.lside-sp__beam {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 32% 58% at 50% 62%, rgba(255, 236, 190, .30), transparent 70%),
    conic-gradient(from 180deg at 50% -12%, transparent 156deg, rgba(255, 240, 200, .34) 170deg,
      rgba(255, 240, 200, .42) 180deg, rgba(255, 240, 200, .34) 190deg, transparent 204deg);
  pointer-events: none;
}
.lside-sp__pool {
  position: absolute;
  left: 24%;
  right: 24%;
  bottom: 8px;
  height: 22px;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 233, 176, .55), transparent);
}
.lside-sp__pic {
  position: absolute;
  left: 50%;
  bottom: 10px;
  height: 132px;
  max-width: 80%;
  object-fit: contain;
  object-position: bottom;
  transform: translateX(-50%);
  filter: drop-shadow(0 0 1px rgba(255, 236, 190, .55)) drop-shadow(0 8px 12px rgba(0, 0, 0, .6));
  transition: transform .35s var(--ease);
}
.lside-sp__stage:hover .lside-sp__pic { transform: translateX(-50%) translateY(-3px); }
/* the marquee sign: a dark plate, a ring of bulbs, warm lettering */
.lside-sp__sign, .lside-cs__sign {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .42rem .75rem;
  border-radius: 6px;
  background: #1b0f24;
  outline: 1.5px dotted #ffd76a;
  outline-offset: -4px;
  color: #ffe9b0;
  font-size: .6rem;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.lside-sp__sign > .bi { color: #ffd76a; }
.lside-cs__sign { background: #0a2233; outline-color: #7dd3fc; color: #e0f2fe; }
.lside-cs__sign > .bi { color: #7dd3fc; }
.lside-sp__next {
  font-size: .56rem;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: none;
  opacity: .82;
  font-variant-numeric: tabular-nums;
}
.lside-sp__body, .lside-cs__body { padding: .7rem .9rem .75rem; }
.lside-sp__name {
  margin: 0;
  font-size: 1.4rem;
  font-weight: 850;
  letter-spacing: -.02em;
  line-height: 1.1;
  color: var(--text);
}
.lside-sp__name a { color: inherit; text-decoration: none; }
.lside-sp__name a:hover { opacity: .85; }
.lside-sp__tags { display: flex; flex-wrap: wrap; gap: .25rem; margin: .5rem 0 .55rem; }
.lside-sp .lside-line, .lside-cs .lside-line { margin-inline: -.55rem; }

/* the community's: its backdrop as a banner, its logo standing on the edge */
.lside-cs__banner {
  display: block;
  height: 98px;
  background: color-mix(in srgb, var(--scope-color-community) 30%, #0b1416) center / cover no-repeat;
  -webkit-mask-image: linear-gradient(#000 45%, transparent);
  mask-image: linear-gradient(#000 45%, transparent);
}
.lside-cs__body { position: relative; margin-top: -34px; }
.lside-cs__logo { display: inline-block; margin-bottom: .35rem; }
.lside-cs__logo img {
  display: block;
  width: 56px;
  height: 56px;
  border-radius: 12px;
  object-fit: cover;
  background: var(--bg-card);
  box-shadow: 0 0 0 3px var(--bg-card), 0 0 0 4px var(--border);
}
.lside-cs__sub { font-size: .72rem; color: var(--text-muted); margin-top: .2rem; }
.lside-cs__bio {
  margin: .4rem 0 .5rem;
  font-size: .76rem;
  line-height: 1.45;
  color: var(--text-secondary);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* Open decks running right now (listing_side_opendecks()): a row per
   community, the state as a flat LED and tracked caps in its tone */
.lside-od {
  display: flex;
  align-items: center;
  gap: .65rem;
  padding: .45rem .1rem;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  color: inherit;
  text-decoration: none;
}
.lside-od:last-child { border-bottom: 0; }
.lside-od:hover b { color: var(--text); text-decoration: underline; text-underline-offset: 2px; }
.lside-od__logo {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  object-fit: cover;
  background: var(--bg-elevated);
  box-shadow: 0 0 0 1px var(--border);
}
.lside-od__id { display: flex; flex-direction: column; min-width: 0; }
.lside-od__id b { font-size: .82rem; font-weight: 700; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lside-od__id small { font-size: .68rem; color: var(--text-muted); }
.lside-od__state {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: .35rem;
  font-size: .6rem;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  white-space: nowrap;
  color: color-mix(in srgb, var(--color-amber) 80%, var(--text));
}
.lside-od__led { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }
.lside-od__state.is-live { color: color-mix(in srgb, var(--color-success) 85%, var(--text)); }
:root[data-motion="reduce"] .lside-sp__pic { transition: none; }
:root[data-motion="reduce"] .lside-sp__stage:hover .lside-sp__pic { transform: translateX(-50%); }
/* the sign stays in front of the curtain while the next pick comes in
   (hero-curtain.js marks it .hc-keep, which would otherwise make it relative) */
.lside-sp__sign.hc-keep, .lside-cs__sign.hc-keep { position: absolute; }
