/* ============================================================================
   Listing lightbox.

   Tapping a card lifts it out of the grid rather than replacing the app with a
   full-screen player. The background blurs, the card grows a little, and the
   video plays with sound. Staying one step from the grid is the point.
   ============================================================================ */

.lb {
  position: absolute;
  inset: 0;
  z-index: var(--z-sheet);
  display: grid;
  place-items: center;
  padding: var(--s-4);
}

.lb[hidden] { display: none; }

.lb-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(18px) saturate(0.9);
  -webkit-backdrop-filter: blur(18px) saturate(0.9);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}

.lb.is-open .lb-backdrop { opacity: 1; }

/* --- the card --- */

.lb-card {
  position: relative;
  z-index: 1;
  width: min(420px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;

  background: var(--c-surface);
  border: var(--border-hairline);
  border-radius: var(--r-xl);
  overflow: hidden;

  /* Grows a little on open — enough to feel lifted, not enough to feel like a
     different screen. */
  opacity: 0;
  transform: scale(0.94);
  transition: opacity var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-spring);
}

.lb.is-open .lb-card { opacity: 1; transform: scale(1); }

.lb-close {
  position: absolute;
  top: var(--s-3);
  left: var(--s-3);
  z-index: 3;
  width: 30px;
  height: 30px;
  min-height: 0;
  min-width: 0;
  display: grid;
  place-items: center;
  border-radius: var(--r-pill);
  background: var(--c-scrim);
  color: var(--c-text);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

.lb-close:active { opacity: 0.6; }

/* --- media --- */

/* The video is the point, but it must not push the buttons off the card. It
   keeps 4:5 when there is room and gives way when there is not. */
.lb-media {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--c-raised);
  flex: 0 1 auto;
  min-height: 160px;
  max-height: 40dvh;
}

.lb-poster,
.lb-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
}

.lb-video { opacity: 0; transition: opacity var(--dur-base) var(--ease-out); }
.lb-video[src], .lb-video.is-ready { opacity: 1; }

/* --- body --- */

/* The scrollbar is hidden, which was fine when the body held four fixed rows
   and never scrolled. Now that it carries the seller's full table, content
   below the fold had no indication it existed at all — the table simply
   appeared to stop, mid-listing, which is worse than an ugly scrollbar.
   A soft fade at the bottom edge says "there is more" without adding chrome,
   and `mask-image` costs nothing because it is composited. */
.lb-body {
  flex: 1 1 auto;
  padding: var(--s-4);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;

  --fade: linear-gradient(to bottom, #000 calc(100% - 28px), transparent 100%);
  -webkit-mask-image: var(--fade);
          mask-image: var(--fade);
}

/* Once the reader is at the end there is nothing left to hint at, and the fade
   would just be dimming the last row of the table for no reason. */
.lb-body.is-ended {
  -webkit-mask-image: none;
          mask-image: none;
}

.lb-body::-webkit-scrollbar { display: none; }

.lb-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
}

.lb-place {
  font-size: var(--t-title-3);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-heading);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lb-price {
  flex-shrink: 0;
  font-family: var(--font-num);
  font-size: var(--t-callout);
  font-weight: var(--fw-bold);
  color: var(--c-gold);
  font-variant-numeric: tabular-nums;
}

.lb-seller { display: flex; align-items: center; gap: var(--s-2); }

.lb-avatar {
  width: 24px;
  height: 24px;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  background: var(--c-raised);
  color: var(--c-text);
  font-size: 11px;
  font-weight: var(--fw-bold);
  border: var(--border-hairline);
}

.lb-name { font-size: var(--t-footnote); color: var(--c-text-muted); }

.lb-seal {
  width: 13px;
  height: 13px;
  border-radius: var(--r-pill);
  display: grid;
  place-items: center;
  background: var(--c-gold);
  color: var(--c-text-on-gold);
  font-size: 8px;
  font-weight: var(--fw-bold);
}

.lb-tags { display: flex; flex-wrap: wrap; gap: var(--s-2); }

.lb-tag {
  font-size: var(--t-caption);
  color: var(--c-text-muted);
  border: var(--border-hairline);
  border-radius: var(--r-pill);
  padding: 3px var(--s-2);
}

.lb-cta {
  height: var(--tap-min);
  border-radius: var(--r-md);
  background: var(--c-gold);
  color: var(--c-text-on-gold);
  font-size: var(--t-callout);
  font-weight: var(--fw-bold);
}

.lb-cta:active { opacity: 0.75; }
.lb-cta[disabled] { background: var(--c-raised); color: var(--c-text-faint); cursor: default; }

/* --- detail block ------------------------------------------------------- */

.lb-posted {
  margin-left: auto;
  font-size: var(--t-caption);
  color: var(--c-text-faint);
  flex-shrink: 0;
}

/* Two columns of label/value. The tile carries four facts; everything else a
   buyer needs to decide lives here, one tap away. */
.lb-specs {
  margin: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-2) var(--s-4);
  padding: var(--s-3) 0;
  border-top: var(--border-hairline);
  border-bottom: var(--border-hairline);
}

.lb-specs > div { display: flex; flex-direction: column; gap: 1px; min-width: 0; }

.lb-specs dt {
  font-size: var(--t-caption-2);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-text-faint);
}

/* Values wrap. They used to be clipped to one line with an ellipsis, which was
   fine for "Fairly used" and useless for a seller's own row like
   "slightly dusty but runs perfectly" — the half that carried the meaning was
   always the half that got cut. A spec table exists to be read. */
.lb-specs dd {
  margin: 0;
  font-size: var(--t-footnote);
  font-weight: var(--fw-semibold);
  color: var(--c-text);
  overflow-wrap: anywhere;
}

/* The seller's own sentence, above the table it was turned into.
   Set apart by a gold hairline rather than a quote mark or an italic: it is the
   one piece of the listing written by a person, and the accent is how this
   product marks something as carrying weight. */
.lb-desc {
  margin: 0;
  padding-left: var(--s-3);
  border-left: 2px solid var(--c-gold);
  font-size: var(--t-subhead);
  line-height: var(--lh-body);
  color: var(--c-text-muted);
}

/* --- actions --- */

/* Pinned to the bottom of the card, outside the scroll region. */
.lb-actions {
  flex: 0 0 auto;
  display: flex;
  gap: var(--s-2);
  padding: var(--s-3) var(--s-4) var(--s-4);
  border-top: var(--border-hairline);
  background: var(--c-surface);
}

.lb-save {
  flex: 0 0 auto;
  width: var(--tap-min);
  height: var(--tap-min);
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  border: var(--border-hairline);
  background: var(--c-raised);
  color: var(--c-text-faint);
  transition: color var(--dur-fast) var(--ease-out);
}

.lb-save.is-on { color: var(--c-danger); border-color: var(--c-danger); }
.lb-save:active { opacity: 0.7; }

.lb-cta { flex: 1 1 auto; }
