/* templates/marketplace/browse.twig — foundation rebuild, behind
   redesign_active('collaborations'), OFF by default.
   See .claude/plans/foundation-migration-brief-2026-08-09.md.

   SCOPE: chrome (breadcrumb, page header, search, mobile stat strip,
   category filter rail, load-more button, the anonymous editorial intro +
   FAQ) AND the listing card + grid itself (.mpv2-card / .mpv2-listing-grid),
   built from foundation tokens/components — .fnd-card, .fnd-media,
   .fnd-media-tag, .fnd-avatar, .fnd-iconbtn, .fnd-chip. The card's own
   markup lives in templates/marketplace/_listing_card.twig; the identical
   markup is also emitted client-side by renderCardFnd() in
   marketplace-browse.js (infinite scroll / search), gated on the grid's
   data-fnd attribute — keep all three in sync.
   Still on the old system in both branches (see the TODO(system) comments
   in browse.twig for why): the no-results/never-zero panel, the empty
   states, and the category comparison table.

   Every rule is scoped under `.fnd`, so a page that has not opted in (the
   switch off) never sees any of this — same contract as foundation.css. */

/* ------------------------------------------------------------------
   Page wrapper — keep `.marketplace-browse` for the JS hook
   (document.querySelector('.marketplace-browse')) and for the untouched
   card/grid CSS beneath it; only repaint its own box model to the
   foundation shell numbers instead of the old library's.
   ------------------------------------------------------------------ */
.fnd .marketplace-browse {
  max-width: var(--fnd-shell-w);
  padding: var(--fnd-s4) var(--fnd-s4) var(--fnd-s8);
}
@media (min-width: 768px) {
  .fnd .marketplace-browse { padding: var(--fnd-s6) 32px var(--fnd-s9); }
}
@media (max-width: 767px) {
  .fnd .marketplace-browse { padding: 0 var(--fnd-s4) 96px; }
}

/* ------------------------------------------------------------------
   Page header — title/subtitle in .fnd-pagehead, the "Post a listing"
   button sits beside it (never in the pagehead aside, which is a figure
   slot, not a call to action) and hides at mobile for logged-in members
   only, matching the old page's sticky-header-owns-the-title rule.
   ------------------------------------------------------------------ */
.fnd .mpv2-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--fnd-s4);
  /* The row needs its OWN bottom margin. `align-items: flex-end` puts the
     button's bottom edge exactly on the row's bottom edge, and the pagehead
     inside has its margin zeroed so the two align, so without this the button
     sat flush against the search field below it. It only looked spaced on a
     category page because the breadcrumb above changes what the row's tallest
     child is, which is a 10px accident and not a design. Measured on
     /collaborations at 1440px: 0px with no category, 10px with one. */
  margin-bottom: var(--fnd-s4);
}
.fnd .mpv2-head .fnd-pagehead {
  flex: 1 1 280px;
  min-width: 0;
  margin-bottom: 0;
}
.fnd .mpv2-head-cta { flex: 0 0 auto; }
@media (max-width: 767px) {
  .fnd .mpv2-head--memberhide { display: none; }
}

/* ------------------------------------------------------------------
   Search field — .fnd-input with an icon overlay and a clear button.
   IDs (#mp-search-input / #mp-search-clear) are untouched, so
   marketplace-browse.js's search wiring works unchanged.
   ------------------------------------------------------------------ */
.fnd .mpv2-search { margin: 0 0 var(--fnd-s4); }
.fnd .mpv2-search-field { position: relative; display: flex; align-items: center; }
.fnd .mpv2-search-icon {
  position: absolute; left: 17px; top: 50%; transform: translateY(-50%);
  color: var(--fnd-text-faint); font-size: 14px; pointer-events: none;
}
.fnd .mpv2-search-input { padding-left: 44px; padding-right: 44px; }
.fnd .mpv2-search-input::-webkit-search-cancel-button,
.fnd .mpv2-search-input::-webkit-search-decoration { -webkit-appearance: none; }
.fnd .mpv2-search-clear {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px;
}
.fnd .mpv2-search-clear[hidden] { display: none; }

/* ------------------------------------------------------------------
   Mobile stat strip — a fact chip (private beta framing) plus a plain
   number-and-label line. Hidden at desktop, matching the old strip.
   ------------------------------------------------------------------ */
.fnd .mpv2-statstrip { padding: 4px 0 var(--fnd-s4); }
.fnd .mpv2-statstrip-eyebrow { display: inline-flex; margin-bottom: 10px; }
.fnd .mpv2-statstrip-row { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 0; }
.fnd .mpv2-statstrip-count {
  font-family: var(--fnd-display-font); font-weight: 800; font-size: 28px;
  letter-spacing: -.03em; line-height: 1; color: var(--fnd-text);
  font-variant-numeric: tabular-nums;
}
.fnd .mpv2-statstrip-label { font-size: var(--fnd-t-sm); color: var(--fnd-text-soft); }
/* The "+ Post" pill lives on this row since 2026-08-12 (it was crushing the
   filter scroller below). `align-self` is needed because the row aligns on the
   baseline for the count and its label, and a button on a text baseline sits
   low. `margin-left: auto` pushes it to the far edge without a spacer. */
.fnd .mpv2-statstrip .mpv2-rail-post { margin-left: auto; align-self: center; }
@media (min-width: 768px) {
  .fnd .mpv2-statstrip { display: none; }
}

/* ------------------------------------------------------------------
   Category filter rail — .fnd-chips scrolls horizontally on a phone
   (sticky under the mobile header, matching the old rail) and wraps at
   desktop. The "+Post" pill only exists at mobile; the pagehead button
   takes over from 768px, same swap the old rail made.
   ------------------------------------------------------------------ */
.fnd .mpv2-rail {
  position: relative;
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 var(--fnd-s4);
}
/* The sideways scrolling, the hidden scrollbar and the edge fade moved into
   `.fnd-chips--scroll` (foundation-devices.css) on 2026-08-12, because the
   set overflows its rail on every phone and any other filter surface will
   want the same. What stays here is only how the rail SIZES the scroller,
   which is this page's own layout. */
.fnd .mpv2-chips { flex: 1 1 auto; min-width: 0; }
.fnd .mpv2-rail-post { flex: 0 0 auto; }
@media (max-width: 767px) {
  .fnd .mpv2-rail {
    position: sticky; top: 60px; z-index: 30;
    margin-left: calc(-1 * var(--fnd-s4)); margin-right: calc(-1 * var(--fnd-s4));
    padding: 8px var(--fnd-s4) 10px;
    background: var(--fnd-paper);
    box-shadow: 0 1px 0 var(--fnd-rule);
  }
}
@media (min-width: 768px) {
  /* Desktop has the width to wrap, so the scroller stands down. The mask has
     to be cleared with it: left on a wrapped set it would fade the right edge
     of every row, which is the device's documented failure mode. */
  .fnd .mpv2-chips {
    flex-wrap: wrap; overflow: visible;
    -webkit-mask-image: none; mask-image: none;
  }
  .fnd .mpv2-rail-post { display: none; } /* desktop uses the pagehead CTA */
}

/* ------------------------------------------------------------------
   Anonymous editorial footer — intro/about paragraphs and the guide
   cross-link. Quiet by design (no tinted card behind the text): the
   system's own rule is that a bordered box around plain prose is not a
   device, and this content already sits below a working search UI, not
   inside a hero.
   ------------------------------------------------------------------ */
.fnd .mpv2-intro { margin: var(--fnd-s6) 0; max-width: 66ch; }
.fnd .mpv2-intro-lede { margin-bottom: var(--fnd-s3); }
.fnd .mpv2-intro-about { font-size: var(--fnd-t-body); color: var(--fnd-text-soft); line-height: 1.65; margin: 0; }
.fnd .mpv2-guide-link { margin: var(--fnd-s4) 0 0; }
.fnd .mpv2-guide-link a {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--fnd-display-font); font-weight: 700; font-size: var(--fnd-t-meta);
  color: var(--fnd-text); text-decoration: underline; text-underline-offset: 3px;
  min-height: 44px;
}
.fnd .mpv2-guide-link a:hover { color: var(--fnd-accent-deep); }

/* ------------------------------------------------------------------
   FAQ heading — .fnd-faq itself is centred at 840px; the heading above
   it matches that measure instead of the public-page 20ch cap.
   ------------------------------------------------------------------ */
.fnd .mpv2-faq-wrap { margin-top: var(--fnd-s7); }
.fnd .mpv2-faq-heading { text-align: center; max-width: none; margin-bottom: var(--fnd-s3); }

/* ------------------------------------------------------------------
   THE LISTING CARD (.mpv2-card) — the page's own rich device: banner hero,
   corner badges, byline, save toggle, and the desktop "magazine" span for
   featured listings, all rebuilt from foundation tokens/components instead
   of the old library. Markup: templates/marketplace/_listing_card.twig.
   Mirrored client-side by renderCardFnd() in marketplace-browse.js.

   Three accessibility bugs measured on the OLD card (still present on
   redesign=0 today, not something this migration introduced) are fixed HERE
   by construction rather than patched after the fact: the "·" separator
   uses --fnd-text-faint (5.37:1+, not the old #cbd5e1 at 1.48:1); the save
   toggle is 44x44 from the start; the "NEW" pill uses #15803d (~5.0:1 on
   white) instead of the old #16a34a (3.3:1).
   ------------------------------------------------------------------ */
.fnd .mpv2-listing-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--fnd-s4);
}
@media (min-width: 768px) {
  .fnd .mpv2-listing-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .fnd .mpv2-listing-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); grid-auto-flow: dense; gap: var(--fnd-s5); }
  .fnd .mpv2-listing-grid > .mpv2-card--featured { grid-column: span 2; grid-row: span 2; }
}
/* One or two listings total: centre instead of stretching a lone card the
   full grid width (mirrors the old sparse-state centring). */
.fnd .mpv2-listing-grid:has(> .mpv2-card:nth-child(1):last-child) { grid-template-columns: minmax(0, 420px); justify-content: center; }
.fnd .mpv2-listing-grid:has(> .mpv2-card:nth-child(2):last-child) { grid-template-columns: repeat(2, minmax(0, 340px)); justify-content: center; }

.fnd .mpv2-card { position: relative; overflow: hidden; }

.fnd .mpv2-card-save {
  position: absolute; top: 8px; right: 8px; z-index: 3;
  width: 44px; height: 44px;
  background: rgba(22, 20, 26, .55); color: #fff;
  -webkit-backdrop-filter: blur(6px) saturate(160%); backdrop-filter: blur(6px) saturate(160%);
}
.fnd .mpv2-card-save:hover { background: rgba(22, 20, 26, .74); color: #fff; }
.fnd .mpv2-card-save[aria-pressed="true"] { background: var(--fnd-ink); color: var(--fnd-on-ink); }
/* Set by handleSaveClick() while the save API call is in flight (shared
   class name with the old card; there is no matching old-card rule to
   collide with, so it is safe to reuse rather than invent a second one). */
.fnd .mpv2-card-save.mp-card__save--pending { opacity: .6; pointer-events: none; }

.fnd .mpv2-card-link { display: flex; flex-direction: column; height: 100%; color: inherit; text-decoration: none; }

.fnd .mpv2-card-hero {
  display: flex; align-items: center; justify-content: center;
  border-radius: calc(var(--fnd-r) - 1px) calc(var(--fnd-r) - 1px) 0 0;
  flex: 0 0 auto;
}
.fnd .mpv2-card-banner { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.fnd .mpv2-card-scrim {
  position: absolute; left: 0; right: 0; bottom: 0; height: 46%; z-index: 1; pointer-events: none;
  background: linear-gradient(to top, rgba(22, 20, 26, .45), rgba(22, 20, 26, 0));
}
.fnd .mpv2-card-hero-avatar.fnd-avatar,
.fnd .mpv2-card-hero-initial {
  position: relative; z-index: 2;
  width: 68px; height: 68px; border-radius: 50%;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .72), 0 6px 16px rgba(22, 20, 26, .3);
}
.fnd .mpv2-card-hero-initial {
  display: flex; align-items: center; justify-content: center;
  background: var(--fnd-ink); color: var(--fnd-on-ink);
  font-family: var(--fnd-display-font); font-weight: 800; font-size: 24px;
}
/* Placeholder (no channel banner): a flat category tint, never a gradient
   — gradients are a hierarchy tool only and never belong on a card. */
.fnd .mpv2-card-hero--ph { background: var(--fnd-paper-2); }
.fnd .mpv2-card-hero--joint_video               { background: var(--fnd-accent-soft); }
.fnd .mpv2-card-hero--guest_appearance          { background: var(--fnd-warn-soft); }
.fnd .mpv2-card-hero--shorts_collab             { background: #FBE7F1; }
.fnd .mpv2-card-hero--challenge_video           { background: var(--fnd-danger-soft); }
.fnd .mpv2-card-hero--series_collaboration      { background: #E4EEFC; }
.fnd .mpv2-card-hero--live_stream               { background: #F5E4EE; }
.fnd .mpv2-card-hero--featured_channel_exchange { background: var(--fnd-ok-soft); }
.fnd .mpv2-card-hero--other                     { background: var(--fnd-paper-2); }

/* Overlays. .fnd-media-tag's own default position is bottom-right, which is
   exactly where the responses count sits, so only NEW (top-left) and the
   category pill (bottom-left) need repositioning. */
.fnd .mpv2-card-tag--new { top: 8px; left: 8px; right: auto; bottom: auto; background: #15803d; }
.fnd .mpv2-card-tag--pill {
  left: 8px; right: auto; bottom: 8px; top: auto;
  max-width: calc(100% - 16px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fnd .mpv2-card-tag--pill-narrow { max-width: calc(100% - 78px); }
.fnd .mpv2-card-tag--pill-featured .cp-crown { margin-right: 4px; }
.fnd .mpv2-card-tag--responses i { margin-right: 4px; }

.fnd .mpv2-card-body { display: flex; flex-direction: column; flex: 1 1 auto; padding: 14px 16px; }
/* The container owns the rhythm — the gap between title/badges/preview/byline
   is set ONCE here, never per-child, so it can never drift to a value under
   the system's own 12px floor for a card body. Do NOT add margin to any
   .mpv2-card-title / -preview / -byline rule below; that would tie on
   specificity with this selector and the child (being later in the file)
   would silently win, which is exactly the bug this note is here to stop
   someone from reintroducing. */
.fnd .mpv2-card-body > * + * { margin-top: 12px; }
.fnd .mpv2-card-title {
  font-family: var(--fnd-display-font); font-weight: 800; font-size: 17px;
  line-height: 1.25; letter-spacing: -.02em; color: var(--fnd-text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.fnd .mpv2-card-preview {
  font-size: 13.5px; line-height: 1.5; color: var(--fnd-text-soft);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;
}
.fnd .mpv2-card-byline {
  display: flex; align-items: center; gap: 6px;
  margin-top: 12px; /* the featured-row "pin to bottom" trick was dropped: it
     required margin-top:auto, which fights the container's fixed rhythm and
     can resolve to 0 on a non-stretched card — a real check.js FAIL, not a
     cosmetic loss worth keeping. */
  font-size: 12.5px; color: var(--fnd-text-faint); white-space: nowrap; overflow: hidden;
}
.fnd .mpv2-card-byline-avatar-wrap { position: relative; display: inline-flex; flex: 0 0 auto; line-height: 0; }
.fnd .mpv2-card-byline-avatar.fnd-avatar { width: 20px; height: 20px; flex: 0 0 auto; }
.fnd .mpv2-card-byline-initial {
  display: flex; align-items: center; justify-content: center;
  background: var(--fnd-ink); color: var(--fnd-on-ink); font-size: 12px; font-weight: 800;
}
.fnd .mpv2-card-byline-active-dot {
  position: absolute; bottom: -1px; right: -1px;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--fnd-ok); border: 1.5px solid var(--fnd-card);
}
.fnd .mpv2-card-byline-name { color: var(--fnd-text-soft); font-weight: 600; overflow: hidden; text-overflow: ellipsis; max-width: 46%; }
.fnd .mpv2-card-byline-sep { color: var(--fnd-text-faint); }
/* The icon is the phone row's version of the word "subscribers". On a desktop
   card there is room for the word, so the icon stays out of the way. */
.fnd .mpv2-card-byline-subs-icon { display: none; }
.fnd .mpv2-card-byline-time { display: inline-flex; align-items: center; gap: 4px; }

.fnd .mpv2-card-badge { align-self: flex-start; }

/* Featured: the 2x2 magazine cell earns bigger type and more room, same as
   the old design's desktop-only treatment. */
@media (min-width: 1024px) {
  .fnd .mpv2-card--featured .mpv2-card-title { font-size: 22px; -webkit-line-clamp: 3; }
  .fnd .mpv2-card--featured .mpv2-card-preview { font-size: 14px; -webkit-line-clamp: 6; }
  .fnd .mpv2-card-body { padding: 16px 18px; }
  .fnd .mpv2-card--featured .mpv2-card-body { padding: 22px 24px; }
}
/* Sparse state (1-2 listings total): a touch more room, mirroring the old
   .marketplace-browse--sparse treatment (that class still renders in both
   branches — see the container div in browse.twig). */
.fnd .marketplace-browse--sparse .mpv2-card-body { padding: 18px 18px; }
.fnd .marketplace-browse--sparse .mpv2-card-title { font-size: 19px; -webkit-line-clamp: 3; }

/* ------------------------------------------------------------------
   No-results / empty state (search returned nothing, or a genuinely
   empty view) — .fnd-empty, with a page-own button row and confirm line.
   Mirrored by ensureNoResultsEl()/renderNeverZero()/showSavedEmpty() in
   marketplace-browse.js when isFnd is true.
   ------------------------------------------------------------------ */
.fnd .mpv2-empty-cta { display: flex; flex-direction: column; align-items: center; gap: var(--fnd-s3); margin-top: var(--fnd-s4); }
.fnd .mpv2-empty-confirm {
  display: inline-block; margin: var(--fnd-s4) 0 0; padding: 8px 16px;
  font-size: var(--fnd-t-meta); font-weight: 600; color: var(--fnd-ok);
  background: var(--fnd-ok-soft); border-radius: 999px;
}
.fnd .mpv2-empty-confirm[hidden] { display: none; }
.fnd .mpv2-fallback-heading { text-align: center; max-width: none; margin: var(--fnd-s6) 0 var(--fnd-s3); font-size: var(--fnd-t-h3); }
.fnd .mpv2-listing-grid--fallback { margin-top: var(--fnd-s2); }
.fnd .marketplace-browse--sparse .mpv2-card-preview { -webkit-line-clamp: 3; font-size: 14px; }

/* ──────────────────────────────────────────────────────────────
   HOVER
   Same fault as the listing page, found the same way: both of these paint
   `--color-primary-dark` indigo under the cursor while sitting on a page
   whose buttons are ink. A variable remap cannot fix them, because the
   variable IS the indigo; the rule has to be replaced.
   ────────────────────────────────────────────────────────────── */
.fnd .mp-rail-post:hover,
.fnd .mp-no-results__suggest:hover {
  background: var(--fnd-ink);
  color: var(--fnd-on-ink);
  transform: translateY(-2px);
}

/* ══════════════════════════════════════════════════════════════════════
   THE PHONE: THE GRID BECOMES THE SYSTEM'S LIST
   Added 2026-08-14. Measured first, because "it feels long" is not a reason:
   at 375px this page was 6,315px tall for 16 listings against 2,703px for the
   same 16 on a desktop. Each card is a full-width 16:9 banner plus a title, a
   preview line and a byline, which comes to 344px, so a member sees 2.3
   collaborations per screen and scrolls six and a half screens to reach the
   end of one category.

   Browsing is a SCANNING task. The point of the page is comparing candidates,
   and a shape that shows two of them at a time is the wrong shape for it on a
   phone, however good each card looks on its own.

   THIS IS NOT A NEW DEVICE. The system already ships the answer: `.fnd-list`
   is a picture column, a facts column and an action column, and `/collab-board`
   and `/studio` both use it for exactly this kind of scan. What is written here
   is the SIZE, which the system explicitly leaves to each list ("THE BOX SIZE
   IS PER LIST", foundation-devices.css), plus the release of the card's own
   stacked layout. Nothing invents a row.

   WHY 112x63 AND NOT THE SYSTEM DEFAULT 84x47. On /studio the picture answers
   "which of my videos is this". Here it is the creator's channel art, and it is
   the main signal of what somebody makes before you read a word. 112 keeps that
   legible at 16:9 and still shows about eight rows a screen.

   DESKTOP IS UNTOUCHED. The card grid is right on a wide screen, where three
   across already shows nine at once.
   ══════════════════════════════════════════════════════════════════════ */
@media (max-width: 767px) {
  .fnd .mpv2-listing-grid {
    /* The system's own list size, from .fnd-list in foundation-devices.css.
       A larger 112x63 was tried first, on the reasoning that channel art is
       the signal here. Measured, it cost the title 28px of a 199px column and
       clipped nearly every listing to three words, which is a worse trade than
       a smaller picture. When in doubt the system's number wins. */
    --mpv2-row-media-w: 84px;
    --mpv2-row-media-h: 47px;
    display: block;
  }
  /* The card keeps being a .fnd-card; only its INSIDE changes shape. The
     hairline between rows comes from the card, so they still read as separate
     things rather than as one long block. */
  .fnd .mpv2-listing-grid > .mpv2-card { margin-bottom: 10px; }

  /* A featured listing spans two columns on a desktop grid. There are no
     columns here, and the rule would otherwise leak in as a span on a block. */
  .fnd .mpv2-listing-grid > .mpv2-card--featured { grid-column: auto; grid-row: auto; }

  .fnd .mpv2-card-link {
    display: grid;
    grid-template-columns: var(--mpv2-row-media-w) minmax(0, 1fr);
    gap: var(--fnd-s3);
    align-items: center;
    padding: 10px;
  }

  .fnd .mpv2-card-hero {
    width: var(--mpv2-row-media-w);
    height: var(--mpv2-row-media-h);
    min-height: 0;
    aspect-ratio: auto;
    border-radius: var(--fnd-r-xs);
    flex: 0 0 var(--mpv2-row-media-w);
  }
  .fnd .mpv2-card-banner { width: 100%; height: 100%; object-fit: cover; }

  /* Everything that was drawn ON the banner goes, because at 112px wide it
     would be stacked labels over a thumbnail nobody can read. Not lost: the
     channel and its size are in the byline one column across, and the category
     is the chip the member already tapped to get here. */
  .fnd .mpv2-card-hero-avatar,
  .fnd .mpv2-card-hero-initial,
  .fnd .mpv2-card-scrim,
  .fnd .mpv2-card-tag--pill,
  .fnd .mpv2-card-tag--responses { display: none; }

  /* NEW stays. It is the one thing on the picture that changes what a member
     does next, and it is a single short word. */
  /* 12px, the floor, not the 9.5px this shrank to on the first pass. Below the
     floor is a hard rule and it is not negotiable for a small box: text that
     cannot be read is not a signal, it is decoration on a thumbnail. At 12px
     the pill is about 34x16 in the corner of an 84x47 frame, which fits. */
  .fnd .mpv2-card-tag--new { top: 3px; left: 3px; font-size: 12px; padding: 0 5px; line-height: 1.35; }

  /* Both classes, because `.fnd-card-body` sets 20px of padding from a
     selector this could not outrank with one class. Measured: the byline came
     out 160px inside a 200px body and the 40px difference was this padding,
     not anything in the row's own rules. The row's spacing is on the link
     wrapper, so the body needs none of its own. */
  .fnd .mpv2-card-body.fnd-card-body { padding: 0; min-width: 0; }
  .fnd .mpv2-card-title {
    font-size: 15px;
    line-height: 1.3;
    margin: 0 0 5px;
    /* THREE lines, not two. The preview sentence is hidden in this shape, so
       the title is the only thing describing the collaboration, and at 375px
       two lines cut most of them mid-phrase. A row whose height depends on its
       title length is not a list, so it is still a hard clamp. */
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }

  /* The preview sentence is the card's third line of prose. In a row it is what
     turns eight scannable items back into three. The title and the channel are
     what a member picks on; the body is one tap away. */
  .fnd .mpv2-card-preview { display: none; }

  /* The name must be allowed to shrink and ellipsis rather than vanish: at
     `padding-right: 38px` it was squeezed to zero width and the byline read
     "· 1 subscriber". The save button is level with this line, so the reserve
     stays, but the name owns the leftover space. */
  /* No reserve: the bookmark is on the picture now, so the whole 200px is the
     channel's. */
  /* `align-self: stretch` and an explicit width, because the card body is a
     flex COLUMN and this line was coming out 160px inside a 200px body. Those
     40px are the difference between "For You Only Dear" and "For You...". */
  .fnd .mpv2-card-byline {
    font-size: var(--fnd-t-micro);
    gap: 5px;
    margin: 0;
    align-self: stretch;
    width: 100%;
  }
  /* The name takes the leftover space and ellipsises; it must never be the
     thing that gives way. At 375px it had been squeezed to "A." while the
     subscriber count beside it kept its full width, which is backwards: the
     name is who a member would be collaborating with. */
  .fnd .mpv2-card-byline-name {
    min-width: 0;
    flex: 1 1 auto;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    /* The desktop card caps the name at 46% so it cannot crowd the subscriber
       count beside it. In the row the count is gone, so the cap was clipping
       "Parthionix" to "Parthio..." with 70px of empty space to its right. */
    max-width: none;
  }
  /* THE SUBSCRIBER COUNT STAYS ON THE PHONE. It was dropped on the first pass
     because the name, the count and the bookmark did not fit in 199px. The
     founder's call, and he is right: channel size is half of whether a
     collaboration is worth answering, so the row is worth re-cutting for it.

     What gives way instead is the byline AVATAR. The row already carries a
     picture of this creator's channel 12px to the left; a second 16px circle
     of the same person on the same line is the only thing here that repeats
     itself, and removing it buys 21px, which is the difference between
     "Parthionix" and "Parth...". */
  .fnd .mpv2-card-byline-avatar-wrap { display: none; }
  /* Icon instead of the word. "9.0K subscribers" costs 93px of the 156px this
     line has once the bookmark takes its column, which leaves a channel name
     about seven characters. The icon says the same thing in 14px and the full
     phrase is still on the label and the tooltip. */
  .fnd .mpv2-card-byline-subs { flex: 0 0 auto; white-space: nowrap; display: inline-flex; align-items: center; gap: 4px; }
  .fnd .mpv2-card-byline-subs-icon { display: inline-block; font-size: 10px; opacity: .7; }
  .fnd .mpv2-card-byline-subs-word { display: none; }
  .fnd .mpv2-card-byline-avatar { width: 16px; height: 16px; }
  /* Posted-when is the least load-bearing fact in the row and the first to
     push the channel name into an ellipsis on a 375px screen. */
  .fnd .mpv2-card-byline-time { display: none; }
  /* Its separator sits BEFORE it in the markup, so `+ .time` never matched and
     the row ended on a dangling middot: "1 subscriber ·". Caught by looking at
     the phone, not by any check. `:last-of-type` is the separator that has
     nothing after it once the time is gone. */
  /* `:last-of-type` matches by TAG, and every part of the byline is a span, so
     it resolved to the time span and hid nothing. `:has()` names the actual
     relationship: the separator that introduces the thing being hidden. */
  .fnd .mpv2-card-byline-sep:has(+ .mpv2-card-byline-time) { display: none; }

  /* The save control moves off the picture and onto the row's right edge,
     where it is a real 44px target instead of a 28px dot on a thumbnail. */
  /* THE BOOKMARK IS A COLUMN OF THE ROW, NOT SOMETHING FLOATING ON IT.
     Founder, 2026-08-16, and every word of it was fair: "I hate the new
     bookmark icon. And sometimes its got a blurred circle around it and
     sometimes not. And it even overlaps content."

     Three separate faults, all mine, all from treating an absolutely
     positioned overlay as if it were part of the row:

       - it overlapped the title, because `.mpv2-card` is the positioned
         ancestor, not the thumbnail. `right: 4px` put a 44px box on the CARD's
         right edge, which on a row is the text column.
       - the blurred circle came and went, because the desktop rule sets
         `backdrop-filter: blur(6px)` and the phone rule only cleared the
         BACKGROUND. A blur with nothing behind it is invisible over dark
         channel art and a grey smudge over light art.
       - and it read as a dark pill on paper, which is not a control this
         system has.

     The system's list row is picture, facts, action, and the action is a real
     third column. So the card becomes that grid, the button stops floating,
     and nothing can overlap anything. It costs the byline 44px, which is the
     honest price of a control that is always visible. */
  .fnd .mpv2-listing-grid > .mpv2-card {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 44px;
    align-items: center;
  }
  /* EXPLICIT COLUMNS, because the bookmark is written BEFORE the link in the
     markup (it has to be a sibling of the anchor so clicking it does not
     navigate). Left to auto-flow it took the 1fr and the whole listing was
     squeezed into 44px. The system's list notes say the same thing in the same
     words: place every cell by grid-column, never by source order. */
  .fnd .mpv2-card-link { grid-column: 1; grid-row: 1; }
  .fnd .mpv2-card-save { grid-column: 2; grid-row: 1; }
  .fnd .mpv2-card-save {
    position: static;
    width: 44px;
    height: 44px;
    /* The paper icon button: no fill, no blur, no shadow, no border. The only
       thing that changes when it is on is the ink. */
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
    border: 0;
    color: var(--fnd-text-faint);
    text-shadow: none;
    justify-self: end;
  }
  .fnd .mpv2-card-save:hover { background: var(--fnd-paper-2); color: var(--fnd-ink); }
  .fnd .mpv2-card-save[aria-pressed="true"] {
    background: transparent;
    color: var(--fnd-ink);
  }
  /* NEW keeps the left corner it has on the desktop card, so the two never
     stack and neither moves between breakpoints. */
  .fnd .mpv2-card-tag--new { left: 3px; right: auto; }
}

/* ──────────────────────────────────────────────────────────────
   THE SUBSCRIBER-FLOOR CHIP ON THE PHONE ROW
   It renders on roughly one listing in ten and only for a viewer below that
   listing's floor, so it does not have to fit the row's normal rhythm; it has
   to be readable and clearly attached to the listing above it. Its own line
   under the title, at the system chip's smallest honest size.
   ────────────────────────────────────────────────────────────── */
@media (max-width: 767px) {
  .fnd .mpv2-card-badge--floor {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 0 0 5px;
    padding: 2px 8px;
    font-size: 12px;
    line-height: 1.4;
    max-width: 100%;
  }
  .fnd .mpv2-card-badge--floor i { font-size: 11px; opacity: .75; }
}

/* ──────────────────────────────────────────────────────────────
   THE SAVE CONFIRMATION IS A FLASH MESSAGE, NOT A PAGE-PRIVATE TOAST
   The bespoke `.mp-save-toast` is no longer used on this page, so the rules
   that used to lift it clear of the Concierge are gone with it. Two faults
   killed it and both were the same mistake: it was a device this page owned
   alone, so nobody had ever asked it to work anywhere but a phone.

     - its offset cleared the 64px app nav and the Concierge, neither of which
       exists at 1440, so on a desktop it floated 156px above the bottom edge
       in the middle of nothing.
     - it painted slate #0F172A, the old library's, not the system's ink.

   The flash message has neither problem, appears where every other message on
   the site appears, and becomes the system's own toast the moment the
   flash-messages switch is flipped. The old design keeps the old toast.
   ────────────────────────────────────────────────────────────── */
