/**
 * PUBLIC CATALOG — THE OPERATOR-ONLY LISTING CARDS on the item detail page.
 * They render below the read-only listing-state strip and the client self-gates
 * the mount, so an anonymous visitor never sees any of these classes: the
 * editable sale-price / cost-override card, the channels card, the
 * external-sources card, the activity feed with its note composer, the reach-out
 * tracker, and the inline title / description edit affordance.
 *
 * NINTH of ten sheets — after styles-narrow.css, before styles-mobile.css. Read
 * the load-order block at the top of styles.css before moving a rule between
 * sheets: the split is a contiguous slice of one original file and the cascade
 * depends on it.
 *
 * These cards deliberately reuse the token vocabulary (var(--bg-card),
 * --border, --accent) instead of inventing their own colours, so a theme tweak
 * in styles.css picks them up for free.
 */

/* ── Editable sale-price + cost-override card (Chunk 1) ──
   Catalog detail page, logged-in users only. Sits directly below the
   read-only listing-state strip. The renderer self-gates on
   isCatalogAdminSession() so the mount stays empty for anon visitors —
   no extra surface and no extra fetches.
   Uses existing token vocabulary (var(--bg-card), --border, --accent,
   etc.) so a future theme tweak picks the card up for free. */
.catalog-listing-detail-mount {
  margin-top: 16px;
}
.catalog-listing-detail-card {
  background: var(--bg-card);
  border: var(--border-1);
  border-radius: 14px;
  padding: 14px 12px;
}
.catalog-listing-detail-card__title {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 12px;
  color: var(--text-dim);
  margin-bottom: 12px;
}
/* `__cost` sat here: the monospace cost readout on the editable sale-price card,
   whose renderer (data/catalog/listing-detail-price.js) was deleted in ad8ee9a4
   with the rest of the shop-ops cards. The three sibling `__*` classes around it
   are all still rendered — by the sources card, the activity feed and the
   admin-tools card, which share this shell — so only this one went (2026-08-10,
   same three-way proof as the channels-card block below). */
.catalog-listing-detail-card__row {
  display: flex;
  gap: 8px;
  margin-bottom: 10px;
}
.catalog-listing-detail-card__field { flex: 1; }
.catalog-listing-detail-card__field label {
  display: block;
  font-size: 11px;
  color: var(--text-muted);
  margin-bottom: 4px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.catalog-listing-detail-card__field input,
.catalog-listing-detail-card__field textarea {
  width: 100%;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  color: var(--text);
  font-size: 13px;
  font-family: inherit;
  outline: none;
  box-sizing: border-box;
}
.catalog-listing-detail-card__field input[type='number'] {
  font-family: 'Space Mono', ui-monospace, monospace;
}
.catalog-listing-detail-card__field input:focus,
.catalog-listing-detail-card__field textarea:focus {
  border-color: var(--accent);
}
.catalog-listing-detail-card__field textarea {
  resize: vertical;
  min-height: 32px;
}
.catalog-listing-detail-card__actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}
.catalog-listing-detail-card__actions .btn {
  padding: 7px 14px;
  font-size: 13px;
}
.catalog-listing-detail-card__status {
  color: var(--text-muted);
  font-size: 12px;
  margin-top: 6px;
  min-height: 1em;
}
.catalog-listing-detail-card__status.is-error {
  color: var(--accent-strong);
}
.catalog-listing-detail-card__override {
  margin-top: 14px;
  border-top: var(--border-1);
  padding-top: 10px;
}
.catalog-listing-detail-card__override summary {
  cursor: pointer;
  color: var(--text-muted);
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 4px 0;
}
.catalog-listing-detail-card__override summary:hover { color: var(--accent); }
.catalog-listing-detail-card__override[open] { padding-bottom: 4px; }
.catalog-listing-detail-card__override .catalog-listing-detail-card__row {
  margin-top: 10px;
}
/* `.catalog-listing-strip .strip-link-action` (+ its :hover) lived here: the
   link-shaped "Set price" button the strip's price chip used to render. That
   button was removed when price editing moved to /admin/shop-ops — paintPrice()
   in data/catalog/listing-state-strip.js says so at the call site and now paints
   a plain "No price set" hint instead. Deleted 2026-08-10 on the same three-way
   proof as the channels card below: no literal in any markup producer, absent
   from 16 rendered surfaces (the strip itself DID render on the operator-authed
   item detail page in that sweep), and nothing composes a `strip-link-*` class
   by concatenation. */

/* The ~130-line "Editable channels card (Chunk 2)" block lived here until
   2026-08-10 — the card shell, the four per-channel pill hues, the link /
   price / remove / meta / empty rows and the "Mark for X" shortcut row.
   Its renderer, data/catalog/listing-detail-channels.js, was DELETED in
   ad8ee9a4 ("strip shop-ops cards from catalog item page"), so every class in
   it had been styling nothing since. Proven three ways before deleting, because
   a grep alone produces both false positives and false negatives on this
   frontend: (1) no literal anywhere in data/catalog/**, src/**, shared/,
   scripts/ or the sibling hubs; (2) absent from the rendered DOM of 16 real
   Chromium surfaces (8 pages x 1440/390), including the operator-authed item
   detail page where the card used to mount; (3) no dynamic composition — the
   only per-channel class this frontend still builds by concatenation is
   `catalog-listing-admin-tools-card__pill--<channel>`, a different prefix with
   its own rules injected from that card's own script.
   The surviving channel surface on this page is the Admin-tools card, whose CSS
   travels inside listing-detail-admin-tools.js on purpose. */
/* ── Editable external-sources card (Chunk 3) ──
   The first card below the read-only strip on the catalog item detail page (the
   channels card that used to sit above it is gone — see the note just above).
   Reuses the .catalog-listing-detail-card shell from Chunk 1 and carries its own
   row / pill / link / remove silhouettes, which is why they survived the Chunk 2
   deletion: this card renders every one of them. Per-source pill hues pull from
   the strip's source-chip palette (Phase 2.6) so the card reads as the same
   vocabulary as the read-only strip chips. */
.catalog-listing-sources-card__list {
  list-style: none;
  padding: 0;
  margin: 0 0 10px 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.catalog-listing-sources-card__row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 8px 10px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 10px;
}
.catalog-listing-sources-card__row-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.catalog-listing-sources-card__pill {
  display: inline-flex;
  align-items: center;
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  letter-spacing: 0.02em;
}
.catalog-listing-sources-card__pill--makerworld {
  border-color: rgba(56, 189, 248, 0.32);
  background: rgba(56, 189, 248, 0.14);
  color: #7dd3fc;
}
.catalog-listing-sources-card__pill--printables {
  border-color: rgba(249, 115, 22, 0.32);
  background: rgba(249, 115, 22, 0.14);
  color: #fdba74;
}
.catalog-listing-sources-card__pill--thingiverse {
  border-color: rgba(34, 197, 94, 0.32);
  background: rgba(34, 197, 94, 0.14);
  color: #86efac;
}
.catalog-listing-sources-card__pill--other {
  border-color: rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-muted);
}
.catalog-listing-sources-card__link {
  font-size: 12px;
  color: var(--accent);
  text-decoration: none;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 107, 44, 0.24);
  max-width: 24ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.catalog-listing-sources-card__link:hover {
  background: rgba(255, 107, 44, 0.1);
}
.catalog-listing-sources-card__remove {
  margin-left: auto;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--text-dim);
  width: 26px;
  height: 26px;
  border-radius: var(--radius-pill);
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.catalog-listing-sources-card__remove:hover {
  color: #fda4af;
  border-color: rgba(244, 63, 94, 0.36);
  background: rgba(244, 63, 94, 0.1);
}
.catalog-listing-sources-card__empty {
  list-style: none;
  font-size: 13px;
  color: var(--text-dim);
  font-style: italic;
  padding: 4px 2px;
}
.catalog-listing-sources-card__add summary { /* inherits override summary styling */ }
/* ── Activity feed (Chunk 4 + note_added composer 2026-06-03) ──
   Sits directly below the external-sources card on the catalog item
   detail page. Reuses the .catalog-listing-detail-card shell from Chunk 1
   (background, border, padding, title typography). Rows mirror the
   silhouette used by channels + sources for vocabulary consistency, with
   a muted actor + timestamp line. List caps at ~520px tall on desktop;
   internal scroll handles a 50-event ceiling without pushing the
   similar-items section off the fold. The "+ Note" affordance lives in
   the header to the right of the title; clicking reveals a textarea +
   Save/Cancel that POSTs to /api/listings/:listingKey/notes. */
.catalog-listing-activity-feed__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}
.catalog-listing-activity-feed__add-note {
  appearance: none;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: var(--pill-pad-md);
  border-radius: 6px;
  cursor: pointer;
}
.catalog-listing-activity-feed__add-note:hover {
  background: rgba(255, 255, 255, 0.08);
}
.catalog-listing-activity-feed__composer {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 10px;
  padding: 8px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.025);
}
.catalog-listing-activity-feed__composer[hidden] {
  display: none;
}
.catalog-listing-activity-feed__composer-input {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  min-height: 48px;
  font: inherit;
  color: var(--text);
  background: rgba(0, 0, 0, 0.2);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 6px;
  padding: 6px 8px;
}
.catalog-listing-activity-feed__composer-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.catalog-listing-activity-feed__composer-save,
.catalog-listing-activity-feed__composer-cancel {
  appearance: none;
  font-size: 12px;
  font-weight: 600;
  padding: 4px 12px;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.catalog-listing-activity-feed__composer-save {
  background: rgba(74, 222, 128, 0.18);
  color: var(--text);
}
.catalog-listing-activity-feed__composer-save:hover:not(:disabled) {
  background: rgba(74, 222, 128, 0.28);
}
.catalog-listing-activity-feed__composer-save:disabled,
.catalog-listing-activity-feed__composer-cancel:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.catalog-listing-activity-feed__composer-cancel {
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-muted);
}
.catalog-listing-activity-feed__composer-cancel:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.08);
}
.catalog-listing-activity-feed__composer-status {
  font-size: 12px;
  color: var(--text-muted);
}
.catalog-listing-activity-feed__composer-status--error {
  color: #fda4af;
}
.catalog-listing-activity-feed__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 520px;
  overflow-y: auto;
}
.catalog-listing-activity-feed__row {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 7px 10px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 8px;
}
.catalog-listing-activity-feed__row-head {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}
.catalog-listing-activity-feed__pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  font-size: 12px;
  font-weight: 600;
  border-radius: var(--radius-pill);
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  letter-spacing: 0.02em;
}
.catalog-listing-activity-feed__actor {
  font-size: 12px;
  color: var(--text-muted);
  font-weight: 500;
}
.catalog-listing-activity-feed__when {
  font-size: 12px;
  color: var(--text-dim);
  margin-left: auto;
}
.catalog-listing-activity-feed__summary {
  font-size: 12px;
  color: var(--text-muted);
  word-break: break-word;
  padding-left: 2px;
}
.catalog-listing-activity-feed__empty,
.catalog-listing-activity-feed__error {
  list-style: none;
  font-size: 13px;
  color: var(--text-dim);
  font-style: italic;
  padding: 4px 2px;
}
.catalog-listing-activity-feed__error {
  color: #fda4af;
}

/* ── Reach-out tracker (2026-06-03) ──
   "+ Reach-out" affordance sits next to "+ Note" in the header; the
   composer adds an HTML5 date picker for the due date. Rendered rows
   get a colored left border based on state (red = overdue, amber =
   upcoming, neutral on completed) plus a "Due in Nd" / "Overdue by Nd"
   badge on the row head and an inline "Mark complete" button. */
.catalog-listing-activity-feed__add-reachout {
  appearance: none;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: var(--pill-pad-md);
  border-radius: 6px;
  cursor: pointer;
  margin-left: 6px;
}
.catalog-listing-activity-feed__add-reachout:hover {
  background: rgba(255, 255, 255, 0.08);
}
.catalog-listing-activity-feed__composer-due {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-muted);
}
.catalog-listing-activity-feed__composer-due-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.catalog-listing-activity-feed__composer-due-input {
  font: inherit;
  padding: 4px 6px;
  border-radius: 6px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(0, 0, 0, 0.2);
  color: var(--text);
}
.catalog-listing-activity-feed__row--reachout {
  border-left-width: 4px;
}
.catalog-listing-activity-feed__row--reachout-overdue {
  border-left-color: #f87171;
  background: rgba(248, 113, 113, 0.08);
}
.catalog-listing-activity-feed__row--reachout-upcoming {
  border-left-color: #fbbf24;
  background: rgba(251, 191, 36, 0.06);
}
.catalog-listing-activity-feed__row--reachout-completed {
  border-left-color: rgba(255, 255, 255, 0.18);
}
.catalog-listing-activity-feed__reachout-due {
  font-size: 12px;
  font-weight: 600;
  margin-left: auto;
}
.catalog-listing-activity-feed__row--reachout-overdue
  .catalog-listing-activity-feed__reachout-due {
  color: #fda4af;
}
.catalog-listing-activity-feed__row--reachout-upcoming
  .catalog-listing-activity-feed__reachout-due {
  color: #fcd34d;
}
.catalog-listing-activity-feed__summary--struck {
  text-decoration: line-through;
  opacity: 0.7;
}
.catalog-listing-activity-feed__reachout-actions {
  margin-top: 4px;
}
.catalog-listing-activity-feed__reachout-complete {
  appearance: none;
  font-size: 12px;
  font-weight: 600;
  padding: 3px 10px;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(74, 222, 128, 0.18);
  color: var(--text);
}
.catalog-listing-activity-feed__reachout-complete:hover:not(:disabled) {
  background: rgba(74, 222, 128, 0.28);
}
.catalog-listing-activity-feed__reachout-complete:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Inline edit affordance for the catalog-page detail TITLE.
   Self-gated on canEditCatalogListing() in app-detail-request-form.js, so these
   styles never trigger for anon visitors OR for a `viewer` session (the JS
   doesn't add the editable class — PATCH /api/catalog/item/:id is
   sales+operator). Keeps the read-only surface visually identical to before.
   The matching `.detail-desc-*` rules went with the description editor in
   #975 — nothing adds those classes any more. */
.detail-title-editable {
  cursor: text;
  border-radius: 6px;
  transition: background-color 0.12s ease;
}
.detail-title-editable:hover {
  background: rgba(255,255,255,0.04);
}
.detail-title-edit {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin: 0;
}
.detail-title-edit-input {
  font-family: var(--font-display);
  font-size: clamp(22px, 3.4vw, 36px);
  font-weight: 700;
  line-height: 1.3;
  width: 100%;
  max-width: 100%;
  padding: var(--pill-pad-lg);
  background: rgba(255,255,255,0.06);
  border: var(--border-1);
  border-radius: 6px;
  color: inherit;
  box-sizing: border-box;
}
.detail-title-edit-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.detail-edit-status {
  font-size: 12px;
  color: var(--text-muted);
  min-height: 1em;
}
.detail-edit-status-error {
  color: var(--red, #ff6b6b);
}
