/* /collaborations browse page
   Mobile-app-native marketplace browse. Mobile-first.
   Reuses shared component classes (.page-header, .button, .badge, .empty-state)
   and only adds layout + listing-card specifics.

   Redesigned 2026-05-22 for "native mobile app" feel:
   - Sticky member header owns the title on mobile (in-content .page-header hidden)
   - Compact stat strip frames small-numbers as private-beta curation
   - Horizontal category rail with edge-fade
   - Whole-card-tappable listings (no per-card filled button)
   - Floating Post FAB sits above global bottom tab bar
   - Two-layer shadow on every card, press-scale on tap
   - Staggered entrance animations on first paint
*/

/* ── Page wrapper ───────────────────────────────────────── */
.marketplace-browse {
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--space-4) var(--space-4) var(--space-12);
  position: relative;
}

@media (min-width: 768px) {
  .marketplace-browse {
    padding: var(--space-8) var(--space-6) var(--space-16);
  }
}

/* === MOBILE PADDING DISCIPLINE ===
   Two parents stack edge padding on mobile (main.member-main = 12px + this
   wrapper = 16px → 28px viewport-to-card, over the 16px ceiling). Take
   ownership of the page edge on this page: zero out main.member-main side
   padding (top is canonical, NOT touched) and own the 16px ourselves.
   Scoped via :has() so other pages are unaffected. */
@media (max-width: 767px) {
  main.member-main:has(.marketplace-browse) {
    padding-left: 0;
    padding-right: 0;
    /* Override main.member-main's default `overflow: hidden auto`. That
       creates a scroll container, which scopes our sticky chip rail to
       main instead of the viewport — sticky then fails to "stick" as
       the page scrolls. We don't need either axis of scroll inside main
       on this page: the page itself is the scroll container. */
    overflow: visible;
  }
  .marketplace-browse {
    padding: 0 16px 96px;
  }

  /* Sticky member header owns the title — hide in-content page-header.
     Only logged-in members (base_members.twig). Logged-out users on
     base.twig have no sticky title, so keep their in-content header. */
  .marketplace-browse--member .page-header {
    display: none;
  }
}

/* ── Compact stat strip (mobile-first) ─────────────────────
   Replaces the page subtitle on mobile. Eyebrow first (curated framing
   that turns small absolute numbers into private-beta cachet), then a
   dramatic display count. The count uses tabular-nums so the number
   does not jitter when the live list updates. */
.mp-status-strip {
  padding: 4px 0 var(--space-4);
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
}
.mp-status-strip__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.75rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--color-primary);
  background: #eef2ff;
  padding: 5px 10px;
  border-radius: 999px;
  margin-bottom: 10px;
  box-shadow: 0 1px 2px rgba(79, 70, 229, 0.06);
}
/* Tiny dot prefix on the eyebrow — adds a "live" pulse without taking space.
   Subtle (1.8s ease) so it reads as breathing, not blinking. */
.mp-status-strip__eyebrow::before {
  content: '';
  display: inline-block;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--color-primary);
  animation: mpEyebrowPulse 1.8s ease-in-out infinite;
}
@keyframes mpEyebrowPulse {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: 0.4; transform: scale(0.85); }
}
@media (prefers-reduced-motion: reduce) {
  .mp-status-strip__eyebrow::before { animation: none; }
}
.mp-status-strip__row {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.mp-status-strip__count {
  font-size: 1.75rem;             /* 28px — louder, more confident */
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--color-gray-900);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.mp-status-strip__label {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--color-gray-600);
  letter-spacing: -0.005em;
}

@media (min-width: 768px) {
  .mp-status-strip { display: none; }
}

/* ── Category rail (horizontal scroll with edge-fade) ──────
   On mobile the rail STICKS just below the fixed header so users can
   filter without scrolling all the way back up. iOS App Store pattern.
   The rail is a flex container: chips scroll horizontally on the left,
   the "+Post" pill is fixed on the right (always visible). */
.mp-category-rail {
  position: relative;
  margin: 0 -16px var(--space-3);
  padding: var(--space-1) 0 var(--space-3);
  display: flex;
  align-items: center;
  gap: 8px;
}
@media (max-width: 767px) {
  .mp-category-rail {
    position: sticky;
    top: 60px; /* sticks under .member-header */
    z-index: 30;
    padding-top: 8px;
    padding-bottom: 10px;
    /* Opaque white per the design skill's mobile chrome rule — translucent
       backdrop-blur on primary sticky chrome reads as washed-out, not iOS. */
    background: #ffffff;
    box-shadow:
      0 1px 0 var(--color-gray-100),
      0 2px 4px rgba(15, 23, 42, 0.04);
  }
}
.mp-category-rail::before,
.mp-category-rail::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 24px;
  pointer-events: none;
  z-index: 2;
}
.mp-category-rail::before {
  left: 0;
  background: linear-gradient(to right, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
}
.mp-category-rail::after {
  right: 0;
  background: linear-gradient(to left, #ffffff 0%, rgba(255, 255, 255, 0) 100%);
}
.mp-category-chips {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 0 4px var(--space-4);
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  scroll-snap-type: x proximity;
  flex: 1 1 auto;
  min-width: 0;
}
.mp-category-chips::-webkit-scrollbar { display: none; }

/* ── Trailing "+Post" pill in the rail (logged-in only).
   Fixed at the right edge of the rail — does NOT scroll with chips,
   so it's persistently tappable while filters slide. */
.mp-rail-post {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  margin-right: 16px;
  padding: 0 13px 0 11px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: -0.005em;
  text-decoration: none;
  white-space: nowrap;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.18) inset,
    0 1px 2px rgba(15, 23, 42, 0.08),
    0 4px 12px -2px rgba(79, 70, 229, 0.34);
  transition: transform 80ms ease, background-color 150ms ease, box-shadow 200ms ease;
}
.mp-rail-post,
.mp-rail-post:hover,
.mp-rail-post:focus,
.mp-rail-post:focus-visible,
.mp-rail-post:visited,
.mp-rail-post:active { color: #fff; }
.mp-rail-post:hover { background: var(--color-primary-dark); }
.mp-rail-post:active { transform: scale(0.96); }
.mp-rail-post i { font-size: 0.75rem; line-height: 1; }
@media (min-width: 768px) {
  .mp-rail-post { display: none; } /* desktop uses the page-header CTA */
}

.mp-category-chip {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--color-gray-200);
  border-radius: 999px;
  background: #fff;
  color: var(--color-gray-800);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 120ms ease, color 120ms ease, border-color 120ms ease, transform 80ms ease;
  scroll-snap-align: start;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.9) inset, 0 1px 2px rgba(15, 23, 42, 0.04);
}
.mp-category-chip:hover {
  border-color: var(--color-gray-300);
  color: var(--color-gray-900);
}
.mp-category-chip:active {
  transform: scale(0.96);
}
.mp-category-chip.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.18) inset, 0 2px 6px rgba(79, 70, 229, 0.28);
}
.mp-category-chip.is-active:hover,
.mp-category-chip.is-active:focus,
.mp-category-chip.is-active:visited {
  color: #fff;
}

/* Desktop: collapse rail to natural wrap, drop edge fade */
@media (min-width: 768px) {
  .mp-category-rail {
    margin: 0 0 var(--space-6);
    padding: 0;
  }
  .mp-category-rail::before,
  .mp-category-rail::after { display: none; }
  .mp-category-chips {
    flex-wrap: wrap;
    overflow: visible;
    padding: 0;
  }
}

/* ── Listing grid ─────────────────────────────────────────
   Sparse-state (1-3 listings) uses the same single-column on mobile but
   gets featured padding on the card. Desktop centers the grid. */
.mp-listing-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}

@media (min-width: 768px) {
  .mp-listing-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-5);
  }
}

@media (min-width: 1024px) {
  .mp-listing-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-6);
    /* dense flow lets regular cards backfill the gap a 2-col featured
       card leaves on rows where another span-2 doesn't fit alongside it */
    grid-auto-flow: dense;
  }
  .mp-listing-grid:has(> .mp-card:nth-child(1):last-child) {
    grid-template-columns: minmax(0, 480px);
    justify-content: center;
  }
  .mp-listing-grid:has(> .mp-card:nth-child(2):last-child) {
    grid-template-columns: repeat(2, minmax(0, 360px));
    justify-content: center;
  }
}

/* ── Listing card — app-native, whole-row tappable ──────── */
.mp-card {
  background: #fff;
  border: 1px solid var(--color-gray-100);
  border-radius: 18px;
  overflow: hidden;
  position: relative;
  transition: transform 80ms ease, box-shadow 200ms ease, border-color 200ms ease;
  /* Two-layer shadow recipe (hairline highlight + soft drop) per design rules */
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 1px 2px rgba(15, 23, 42, 0.05),
    0 8px 24px -10px rgba(15, 23, 42, 0.08);
  /* Entrance animation — staggered via :nth-child below */
  opacity: 0;
  animation: mpCardIn 460ms cubic-bezier(0.22, 1, 0.36, 1) forwards;
}
.mp-card:nth-child(1) { animation-delay: 40ms; }
.mp-card:nth-child(2) { animation-delay: 100ms; }
.mp-card:nth-child(3) { animation-delay: 160ms; }
.mp-card:nth-child(4) { animation-delay: 220ms; }
.mp-card:nth-child(5) { animation-delay: 280ms; }
.mp-card:nth-child(6) { animation-delay: 340ms; }
.mp-card:nth-child(n+7) { animation-delay: 400ms; }

@keyframes mpCardIn {
  0%   { opacity: 0; transform: translateY(10px); }
  100% { opacity: 1; transform: translateY(0); }
}

.mp-card:hover {
  border-color: var(--color-gray-200);
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 2px 4px rgba(15, 23, 42, 0.06),
    0 20px 40px -14px rgba(15, 23, 42, 0.16);
}
.mp-card:active {
  transform: translateY(0) scale(0.985);
  transition: transform 80ms ease;
}

/* Featured (Elite plan) — earns visual hierarchy.
   Gold ring + warmer shadow tint (sits on all four edges, never a side-stripe).
   On 3-up desktop grids, featured cards SPAN 2 COLUMNS, creating intentional
   asymmetry across the marketplace grid (Etsy / Airbnb editorial pattern).
   On mobile, featured cards get a touch more body-wrap padding so the title
   can breathe a hair more. */
.mp-card--featured {
  border-color: #e8d68b;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 1px 2px rgba(180, 130, 0, 0.06),
    0 12px 28px -10px rgba(212, 160, 23, 0.22);
}
.mp-card--featured:hover {
  border-color: #d4a017;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 2px 4px rgba(180, 130, 0, 0.08),
    0 20px 40px -14px rgba(212, 160, 23, 0.32);
}
@media (min-width: 768px) {
  .mp-card--featured .mp-card__body-wrap {
    padding: 18px 20px 18px 20px;
  }
}
/* Desktop 3-up magazine grid:
   Featured cards span 2 columns AND 2 rows. The two cells beside them
   (col 3, rows 1+2) fill with two stacked regular cards — matching the
   featured card's height, no stranded empty space. The body-wrap grows
   to fill any leftover space; byline (margin-top: auto) sticks to the
   bottom so the layout reads as intentional. */
@media (min-width: 1024px) {
  .mp-listing-grid > .mp-card--featured {
    grid-column: span 2;
    grid-row: span 2;
  }
  .mp-card--featured .mp-card__title {
    font-size: 1.5rem;          /* 24px — featured title is the screen hero */
    line-height: 1.2;
    letter-spacing: -0.025em;
    /* Featured has 2x the height — let the title breathe to 3 lines before
       ellipsis. Most titles are 1-2 lines, so this rarely triggers; when it
       does, the longer pitch actually fits instead of being cut off. */
    -webkit-line-clamp: 3;
  }
  .mp-card--featured .mp-card__body {
    font-size: 0.9375rem;
    /* Six body lines on featured — uses the real estate that the 2-row
       span gave us. Cards with short bodies stay short (flex layout),
       cards with long pitches get to actually deliver them. */
    -webkit-line-clamp: 6;
    line-height: 1.55;
    margin: 0 0 16px;
  }
  .mp-card--featured .mp-card__body-wrap {
    padding: 24px 26px 22px 26px;
    gap: 2px;
  }
}

.mp-card__link {
  display: block;
  padding: 18px 16px 18px 16px;
  text-decoration: none;
  color: inherit;
  /* Reserve right-edge room for chevron */
  padding-right: 38px;
}

/* ── Category pill (corner overlay, category-tinted) ────── */
/* Pill row (v5.2): standalone row between poster and title.
   Consistent placement on every card; meta-row stays single-line. */
.mp-card__pill-row {
  margin: 4px 0 10px;
  display: flex;
  align-items: center;
}

/* Category pill (v5.2): sits inside .mp-card__pill-row, slightly larger
   now that it owns its own line and isn't competing with meta text. */
.mp-card__pill {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  line-height: 1;
  flex-shrink: 0;
  /* Default tint — overridden per-category below */
  background: #eef2ff;
  color: #4338ca;
}
.mp-card--joint_video .mp-card__pill              { background: #eef2ff; color: #4338ca; }
.mp-card--guest_appearance .mp-card__pill         { background: #fef3c7; color: #92400e; }
.mp-card--shorts_collab .mp-card__pill            { background: #fce7f3; color: #9d174d; }
.mp-card--challenge_video .mp-card__pill          { background: #ffe4e6; color: #9f1239; }
.mp-card--series_collaboration .mp-card__pill     { background: #dbeafe; color: #1e40af; }
.mp-card--live_stream .mp-card__pill              { background: #fee2e2; color: #991b1b; }
.mp-card--featured_channel_exchange .mp-card__pill{ background: #dcfce7; color: #166534; }
.mp-card--other .mp-card__pill                    { background: var(--color-gray-100); color: var(--color-gray-700); }

/* ── Poster row (v5.1) ─────────────────────────────────────
   The category pill moved out of the corner into the meta row, so the
   channel name now uses the full poster-row width (only the avatar +
   gap on the left, and the small bookmark-button clearance up top). */
.mp-card__poster {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  /* No right-padding reservation. */
}

.mp-card__avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--color-gray-100);
  flex-shrink: 0;
  box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.06);
}
.mp-card__avatar--placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-gray-400);
  font-size: 1rem;
  background: var(--color-gray-100);
}

.mp-card__poster-info {
  min-width: 0;
  flex: 1;
}

.mp-card__channel-name {
  font-weight: 700;
  font-size: 0.875rem;
  color: var(--color-gray-900);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: -0.01em;
  line-height: 1.25;
}

.mp-card__crown {
  color: #d4a017;
  font-size: 0.75rem;
  margin-left: 4px;
}

.mp-card__subs {
  font-size: 0.75rem;
  color: var(--color-gray-500);
  letter-spacing: -0.005em;
  font-weight: 500;
  margin-top: 2px;
}

/* ── Title + body ───────────────────────────────────────── */
.mp-card__title {
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--color-gray-900);
  letter-spacing: -0.015em;
  margin: 0 0 6px;
  word-break: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.mp-card__body {
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--color-gray-600);
  margin: 0 0 12px;
  word-break: break-word;
  overflow-wrap: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── DNA tags (max 2 + overflow count) ──────────────────── */
.mp-card__tags {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  margin: 0;
  overflow: hidden;
}

.mp-card__tag {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  background: var(--color-gray-50, #f8fafc);
  border: 1px solid var(--color-gray-100);
  border-radius: 999px;
  font-size: 0.6875rem;
  color: var(--color-gray-700);
  font-weight: 600;
  letter-spacing: -0.005em;
  white-space: nowrap;
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.mp-card__tag--more {
  background: transparent;
  border-color: transparent;
  color: var(--color-gray-500);
  padding: 0 2px;
}

/* ── Chevron (whole-card-tappable affordance) ───────────── */
.mp-card__chev {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-gray-300);
  font-size: 0.8125rem;
  transition: color 150ms ease, transform 150ms ease;
  pointer-events: none;
  line-height: 1;
}
.mp-card:hover .mp-card__chev {
  color: var(--color-primary);
  transform: translateY(-50%) translateX(2px);
}

/* ── Sparse-state: featured padding on every card when only 1-2 listings ── */
.marketplace-browse--sparse .mp-card__link {
  padding: 22px 18px 22px 18px;
  padding-right: 42px;
}
.marketplace-browse--sparse .mp-card__title {
  font-size: 1.1875rem;
  -webkit-line-clamp: 3;
}
.marketplace-browse--sparse .mp-card__body {
  font-size: 0.875rem;
  -webkit-line-clamp: 3;
}

/* (v3 2026-05-22) The floating "+Post" FAB was removed. The Post action
   now lives as a fixed trailing pill in the .mp-category-rail (see above),
   eliminating the bottom-right cluster with the Concierge bubble and
   language switcher. No lang-switcher lift hack is needed anymore. */

/* ── Empty state — app-native, friendly ───────────────────
   Fades up on mount; bubbles drift gently to give the empty surface a
   sense of life rather than feeling like a dead end. */
.mp-empty {
  max-width: 520px;
  margin: var(--space-6) auto var(--space-12);
  text-align: center;
  padding: var(--space-6) var(--space-4);
  opacity: 0;
  animation: mpEmptyIn 520ms cubic-bezier(0.22, 1, 0.36, 1) 80ms forwards;
}
@keyframes mpEmptyIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.mp-empty__art {
  position: relative;
  width: 132px;
  height: 88px;
  margin: 0 auto var(--space-5);
}
.mp-empty__bubble {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 52px;
  height: 52px;
  border-radius: 50%;
  font-size: 1.125rem;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 6px 16px rgba(15, 23, 42, 0.1);
  /* Default float animation — each variant overrides timing/origin */
  animation: mpBubbleFloat 5.6s ease-in-out infinite;
}
.mp-empty__bubble--a {
  background: #eef2ff;
  color: #4338ca;
  top: 8px;
  left: 0;
  --rot: -8deg;
  animation-delay: 0ms;
}
.mp-empty__bubble--b {
  background: #fce7f3;
  color: #9d174d;
  top: 24px;
  left: 50%;
  margin-left: -29px;
  z-index: 2;
  width: 58px;
  height: 58px;
  font-size: 1.25rem;
  --rot: 0deg;
  animation-delay: 600ms;
}
.mp-empty__bubble--c {
  background: #dcfce7;
  color: #166534;
  top: 8px;
  right: 0;
  --rot: 8deg;
  animation-delay: 1200ms;
}
@keyframes mpBubbleFloat {
  0%, 100% { transform: rotate(var(--rot, 0deg)) translateY(0); }
  50%      { transform: rotate(var(--rot, 0deg)) translateY(-4px); }
}
.mp-empty__bubble--b {
  /* B is centered horizontally with margin-left and shouldn't rotate. */
}
@media (prefers-reduced-motion: reduce) {
  .mp-empty { animation: none; opacity: 1; }
  .mp-empty__bubble { animation: none; transform: rotate(var(--rot, 0deg)); }
}

.mp-empty__title {
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 1.375rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--color-gray-900);
  margin: 0 0 8px;
}
.mp-empty__body {
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--color-gray-600);
  margin: 0 0 var(--space-5);
}
.mp-empty__body a {
  color: var(--color-primary);
  font-weight: 600;
  text-decoration: none;
}
.mp-empty__body a:hover {
  text-decoration: underline;
}
.mp-empty__cta .button {
  min-width: 200px;
}

/* ── Load-more sentinel ─────────────────────────────────── */
.mp-load-more {
  display: flex;
  justify-content: center;
  margin: var(--space-6) 0 var(--space-4);
}
/* Load-more button polish — appears as the user nears the bottom of the
   grid. While the JS sets disabled+textContent to "Loading…", the button
   gets a left-aligned mini-spinner via ::before so the loading state reads
   as alive, not frozen. */
#mp-load-more-btn {
  position: relative;
  min-width: 180px;
  font-weight: 600;
  letter-spacing: -0.005em;
  transition: transform 100ms ease, opacity 150ms ease;
}
#mp-load-more-btn:active { transform: scale(0.97); }
#mp-load-more-btn:disabled {
  opacity: 1;
  cursor: default;
  padding-left: 38px;     /* room for the spinner */
}
#mp-load-more-btn:disabled::before {
  content: '';
  position: absolute;
  left: 16px;
  top: 50%;
  width: 14px;
  height: 14px;
  margin-top: -7px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: mpLoadSpin 720ms linear infinite;
  opacity: 0.75;
}
@keyframes mpLoadSpin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  #mp-load-more-btn:disabled::before {
    animation: none;
    border-right-color: currentColor;
    opacity: 0.4;
  }
}

/* ── Loading state for cards being appended ─────────────── */
.mp-card.is-skeleton {
  pointer-events: none;
}
.mp-card.is-skeleton .mp-card__title,
.mp-card.is-skeleton .mp-card__body {
  background: var(--color-gray-100);
  color: transparent;
  border-radius: 4px;
}

/* ══════════════════════════════════════════════════════════
   v2 ADDITIONS (2026-05-22) — appended to override v1
   ══════════════════════════════════════════════════════════ */

/* ── v2: Avatar initial fallback (category-tinted gradient circle) ── */
.mp-card__avatar--initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 1.0625rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  background: linear-gradient(135deg, #6366f1 0%, #4338ca 100%);
  box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.06), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.mp-card--joint_video              .mp-card__avatar--initial { background: linear-gradient(135deg, #818cf8, #4338ca); }
.mp-card--guest_appearance         .mp-card__avatar--initial { background: linear-gradient(135deg, #fbbf24, #b45309); }
.mp-card--shorts_collab            .mp-card__avatar--initial { background: linear-gradient(135deg, #f472b6, #9d174d); }
.mp-card--challenge_video          .mp-card__avatar--initial { background: linear-gradient(135deg, #fb7185, #9f1239); }
.mp-card--series_collaboration     .mp-card__avatar--initial { background: linear-gradient(135deg, #60a5fa, #1e40af); }
.mp-card--live_stream              .mp-card__avatar--initial { background: linear-gradient(135deg, #f87171, #991b1b); }
.mp-card--featured_channel_exchange .mp-card__avatar--initial { background: linear-gradient(135deg, #4ade80, #166534); }
.mp-card--other                    .mp-card__avatar--initial { background: linear-gradient(135deg, #94a3b8, #475569); }

/* ── v2: Meta row — subs · time · NEW pill ── */
.mp-card__meta {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-top: 2px;
  font-size: 0.75rem;
  color: var(--color-gray-500);
  font-weight: 500;
  letter-spacing: -0.005em;
  flex-wrap: nowrap;       /* identical position across cards — never wrap */
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.mp-card__meta .mp-card__subs {
  font-size: inherit;
  color: var(--color-gray-600);
  margin-top: 0;
  font-weight: 600;
}
.mp-card__meta-dot {
  color: var(--color-gray-300);
  font-weight: 700;
}
.mp-card__time {
  white-space: nowrap;
}
.mp-card__new {
  display: inline-flex;
  align-items: center;
  height: 16px;
  padding: 0 6px;
  margin-left: 4px;
  border-radius: 999px;
  background: #ecfdf5;
  color: #047857;
  font-size: 0.5625rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  line-height: 1;
}

/* ── v2: Featured (Elite) card — magnetic, NOT a side stripe ── */
.mp-card--featured {
  border: 1.5px solid #e0c878;
  background: linear-gradient(165deg, #fffbeb 0%, #ffffff 38%);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.95) inset,
    0 1px 2px rgba(180, 130, 0, 0.08),
    0 14px 32px -10px rgba(212, 160, 23, 0.22);
}
.mp-card--featured:hover {
  border-color: #d4a017;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.95) inset,
    0 1px 2px rgba(180, 130, 0, 0.12),
    0 18px 38px -12px rgba(212, 160, 23, 0.32);
}
.mp-card--featured .mp-card__pill {
  background: linear-gradient(135deg, #fde68a, #fbbf24);
  color: #78350f;
  box-shadow: 0 0 0 1px rgba(180, 130, 0, 0.18);
}
.mp-card__pill-crown {
  font-size: 0.55rem;
  margin-right: 4px;
  color: #92400e;
  vertical-align: -1px;
}

/* ── Shimmer skeleton (v6 — rewritten for the hero-thumbnail card
   structure). Three shimmering surfaces per skeleton card:
     1. The hero rectangle (was a thumbnail)
     2. The title row
     3. The body preview row
   All chip / pill / chevron / byline overlays are hidden during skeleton
   so the placeholder reads as pure geometry. The bookmark stays hidden
   too — it's a tap target, not content. */
@keyframes mpShimmer {
  0%   { background-position: -240px 0; }
  100% { background-position: calc(240px + 100%) 0; }
}
.mp-card.is-skeleton {
  pointer-events: none;
  opacity: 1;
  animation: none;
}
.mp-card.is-skeleton .mp-card__hero,
.mp-card.is-skeleton .mp-card__title,
.mp-card.is-skeleton .mp-card__body {
  background: linear-gradient(
    90deg,
    var(--color-gray-100) 0px,
    var(--color-gray-50, #f8fafc) 80px,
    var(--color-gray-100) 160px
  );
  background-size: 240px 100%;
  background-repeat: no-repeat;
  animation: mpShimmer 1600ms ease-in-out infinite;
  color: transparent;
}
.mp-card.is-skeleton .mp-card__thumb,
.mp-card.is-skeleton .mp-card__hero-new,
.mp-card.is-skeleton .mp-card__hero-pill,
.mp-card.is-skeleton .mp-card__hero-responses,
.mp-card.is-skeleton .mp-card__save,
.mp-card.is-skeleton .mp-card__byline,
.mp-card.is-skeleton .mp-card__hero::after {
  display: none !important;
}
.mp-card.is-skeleton .mp-card__title {
  height: 22px;
  border-radius: 6px;
  margin: 0 0 10px;
}
.mp-card.is-skeleton .mp-card__body {
  height: 14px;
  border-radius: 5px;
  margin: 0;
}
@media (prefers-reduced-motion: reduce) {
  .mp-card.is-skeleton .mp-card__hero,
  .mp-card.is-skeleton .mp-card__title,
  .mp-card.is-skeleton .mp-card__body {
    animation: none;
    background: var(--color-gray-100);
  }
}

/* ══════════════════════════════════════════════════════════
   v4 ADDITIONS (2026-05-22) — bookmark toggle + Saved chip
   ══════════════════════════════════════════════════════════ */

/* Bookmark button: sibling of .mp-card__link, sits at top-LEFT
   corner of the card so it doesn't collide with the corner pill
   or the right-edge chevron. 32px circular hit-target.
   Dark glass chrome matches the category pill + response chip family
   for system consistency across all hero overlays. */
.mp-card__save {
  position: absolute;
  top: 10px;
  left: 10px;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(15, 23, 42, 0.6);
  -webkit-backdrop-filter: blur(8px) saturate(180%);
  backdrop-filter: blur(8px) saturate(180%);
  color: #fff;
  font-size: 0.875rem;
  cursor: pointer;
  z-index: 2; /* above link anchor */
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.08) inset,
    0 2px 6px rgba(15, 23, 42, 0.32);
  transition: transform 100ms cubic-bezier(0.22, 1, 0.36, 1),
              color 120ms ease,
              background-color 120ms ease,
              box-shadow 200ms ease;
}
.mp-card__save:hover {
  background: rgba(15, 23, 42, 0.78);
  color: #fff;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.12) inset,
    0 4px 12px rgba(15, 23, 42, 0.38);
}
.mp-card__save:active { transform: scale(0.88); }
.mp-card__save[aria-pressed="true"] {
  background: var(--color-primary);
  color: #fff;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.18) inset,
    0 1px 2px rgba(15, 23, 42, 0.12),
    0 4px 10px -2px rgba(79, 70, 229, 0.42);
}
.mp-card__save[aria-pressed="true"]:hover {
  background: var(--color-primary-dark);
  color: #fff;
}
.mp-card__save--pending {
  opacity: 0.6;
  pointer-events: none;
}
/* Bookmark slot offset: shift the poster row so the channel name doesn't
   start under the bookmark button. Avatar stays put. */
.mp-card__poster {
  /* +32 (button width) +6 gap = ~38px left clearance */
  padding-left: 38px;
}

/* Saved chip in the rail — at the start (before "All") with a bookmark
   icon so it reads as a "view: saved" toggle, distinct from category
   chips. Only present when logged in (twig-gated). */
.mp-category-chip--saved {
  background: linear-gradient(135deg, #eef2ff, #e0e7ff);
  border-color: #c7d2fe;
  color: #4338ca;
}
.mp-category-chip--saved i {
  margin-right: 4px;
  font-size: 0.75rem;
}
.mp-category-chip--saved.is-active {
  background: var(--color-primary);
  border-color: var(--color-primary);
  color: #fff;
}

/* Saved-view empty state mirrors .mp-empty but lighter. */
.mp-empty--saved {
  border: 1px dashed var(--color-gray-200);
  border-radius: 16px;
  background: #fff;
}

/* ══════════════════════════════════════════════════════════
   v3 ADDITIONS (2026-05-22) — search input + no-results state
   ══════════════════════════════════════════════════════════ */

.mp-search {
  margin: 0 0 var(--space-3);
}
.mp-search__field {
  position: relative;
  display: flex;
  align-items: center;
}
.mp-search__icon {
  position: absolute;
  left: 16px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--color-gray-400);
  font-size: 0.9375rem;
  pointer-events: none;
  transition: color 150ms ease;
}
.mp-search__field:focus-within .mp-search__icon {
  color: var(--color-primary);
}
.mp-search__input {
  flex: 1;
  width: 100%;
  height: 48px;                 /* iOS Search bar height */
  padding: 0 44px 0 40px;
  border: 1px solid var(--color-gray-200);
  border-radius: 16px;          /* iOS rounded search */
  background: #fff;
  font-size: 1rem;              /* prevents iOS auto-zoom on focus */
  font-weight: 500;
  color: var(--color-gray-900);
  letter-spacing: -0.005em;
  -webkit-appearance: none;
  appearance: none;
  outline: none;
  transition: border-color 150ms ease, box-shadow 150ms ease, transform 100ms ease;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.9) inset,
    0 1px 2px rgba(15, 23, 42, 0.04),
    0 4px 14px -6px rgba(15, 23, 42, 0.06);
}
.mp-search__input:hover {
  border-color: var(--color-gray-300);
}
.mp-search__input::placeholder {
  color: var(--color-gray-400);
  font-weight: 500;
}
.mp-search__input:focus,
.mp-search__input:focus-visible {
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.14);
}
/* Hide the native iOS search clear "X" — we render our own */
.mp-search__input::-webkit-search-cancel-button,
.mp-search__input::-webkit-search-decoration { -webkit-appearance: none; }

.mp-search__clear {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 999px;
  background: var(--color-gray-100);
  color: var(--color-gray-500);
  font-size: 0.6875rem;
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease, transform 80ms ease;
}
.mp-search__clear:hover {
  background: var(--color-gray-200);
  color: var(--color-gray-800);
}
.mp-search__clear:active { transform: translateY(-50%) scale(0.92); }
.mp-search__clear[hidden] { display: none; }

/* ── No-results state for active search ── */
.mp-no-results {
  text-align: center;
  padding: var(--space-6) var(--space-4);
  max-width: 480px;
  margin: 0 auto;
}
.mp-no-results__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: #eef2ff;
  color: #4338ca;
  font-size: 1.25rem;
  margin: 0 auto var(--space-3);
  box-shadow: 0 4px 14px rgba(67, 56, 202, 0.12);
}
.mp-no-results__title {
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 1.125rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--color-gray-900);
  margin: 0 0 6px;
}
.mp-no-results__body {
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--color-gray-600);
  margin: 0 0 var(--space-4);
}
.mp-no-results__suggest {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 14px;
  border-radius: 999px;
  background: var(--color-primary);
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 700;
  text-decoration: none;
  border: none;
  cursor: pointer;
}
.mp-no-results__suggest:hover { background: var(--color-primary-dark); color: #fff; }

/* ── Reduced motion ─────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .mp-card {
    opacity: 1;
    animation: none;
    transition: box-shadow 200ms ease, border-color 200ms ease;
  }
  .mp-card:active { transform: none; }
  .mp-category-chip:active { transform: none; }
  .mp-rail-post:active { transform: none; }
  .mp-search__clear:active { transform: translateY(-50%); }
}

/* ══════════════════════════════════════════════════════════
   v5 ADDITIONS (2026-05-22) — first-save success toast
   (Editorial "Just posted today" section headers from v5 were removed
   in v5.1 per founder feedback.)
   ══════════════════════════════════════════════════════════ */

/* ── First-save success toast ─────────────────────────────
   Floats above the bottom nav, centered, with a "View saved" tap-action.
   Shown ONCE per browser (localStorage-gated). ── */
.mp-save-toast {
  position: fixed;
  left: 50%;
  bottom: calc(64px + env(safe-area-inset-bottom, 0px) + 20px);
  transform: translateX(-50%) translateY(16px);
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: calc(100vw - 32px);
  padding: 10px 8px 10px 14px;
  border-radius: 14px;
  background: #0f172a;
  color: #fff;
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  opacity: 0;
  pointer-events: none;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.06) inset,
    0 12px 28px rgba(15, 23, 42, 0.32),
    0 2px 6px rgba(15, 23, 42, 0.18);
  z-index: 5200; /* above lang-switcher (5000) + FAB-class (5100 if present) */
  transition: opacity 200ms ease, transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}
.mp-save-toast--visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  pointer-events: auto;
}
.mp-save-toast__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: rgba(34, 197, 94, 0.18);
  color: #4ade80;
  font-size: 0.6875rem;
  flex-shrink: 0;
}
.mp-save-toast__label {
  white-space: nowrap;
}
.mp-save-toast__cta {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  text-decoration: none;
  margin-left: 4px;
  transition: background-color 120ms ease, transform 80ms ease;
}
.mp-save-toast__cta:hover,
.mp-save-toast__cta:focus,
.mp-save-toast__cta:visited,
.mp-save-toast__cta:active { color: #fff; text-decoration: none; }
.mp-save-toast__cta:hover { background: rgba(255, 255, 255, 0.22); }
.mp-save-toast__cta:active { transform: scale(0.96); }

@media (prefers-reduced-motion: reduce) {
  .mp-save-toast {
    transition: opacity 200ms ease;
    transform: translateX(-50%);
  }
  .mp-save-toast--visible { transform: translateX(-50%); }
}

/* ══════════════════════════════════════════════════════════
   v6 ADDITIONS (2026-05-22) — Hero-thumbnail card layout
   Replaces the text-heavy card body with: 16:9 thumbnail at top,
   then title big + body 1-line + small byline strip. Bookmark + NEW +
   category pill overlay the thumbnail. No chevron, no DNA tags.
   ══════════════════════════════════════════════════════════ */

/* The anchor lays out hero + body-wrap vertically and is flex so that
   body-wrap can grow to fill any stretched card height (e.g. when a
   regular card sits in the same row as a 2-row featured card on the
   desktop magazine grid). Without flex, stretched cards leave a dead
   pocket below their byline. Padding is zero so the thumbnail can
   extend edge-to-edge — body padding lives on .mp-card__body-wrap. */
.mp-card__link {
  display: flex;
  flex-direction: column;
  padding: 0 !important;
  text-decoration: none;
  color: inherit;
  height: 100%;
}
.marketplace-browse--sparse .mp-card__link {
  padding: 0 !important;
}

/* ── HERO (top section): 16:9 thumbnail or category-tinted placeholder ── */
.mp-card__hero {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: var(--color-gray-100);
  overflow: hidden;
  /* Match the parent card's top corner radius. The card has border-radius: 18px;
     overflow: hidden already, so we don't need to repeat it here, but explicit
     keeps it intentional. */
}
/* Subtle bottom-fade scrim so poster-baked thumbnail overlays
   (channel name, video title text painted onto the thumbnail) recede
   behind the category pill / response chip. Covers the bottom ~45% of
   the hero at a max 0.4 alpha — soft enough to leave clean thumbnails
   alone, strong enough to mute text-heavy ones. Pointer-events none so
   chip / pill / bookmark stay tappable. */
.mp-card__hero::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 45%;
  background: linear-gradient(
    to top,
    rgba(15, 23, 42, 0.4) 0%,
    rgba(15, 23, 42, 0.15) 40%,
    rgba(15, 23, 42, 0) 100%
  );
  pointer-events: none;
  z-index: 1;
}
/* Placeholder hero (no cached video) already has a category gradient,
   doesn't need the dark scrim — the gradient IS the texture. */
.mp-card__thumb--placeholder ~ .mp-card__hero-pill { /* no-op selector */ }
.mp-card__hero:has(.mp-card__thumb--placeholder)::after {
  display: none;
}

.mp-card__thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: var(--color-gray-100);
  transition: transform 600ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: transform;
}
.mp-card:hover .mp-card__thumb {
  transform: scale(1.04);
}
@media (prefers-reduced-motion: reduce) {
  .mp-card__thumb { transition: none; }
  .mp-card:hover .mp-card__thumb { transform: none; }
}

/* Placeholder when no cached video exists for the creator.
   Category-tinted gradient + the channel avatar (or initial) centered. */
.mp-card__thumb--placeholder {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #6366f1 0%, #4338ca 100%);
}

/* Banner backdrop variant (v7): the creator's YouTube channel banner used
 * as the hero background, with the same centered-avatar treatment as the
 * placeholder. The .mp-card__hero::after dark scrim still applies (no
 * suppression rule), keeping the bottom-edge overlays readable on any
 * banner image. Background-position: 50% centers YouTube's standard banner
 * safe-zone (the desktop crop most creators design for). */
.mp-card__thumb--banner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--color-gray-300);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
/* Additional darken pass over banners only — banners can be busy / bright
 * and the centered avatar needs to read against them. Sits beneath the
 * avatar, above the banner image. Independent from the bottom scrim. */
/* Banner image (2026-05-29): now an <img referrerpolicy="no-referrer"> child
   instead of a CSS background, so YouTube's googleusercontent banner CDN
   serves it on the public board (it 403s a cross-origin Referer, which left
   banners blank when logged out). Sits at the base of the hero stack. */
.mp-card__banner-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: 0;
}
.mp-card__thumb--banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.28);
  pointer-events: none;
  z-index: 1;
}
.mp-card__thumb--banner > .mp-card__placeholder-avatar,
.mp-card__thumb--banner > .mp-card__placeholder-initial {
  position: relative;
  z-index: 2;
}
.mp-card--joint_video              .mp-card__thumb--placeholder { background: linear-gradient(135deg, #818cf8, #4338ca); }
.mp-card--guest_appearance         .mp-card__thumb--placeholder { background: linear-gradient(135deg, #fbbf24, #b45309); }
.mp-card--shorts_collab            .mp-card__thumb--placeholder { background: linear-gradient(135deg, #f472b6, #9d174d); }
.mp-card--challenge_video          .mp-card__thumb--placeholder { background: linear-gradient(135deg, #fb7185, #9f1239); }
.mp-card--series_collaboration     .mp-card__thumb--placeholder { background: linear-gradient(135deg, #60a5fa, #1e40af); }
.mp-card--live_stream              .mp-card__thumb--placeholder { background: linear-gradient(135deg, #f87171, #991b1b); }
.mp-card--featured_channel_exchange .mp-card__thumb--placeholder { background: linear-gradient(135deg, #4ade80, #166534); }
.mp-card--other                    .mp-card__thumb--placeholder { background: linear-gradient(135deg, #94a3b8, #475569); }

.mp-card__placeholder-avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.32), 0 0 0 3px rgba(255, 255, 255, 0.25);
}
.mp-card__placeholder-initial {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  background: rgba(255, 255, 255, 0.18);
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 1.875rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18), 0 4px 14px rgba(15, 23, 42, 0.28);
}

/* ── Hero overlays ── */
.mp-card__hero-new {
  position: absolute;
  top: 10px;
  left: 10px;
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 9px;
  border-radius: 999px;
  background: #16a34a;
  color: #fff;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  line-height: 1;
  box-shadow: 0 2px 8px rgba(22, 163, 74, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.18) inset;
  z-index: 2;
}

.mp-card__hero-pill {
  position: absolute;
  bottom: 10px;
  left: 10px;
  display: inline-flex;
  align-items: center;
  height: 26px;
  padding: 0 11px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.72);
  -webkit-backdrop-filter: blur(8px) saturate(180%);
  backdrop-filter: blur(8px) saturate(180%);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08) inset, 0 2px 6px rgba(15, 23, 42, 0.32);
  z-index: 2;
  max-width: calc(100% - 20px);
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Featured: gold-tinted pill with crown */
.mp-card--featured .mp-card__hero-pill {
  background: linear-gradient(135deg, rgba(212, 160, 23, 0.92), rgba(180, 130, 0, 0.92));
  color: #fff;
}
.mp-card__hero-pill .mp-card__pill-crown {
  font-size: 0.75rem;
  margin-right: 5px;
  color: #fde68a;
}
/* When a responses chip is present at bottom-right, constrain the
   category pill so the two never overlap. */
.mp-card__hero-pill--has-sibling {
  max-width: calc(100% - 92px);
}

/* Responses chip — hero bottom-right, mirrors the category pill's chrome.
   Social-proof signal that ONLY renders when response_count > 0, so cards
   without responses look identical to today (no negative empty state). */
.mp-card__hero-responses {
  position: absolute;
  bottom: 10px;
  right: 10px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 10px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.72);
  -webkit-backdrop-filter: blur(8px) saturate(180%);
  backdrop-filter: blur(8px) saturate(180%);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: -0.005em;
  line-height: 1;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08) inset, 0 2px 6px rgba(15, 23, 42, 0.32);
  z-index: 2;
  white-space: nowrap;
}
.mp-card__hero-responses i {
  font-size: 0.6875rem;
  color: #fff;
  opacity: 0.85;
}

/* Bookmark — re-positioned over the hero's top-right corner (Airbnb pattern).
   Override v4's top-left placement. Background/color come from the dark-glass
   base block — DO NOT re-set background here, or the consistency with the
   category pill + response chip dies. */
.mp-card__save {
  position: absolute;
  top: 10px;
  right: 10px;
  left: auto;
  z-index: 3; /* above hero overlays */
  width: 34px;
  height: 34px;
}
.mp-card__save[aria-pressed="true"] {
  background: var(--color-primary);
  color: #fff;
}

/* ── BODY (below hero): title + 1-line preview + byline strip ──
   Flex column so the byline can pin to the bottom on stretched cards
   (regular cards adjacent to a 2-row featured on the desktop magazine
   grid). On a non-stretched card the layout is identical to a static
   block — no visual change. */
.mp-card__body-wrap {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  padding: 14px 16px 14px 16px;
}

.mp-card__title {
  font-family: var(--font-display, 'Plus Jakarta Sans'), sans-serif;
  font-size: 1.25rem;             /* 20px — title is the pitch */
  font-weight: 800;
  line-height: 1.22;
  letter-spacing: -0.025em;
  color: var(--color-gray-900);
  margin: 0 0 6px;
  word-break: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  transition: color 160ms ease;
}
.mp-card:hover .mp-card__title {
  color: var(--color-primary);
}
/* Desktop: bring title back to 18px when the 3-up grid kicks in so the
   line-clamp doesn't break across narrow columns. */
@media (min-width: 768px) {
  .mp-card__title {
    font-size: 1.125rem;
    line-height: 1.28;
    letter-spacing: -0.02em;
  }
}

.mp-card__body {
  font-size: 0.8125rem;
  line-height: 1.45;
  color: var(--color-gray-500);
  margin: 0 0 12px;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Byline strip — small, faint; recedes against the title.
   margin-top: auto pins the byline to the BOTTOM of the body-wrap so that
   on stretched cards (e.g. regulars next to a 2-row featured) extra space
   collects between body preview and byline, not below the byline. */
.mp-card__byline {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: auto;
  font-size: 0.75rem;
  color: var(--color-gray-500);
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
}
/* Avatar wrapper carries the activity dot (LinkedIn iOS pattern). */
.mp-card__byline-avatar-wrap {
  position: relative;
  display: inline-flex;
  flex-shrink: 0;
  line-height: 0;
}
.mp-card__byline-avatar {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--color-gray-100);
  flex-shrink: 0;
}
.mp-card__byline-avatar--initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #6366f1, #4338ca);
  color: #fff;
  font-size: 0.625rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
}
/* Activity dot — presence indicator that overlays the avatar's bottom-right.
   Only renders in the DOM when poster.last_seen_at < 24h, so cards without
   the signal look identical to today. Subtle 4s breathing pulse on the halo
   reads as "this person is alive right now" (LinkedIn iOS pattern). */
.mp-card__byline-active-dot {
  position: absolute;
  bottom: -1px;
  right: -1px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #16a34a;
  border: 1.5px solid #fff;
  box-shadow:
    0 0 0 0.5px rgba(15, 23, 42, 0.12),
    0 0 0 0 rgba(22, 163, 74, 0.55);
  animation: mpActivePulse 3.6s ease-in-out infinite;
}
@keyframes mpActivePulse {
  0%, 100% { box-shadow: 0 0 0 0.5px rgba(15, 23, 42, 0.12), 0 0 0 0 rgba(22, 163, 74, 0.5); }
  50%      { box-shadow: 0 0 0 0.5px rgba(15, 23, 42, 0.12), 0 0 0 3px rgba(22, 163, 74, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .mp-card__byline-active-dot { animation: none; }
}
.mp-card__byline-name {
  color: var(--color-gray-700);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 50%;
}
.mp-card__byline-dot {
  color: var(--color-gray-300);
}
/* Time segment — clock icon + "Posted N units ago" text. inline-flex with
 * gap so the icon hugs the text consistently regardless of HTML whitespace.
 * Icon is decorative; the text carries the meaning. */
.mp-card__byline-time {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.mp-card__byline-time i {
  font-size: 0.6875rem;
  opacity: 0.85;
}

/* Featured card: gold ring around the whole card stays — already defined in v2. */

/* Sparse-state: when only 1-2 listings, give the title a touch more
   prominence without restructuring (taller title clamp). */
.marketplace-browse--sparse .mp-card__title {
  font-size: 1.25rem;
  -webkit-line-clamp: 3;
}
.marketplace-browse--sparse .mp-card__body {
  -webkit-line-clamp: 2;
}
