/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   MARKETPLACE LISTING CARD — THE SHARED ANATOMY
   Brief "Marketplace listing card v2", 1 Oct 2026. Mockup Plan/pt-marketplace-card-v2.html.
   Component: includes/marketplace/listing-card.php.

   WHY THIS SHEET EXISTS. These rules used to live in marketplace-discover.css behind
   `.pt-market-archive-wrapper`, so they reached exactly one page. The public profile strip and
   saved listings each drew their own card instead and drifted — different location, no Verified,
   different spacing. Unprefixed and loaded on all three, the card is the same card everywhere.

   ⚠️ SPECIFICITY. Every rule here is (0,1,0) or (0,2,0). The marketplace page still carries its own
   page-scoped rules at (0,2,0) for what belongs only to it — the save heart, the photo count, the
   sold strip, owner chips, dimming, the wide row card. Those do not re-declare anything below.
   If you add a rule here that the marketplace sheet also declares, the marketplace sheet wins —
   delete it there, do not fight it with a longer selector.

   NO TOKENS ARE DECLARED HERE. Colours come from the site's :root.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

.pt-listing-card {
    display:         flex;
    flex-direction:  column;
    border:          1px solid var(--pt-border);
    border-radius:   0;
    background:      var(--pt-surface);
    overflow:        hidden;
    text-decoration: none;
    color:           var(--pt-ink);
    transition:      border-color 120ms ease, box-shadow 120ms ease;
}
.pt-listing-card:hover {
    border-color: var(--pt-border-strong);
    box-shadow:   0 2px 10px rgba(0, 0, 0, 0.06);
    text-decoration: none;
    color:        var(--pt-ink);
}
.pt-listing-card:focus-visible { outline: 2px solid var(--pt-accent); outline-offset: 2px; }

/* ── THE PHOTO ──────────────────────────────────────────────────────────────────────────────────
   Edge to edge, fixed 4:3. NOTHING IS OVERLAID BY DEFAULT (brief §2): the Verified badge that used
   to sit top-left is gone from every page. The save heart and the photo count are the host page's,
   passed in as an overlay, so a page that cannot wire them up does not inherit them. */
.pt-listing-card__media {
    position:     relative;
    aspect-ratio: 4 / 3;
    background:   var(--pt-fill-control);    /* the no-photo ground */
    overflow:     hidden;
}
.pt-listing-card__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* FIT, DON'T BUTCHER (Leon 19 Sep 2026): a photo far from 4:3 is shown whole rather than cropped. */
.pt-listing-card__media.is-fit     { background: var(--pt-surface); }
.pt-listing-card__media.is-fit img { object-fit: contain; }
.pt-listing-card__noimg {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--pt-ink-3);
}
.pt-listing-card__noimg svg { width: 26px; height: 26px; }

/* ── THE BODY (brief §3) ────────────────────────────────────────────────────────────────────────
   Padding 14px 16px desktop, 10px below 600 — the brief's numbers. */
.pt-listing-card__body {
    display: flex; flex-direction: column; flex: 1;
    padding: 14px 16px;
}

/* Price: UNCHANGED, and out of scope for v2 — 18px mono, the size the card has been since the 14 Sep
   mobile brief stepped it up from 15px. (It was declared twice, 800 lines apart, in the old sheet.)
   The row is a flex pair: the amount, and the card's ONE status pushed to the right. The amount is
   wrapped in its own span so space-between separates price from status and never a sale's <del> from
   its <ins>. `align-items: baseline` sits a 12.5px status word on the 18px figure's baseline. */
.pt-listing-card__price {
    margin: 0;
    white-space: nowrap;          /* "£1,500.00" never breaks across two lines */
}
/* THE ONE STATUS — a caption on the photo, bottom-left, beside the photo count.
   It briefly had a reserved 15px line in the body; see the component for why that went (only 4 cards in
   30 carry a status, and a per-ROW collapse is impossible because CSS decides the rows, not PHP).
   Same furniture as `__cnt` and `__soldstrip`: dark translucent, light ink, square. NO DOT — the chip is
   already the container, so the tone colours the chip instead of a pip inside it. */
.pt-listing-card__statechip {
    position: absolute; left: 8px; bottom: 8px; z-index: 2;
    max-width: calc(100% - 60px);          /* never reaches the photo count on its right */
    padding: 2px 6px;
    font-size: 10.5px; font-weight: 600; line-height: 1.4;
    background: rgba(26, 26, 26, .75); color: var(--pt-surface-dim);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* AMBER only where the pending offer really is the viewer's own move — the §C rule, kept. Everyone
   else's deals stay neutral, which is what stops a whole grid lighting up. */
.pt-listing-card__statechip.is-amber { background: var(--pt-amber-dot); color: var(--pt-ink); }
.pt-listing-card__amount {
    display: inline-block;
    font-family: var(--pt-mono);
    font-size: 18px;
    font-weight: 600;
    color: var(--pt-ink);
    font-variant-numeric: tabular-nums;
}
/* WooCommerce wraps the amount in its own spans and sometimes a sale <del>; keep them in the mono run. */
.pt-listing-card__amount *   { font: inherit; color: inherit; }
.pt-listing-card__amount del { color: var(--pt-ink-3); font-weight: 400; margin-right: 4px; }

/* Title: UNCHANGED font and size. Clamped to two lines, with a min-height of exactly two lines so a
   one-line title does not pull the meta row up and break the grid's alignment (brief §4). `em`, not
   px, so it keeps tracking the font size at every breakpoint without a second number to maintain. */
.pt-listing-card__title {
    margin: 3px 0 0;
    font-size: 14.5px;
    font-weight: 500;
    line-height: 1.35;
    color: var(--pt-ink);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    min-height: 2.7em;            /* 2 × 1.35 line-height = 39px at 14.5px — the brief's §4, in em so it
                                     tracks the font size instead of being a second number to maintain */
}

/* ── THE META ROW (brief §3.4) ──────────────────────────────────────────────────────────────────
   Town on the left, Verified on the right, a hairline above, 12px clear of the title.
   🔴 NO `margin-top: auto`. That spacer is what left 30px+ of nothing under a one-line title and it
   is what the brief removes; the title's min-height does the aligning instead. */
.pt-listing-card__meta {
    display: flex; align-items: center; gap: 6px;
    margin: 5px 0 0;
    font-size: 13px;
    color: var(--pt-ink-2);
    min-width: 0;
}
.pt-listing-card__where {
    justify-content: space-between;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--pt-border);
    /* ALWAYS RENDERED, EVEN EMPTY — 20px of reserved space is what makes a grid a grid, and it costs
       nothing when there is nothing to say (the 14 Sep rule, kept). */
    min-height: 20px;
}
/* The town gives way first; the status beside it never truncates. */
.pt-listing-card__loc { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.pt-listing-card__where .pt-listing-card__state { flex: 0 0 auto; }

/* VERIFIED — the only green on a card, and the whole of what is left of the old photo badge.
   An unverified seller gets nothing here: no label, no grey shield, no placeholder. */
.pt-listing-card__vf {
    display: inline-flex; align-items: center; gap: 4px;
    flex: 0 0 auto;
    white-space: nowrap;
    color: var(--pt-green-text);
    font-weight: 500;
}
.pt-listing-card__vf svg { width: 14px; height: 14px; flex: 0 0 auto; }

/* ── COMPACT (the profile strip and saved listings) ─────────────────────────────────────────────
   Size only — same anatomy, smaller type, as the brief's $context allows. */
.pt-listing-card--compact .pt-listing-card__body  { padding: 12px 14px; }
.pt-listing-card--compact .pt-listing-card__amount { font-size: 16px; }
.pt-listing-card--compact .pt-listing-card__title { font-size: 13.5px; }
.pt-listing-card--compact .pt-listing-card__meta  { font-size: 12px; }

/* Saved listings: Remove sits on the photo, because the card is one <a> and a <button> inside an
   anchor is invalid. Square, white, dims on hover — never recolours, never red. */
.pt-listing-card__unsave {
    position: absolute; top: 8px; right: 8px; z-index: 3;
    width: 28px; height: 28px;
    display: grid; place-items: center;
    background: var(--pt-surface); color: var(--pt-ink);
    border: 1px solid var(--pt-border);
    cursor: pointer;
}
.pt-listing-card__unsave:hover,
.pt-listing-card__unsave:focus { background: var(--pt-fill-control); color: var(--pt-ink); }
.pt-listing-card__unsave:focus-visible { outline: 2px solid var(--pt-accent); outline-offset: 2px; }

/* ── PHONES (brief: 12px meta, 10px padding below 600) ──────────────────────────────────────────*/
@media (max-width: 600px) {
    .pt-listing-card__body  { padding: 10px; }
    .pt-listing-card__amount { font-size: 16px; }
    .pt-listing-card__meta  { font-size: 12px; }
    .pt-listing-card__where { margin-top: 10px; padding-top: 8px; }
    .pt-listing-card__vf svg { width: 13px; height: 13px; }
}

/* ═══ RESERVED / SOLD — the band on the photo (reserved-and-sold brief, Parts 2–3, 2 Oct 2026) ════
   Option A from Plan/pt-reserved-card-options.html, values carried across exactly. B (whole card
   framed) read as "featured" rather than "taken"; C (dimmed with a stamp) told buyers to skip it.

   AMBER MEANS ACTIVE AND WAITING — it is never used for sold.

   ⚠️ The two hexes are the brief's, set as LOCAL custom properties on the card rather than redeclared
   on :root (CLAUDE.md rule 5). They are not PT's amber tokens on purpose: white on --pt-amber-deep
   (#C77E14) is ~3.2:1 and fails contrast at 13px; #A86A00 is ~4.8:1 and passes. */
.pt-listing-card {
    --pt-lc-reserved: #A86A00;
    --pt-lc-sold:     #5C5A54;
}
.pt-listing-card__band {
    position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
    display: flex; align-items: center; gap: 6px;
    padding: 8px 12px;
    font-size: 13px; font-weight: 600; letter-spacing: .02em; line-height: 1.2;
    color: #fff;
    border-radius: 0;
}
.pt-listing-card__band svg { width: 14px; height: 14px; flex: 0 0 auto; stroke: #fff; }
.pt-listing-card__band.is-reserved { background: var(--pt-lc-reserved); }
.pt-listing-card__band.is-sold     { background: var(--pt-lc-sold); }

/* The photo count moves up to sit above the band, not under it (brief Part 2). 44px = the band's
   height (8 + ~16 + 8) plus the count's own 8px clearance — the mockup's figure. */
.pt-listing-card.is-state-reserved .pt-listing-card__cnt,
.pt-listing-card.is-state-sold     .pt-listing-card__cnt { bottom: 44px; }

/* `PT_RESERVED_STYLE = corner` — the fallback if a grid of bands ever looks too amber. A small label
   top-left instead of the full band; the photo count stays where it always was. Built now so switching
   is one constant, not a job. */
.pt-listing-card__band.is-corner {
    left: 8px; right: auto; bottom: auto; top: 8px;
    padding: 4px 8px;
    font-size: 11px;
}
.pt-listing-card__band.is-corner svg { width: 12px; height: 12px; }
.pt-listing-card.is-state-reserved:has(.pt-listing-card__band.is-corner) .pt-listing-card__cnt,
.pt-listing-card.is-state-sold:has(.pt-listing-card__band.is-corner)     .pt-listing-card__cnt { bottom: 8px; }

/* Meta row, right-hand slot — the state replaces Verified (brief Parts 2–3). */
.pt-listing-card__wherestate {
    flex: 0 0 auto;
    white-space: nowrap;
    font-weight: 600;
}
.pt-listing-card__wherestate.is-reserved { color: var(--pt-lc-reserved); }
.pt-listing-card__wherestate.is-sold     { color: var(--pt-lc-sold); }

/* Price, title and everything else on a Reserved card are UNCHANGED — no border, no tint, no dimming
   (brief Part 2). The page sheet's older `.is-sold` rules dim the photo and strike the price; those are
   for the owner's Selling view and stay there. */

/* Car tag (9 Oct 2026): "Fits this car" on an exact fit in a car-filtered grid; the empty twin keeps every card in that grid level */
.pt-fit-chip { display: inline-flex; align-self: flex-start; align-items: center; height: 20px; margin: 4px 0 2px; padding: 0 7px; background: #EEF5F0; color: #2E7D4F; font-size: 11.5px; font-weight: 600; line-height: 20px; white-space: nowrap; }
.pt-fit-chip--none { visibility: hidden; padding: 0; }

/* MOT line under the meta row — Cars grids only (includes/marketplace/listing-mot.php, 9 Oct 2026). One fixed height; the
   empty twin keeps a car without a DVSA record level with its neighbours. */
.pt-mot-line { display: flex; align-items: center; gap: 5px; height: 16px; margin-top: 6px; font-size: 12px; line-height: 16px; color: #2E7D4F; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pt-mot-line .pt-mot-ic { width: 12px; height: 12px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.pt-mot-line.is-amber { color: #A86A00; }
.pt-mot-line--none { visibility: hidden; }
