/* ---------------------------------------------------------------------------
   product.css — one scraped product, and the skeleton that stands in for it.
   ---------------------------------------------------------------------------
   The skeletons are not decoration. A website scrape runs for minutes, and an
   empty section during it is indistinguishable from a hung app. So the shimmer
   holds the shape of what is coming, and the section is never silent.
--------------------------------------------------------------------------- */

.product {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  gap: var(--s-3);
  padding: var(--s-3);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
}

/* ---- the cover slot ------------------------------------------------------ */
/* Deliberately does NOT load the scraped image: fetching it would pull a third
   party asset into this page and tell that server we are looking at them. The
   host is named instead, so the operator still knows an image was found. */
.product__media {
  position: relative;
  display: grid;
  place-items: center;
  gap: var(--s-1);
  aspect-ratio: 4 / 3;
  padding: var(--s-2);
  border-radius: var(--r-sm);
  background: var(--c-primary-soft);
  color: var(--c-primary);
  overflow: hidden;
}
.product__art { line-height: 0; opacity: .55; }
.product__art svg { width: 40px; height: 40px; }
.product__imghost {
  font-size: var(--t-xs);
  color: var(--c-primary);
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.product__imghost[hidden] { display: none; }
.product--hasimg .product__media { background: var(--c-accent-soft); }

.product__body {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  min-width: 0;
}

.product__head {
  display: flex;
  align-items: start;
  justify-content: space-between;
  gap: var(--s-2);
}
.product__name {
  font-size: var(--t-md);
  font-weight: var(--fw-semi);
  min-width: 0;
}
.product__status { flex: none; }
/* Working states get a pulse, so "Rewriting" reads as something in flight
   rather than as a label that has been sitting there for a minute. */
.product__status.is-working { animation: pip-pulse 1.6s var(--m-ease) infinite; }

.product__meta {
  gap: var(--s-1) var(--s-2);
  font-size: var(--t-sm);
  min-width: 0;
}
.product__price { font-weight: var(--fw-semi); color: var(--c-fg); }
.product__price.faint { font-weight: var(--fw-normal); }
.product__source { background: var(--c-idle-soft); color: var(--c-idle-ink); }
.product__source[hidden], .product__link[hidden] { display: none; }
.product__link {
  font-size: var(--t-xs);
  color: var(--c-primary);
  max-width: 40ch;
}

/* The raw scrape, verbatim. Never cleaned up: it is the "before" the rewrite is
   being judged against. Clamped so one lead with a 4000 character page dump
   cannot push every other card off the screen. */
.product__raw {
  margin: 0;
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  color: var(--c-fg-muted);
  display: -webkit-box;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.product__skip {
  margin: 0;
  font-size: var(--t-sm);
  font-weight: var(--fw-medium);
  color: var(--c-drop);
}
.product__skip[hidden] { display: none; }

.product[data-status="skipped"] { background: var(--c-drop-soft); }
.product[data-status="skipped"] .product__name { color: var(--c-fg-muted); }
.product[data-status="listed"] { border-color: var(--c-ok-soft); }
.product[data-status="failed"] { border-color: var(--c-danger); background: var(--c-danger-soft); }

/* ---- skeletons ----------------------------------------------------------- */
.product--sk .product__media { background: var(--c-idle-soft); }
.sk--line {
  height: 10px;
  border-radius: var(--r-pill);
}
.sk--w80 { width: 80%; }
.sk--w60 { width: 60%; }
.sk--w30 { width: 30%; }
.product--sk .product__body { gap: var(--s-2); padding-top: var(--s-1); }

@media (max-width: 700px) {
  .product { grid-template-columns: 72px minmax(0, 1fr); gap: var(--s-2); padding: var(--s-2); }
  .product__art svg { width: 28px; height: 28px; }
  .product__head { flex-direction: column; }
  .product__status { align-self: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
  .product__status.is-working { animation: none; }
}
