/* ══════════════════════════════════════════════════════════════════════════
   Catalog pages — one look for every "browse a supplier's shelves" page.

   Shared by ss-catalog.html (S&S Activewear) and drinkware.html (Polar
   Camel). The rules were written for the S&S page first and the `ss-`
   prefix stayed when Drinkware adopted them: it is the CATALOG component
   prefix now, not a supplier's initials, and both pages' scripts build
   markup against these class names. Renaming would touch every string in
   two scripts for no change on screen.

   Layout: a sticky top bar (search, count, sort), a row of active-filter
   chips, then a two-column grid — facet sidebar, card grid — and a detail
   view that replaces the grid in place (breadcrumbs, gallery, info).
   Page-specific bits (a price, a buy row) live at the bottom, sectioned.
   ══════════════════════════════════════════════════════════════════════════ */

/* `hidden` has to actually hide things — several rules below set display,
   and any one of them beats the UA stylesheet's plain [hidden] rule. Same
   declaration, for the same reason, as garment-proof.html. */
[hidden] { display: none !important; }

/* ── Tab strip: one tab per supplier, in the hero (catalog.html) ──
   Plain links, not buttons: each tab is a full navigation, because the two
   scripts both keep their state in the query string and can't share a page. */
.cat-tabs {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.5rem;
  margin-top: 2rem; border-bottom: 1px solid var(--border);
}
.cat-tabs .ss-label { margin-right: 0.5rem; padding-bottom: 0.7rem; }
.cat-tab {
  position: relative; display: inline-block; padding: 0.45rem 0.9rem 0.7rem;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.04em; color: var(--text-muted);
  text-decoration: none; transition: color 0.15s;
}
.cat-tab::after {
  content: ''; position: absolute; left: 0.9rem; right: 0.9rem; bottom: -1px;
  height: 2px; background: var(--accent); border-radius: 1px;
  transform: scaleX(0); transition: transform 0.18s;
}
.cat-tab:hover { color: var(--text); }
.cat-tab.is-on { color: var(--accent); }
.cat-tab.is-on::after { transform: scaleX(1); }

/* ── Top bar: search, count, sort ── */
.ss-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0.75rem;
  background: var(--card); border: 1px solid var(--border);
  border-radius: 8px; padding: 0.6rem 0.75rem; margin-bottom: 1rem;
  /* --header-fixed, not --header-total: sticky resolves against the
     VIEWPORT, so it needs the token that grows with the notice-bar stack. */
  position: sticky; top: var(--header-fixed); z-index: 50;
  box-shadow: var(--shadow-sm);
}
.ss-search { position: relative; flex: 1 1 260px; min-width: 0; }
.ss-search svg {
  position: absolute; left: 0.75rem; top: 50%; transform: translateY(-50%);
  color: var(--text-dim); pointer-events: none;
}
.ss-search input {
  width: 100%; font-size: 0.9rem; color: var(--text);
  padding: 0.6rem 2.2rem 0.6rem 2.3rem;
  border: 1.5px solid var(--border); border-radius: 6px; background: var(--surface);
  transition: border-color 0.15s, background 0.15s;
}
.ss-search input:focus { outline: none; border-color: var(--accent); background: var(--white); }
.ss-search-clear {
  position: absolute; right: 0.4rem; top: 50%; transform: translateY(-50%);
  width: 1.6rem; height: 1.6rem; border: none; border-radius: 50%;
  background: transparent; color: var(--text-dim); cursor: pointer; font-size: 1rem; line-height: 1;
}
.ss-search-clear:hover { background: var(--surface-2); color: var(--accent); }
.ss-count { font-size: 0.8rem; color: var(--text-muted); white-space: nowrap; }
.ss-count strong { color: var(--text); font-weight: 600; }
.ss-sort { display: flex; align-items: center; gap: 0.4rem; }
.ss-label {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--text-dim); white-space: nowrap;
}
.ss-sort select {
  font-size: 0.8rem; color: var(--text); padding: 0.45rem 0.6rem;
  border: 1.5px solid var(--border); border-radius: 6px; background: var(--surface); cursor: pointer;
}
.ss-sort select:focus { outline: none; border-color: var(--accent); }
.ss-filter-toggle { display: none; }

/* ── Active filters ── */
.ss-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; margin-bottom: 1rem; }
.ss-chip {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-size: 0.74rem; font-weight: 600; color: var(--accent);
  background: var(--accent-dim); border: 1px solid var(--accent-mid);
  border-radius: 999px; padding: 0.28rem 0.4rem 0.28rem 0.75rem; cursor: pointer;
  transition: background 0.15s;
}
.ss-chip:hover { background: var(--accent-mid); }
.ss-chip span[aria-hidden] { font-size: 0.95rem; line-height: 1; opacity: 0.7; }
.ss-chip small { font-weight: 500; opacity: 0.75; font-size: inherit; }
.ss-link {
  background: none; border: none; padding: 0; cursor: pointer;
  font-size: 0.76rem; color: var(--text-muted); text-decoration: underline;
  text-underline-offset: 2px; font-family: inherit;
}
.ss-link:hover { color: var(--accent); }

/* ── Two columns: filters, results ── */
.ss-wrap { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 2rem; align-items: start; }

.ss-side {
  position: sticky; top: calc(var(--header-fixed) + 4.75rem);
  max-height: calc(100vh - var(--header-fixed) - 5.75rem);
  overflow-y: auto; overscroll-behavior: contain;
  background: var(--card); border: 1px solid var(--border); border-radius: 8px;
}
.ss-facet { border-bottom: 1px solid var(--border-light); }
.ss-facet:last-child { border-bottom: none; }
.ss-facet > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.85rem 1rem; font-size: 0.66rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text);
}
.ss-facet > summary::-webkit-details-marker { display: none; }
.ss-facet > summary::after {
  content: ''; width: 6px; height: 6px; margin-right: 2px;
  border-right: 1.5px solid var(--text-dim); border-bottom: 1.5px solid var(--text-dim);
  transform: rotate(45deg); transition: transform 0.2s;
}
.ss-facet[open] > summary::after { transform: rotate(-135deg); }
.ss-facet-body { padding: 0 0.5rem 0.75rem; }
.ss-facet-find {
  width: calc(100% - 1rem); margin: 0 0.5rem 0.5rem; font-size: 0.8rem;
  padding: 0.4rem 0.6rem; border: 1.5px solid var(--border); border-radius: 5px; background: var(--surface);
}
.ss-facet-find:focus { outline: none; border-color: var(--accent); background: var(--white); }
.ss-facet-list { max-height: 17rem; overflow-y: auto; overscroll-behavior: contain; }
.ss-facet-list--all { max-height: none; }
.ss-opt {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  width: 100%; text-align: left; background: none; border: none; cursor: pointer;
  font-family: inherit; font-size: 0.84rem; color: var(--text-muted);
  padding: 0.36rem 0.5rem; border-radius: 5px; transition: background 0.12s, color 0.12s;
}
.ss-opt:hover { background: var(--surface); color: var(--text); }
.ss-opt.is-on { background: var(--accent-dim); color: var(--accent); font-weight: 600; }
.ss-opt-n { font-size: 0.7rem; color: var(--text-dim); font-variant-numeric: tabular-nums; flex-shrink: 0; }
.ss-opt.is-on .ss-opt-n { color: var(--accent); }
.ss-facet-empty { font-size: 0.78rem; color: var(--text-dim); padding: 0.25rem 0.5rem; }

/* ── Grid ── */
.ss-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 1.1rem; }
.ss-card {
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  background: var(--card); border: 1px solid var(--border); border-radius: 8px; overflow: hidden;
  transition: border-color 0.18s, box-shadow 0.18s, transform 0.18s;
}
.ss-card:hover, .ss-card:focus-visible, .ss-card:focus-within {
  border-color: var(--accent); box-shadow: var(--shadow-md); transform: translateY(-2px); outline: none;
}
.ss-card-img {
  position: relative; aspect-ratio: 1 / 1.12; background: var(--white);
  border-bottom: 1px solid var(--border-light);
  display: flex; align-items: center; justify-content: center;
}
.ss-card-img img { width: 100%; height: 100%; object-fit: contain; padding: 0.6rem; }
.ss-noimg { font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim); }
.ss-badges { position: absolute; top: 0.5rem; left: 0.5rem; display: flex; flex-wrap: wrap; gap: 0.3rem; }
.ss-badge {
  font-size: 0.58rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  padding: 0.2rem 0.45rem; border-radius: 4px; background: var(--accent); color: var(--white);
}
.ss-badge--eco { background: #2e6b3f; }
.ss-card-body { padding: 0.75rem 0.85rem 0.85rem; display: flex; flex-direction: column; gap: 0.2rem; flex: 1; }
.ss-card-brand {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent);
}
.ss-card-name { font-family: var(--ff-display); font-size: 1.05rem; font-weight: 700; color: var(--text); line-height: 1.2; }
.ss-card-title {
  font-size: 0.8rem; color: var(--text-muted); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ss-card-id {
  margin-top: auto; padding-top: 0.5rem; font-family: var(--ff-mono);
  font-size: 0.7rem; color: var(--text-dim); letter-spacing: 0.02em;
}

/* Skeletons, so a cold first load reads as "arriving" rather than "empty". */
.ss-card--skel { pointer-events: none; }
.ss-card--skel .ss-card-img, .ss-skel-line {
  background: linear-gradient(100deg, var(--surface-2) 30%, var(--surface) 50%, var(--surface-2) 70%);
  background-size: 300% 100%; animation: ss-shimmer 1.4s linear infinite;
}
.ss-skel-line { height: 0.7rem; border-radius: 4px; margin-top: 0.35rem; }
@keyframes ss-shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) {
  .ss-card--skel .ss-card-img, .ss-skel-line { animation: none; }
  .ss-card { transition: none; }
}

.ss-status {
  text-align: center; padding: 3rem 1.5rem; border: 1px dashed var(--border);
  border-radius: 8px; background: var(--surface);
}
.ss-status h3 { margin-bottom: 0.5rem; }
.ss-status p { max-width: 460px; margin: 0 auto 1rem; }
.ss-status code { font-family: var(--ff-mono); font-size: 0.85em; background: var(--surface-2); padding: 0.1em 0.35em; border-radius: 3px; color: var(--text); }
.ss-more { display: flex; justify-content: center; padding: 2rem 0 0; }
.ss-loading-note { text-align: center; font-size: 0.82rem; color: var(--text-muted); padding: 1.25rem 0 0; }

.ss-sync {
  margin-top: 2.5rem; padding-top: 1rem; border-top: 1px solid var(--border-light);
  font-size: 0.74rem; color: var(--text-dim); display: flex; flex-wrap: wrap; gap: 0.35rem 0.75rem; align-items: center;
}

/* ── Detail view ── */
.ss-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; font-size: 0.78rem; color: var(--text-dim); margin-bottom: 1.5rem; }
.ss-crumbs button { background: none; border: none; padding: 0; font: inherit; color: var(--text-muted); cursor: pointer; }
.ss-crumbs button:hover { color: var(--accent); text-decoration: underline; }
.ss-crumbs .ss-back { font-weight: 600; color: var(--accent); margin-right: 0.5rem; }
.ss-crumbs [aria-current] { color: var(--text); font-weight: 600; }

.ss-detail { display: grid; grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 3rem; align-items: start; }
.ss-gallery { position: sticky; top: calc(var(--header-fixed) + 1rem); }
.ss-stage {
  aspect-ratio: 1 / 1.1; background: var(--white); border: 1px solid var(--border); border-radius: 8px;
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.ss-stage img { width: 100%; height: 100%; object-fit: contain; padding: 1rem; }
.ss-thumbs { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.ss-thumb {
  width: 62px; height: 70px; padding: 3px; background: var(--white); cursor: pointer;
  border: 1.5px solid var(--border); border-radius: 6px; transition: border-color 0.15s;
}
.ss-thumb img { width: 100%; height: 100%; object-fit: contain; }
.ss-thumb:hover { border-color: var(--text-dim); }
.ss-thumb.is-on { border-color: var(--accent); }

.ss-info .eyebrow { margin-bottom: 0.4rem; }
.ss-info h2 { font-size: clamp(1.7rem, 3vw, 2.4rem); margin-bottom: 0.35rem; }
.ss-info-title { font-size: 1.05rem; color: var(--text-muted); margin-bottom: 1rem; }
.ss-ids { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1.75rem; }
.ss-id {
  font-family: var(--ff-mono); font-size: 0.74rem; color: var(--text);
  background: var(--surface-2); border-radius: 4px; padding: 0.25rem 0.55rem;
}
.ss-id b { font-family: var(--ff-body); font-size: 0.6rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim); margin-right: 0.35rem; }
.ss-block { margin-bottom: 1.6rem; }
.ss-block-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.6rem; }
.ss-block-head strong { font-size: 0.9rem; color: var(--text); font-weight: 600; }

.ss-swatches { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.ss-swatch {
  width: 34px; height: 34px; border-radius: 50%; padding: 0; cursor: pointer;
  border: 1px solid rgba(30, 27, 24, 0.18); background-size: cover; background-position: center;
  outline: 2px solid transparent; outline-offset: 2px; transition: outline-color 0.15s, transform 0.15s;
}
.ss-swatch:hover { transform: scale(1.08); }
.ss-swatch.is-on { outline-color: var(--accent); }
.ss-sizes { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.ss-size {
  min-width: 2.9rem; font-size: 0.78rem; font-weight: 600; color: var(--text-muted);
  padding: 0.45rem 0.7rem; border: 1.5px solid var(--border); border-radius: 6px;
  background: var(--card); cursor: pointer; transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.ss-size:hover { border-color: var(--accent); color: var(--accent); }
.ss-size.is-on { border-color: var(--accent); color: var(--accent); background: var(--accent-dim); }

.ss-pick {
  background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--accent);
  border-radius: 8px; padding: 1rem 1.15rem; margin-bottom: 1.75rem;
}
.ss-pick-head { font-family: var(--ff-display); font-size: 1.1rem; font-weight: 700; color: var(--text); margin-bottom: 0.15rem; }
.ss-pick-sub { font-size: 0.8rem; line-height: 1.55; margin-bottom: 0.75rem; }
.ss-pick dl { display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 1rem; margin: 0; font-size: 0.84rem; }
.ss-pick dt { font-size: 0.62rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim); align-self: center; }
.ss-pick dd { margin: 0; color: var(--text); }
.ss-pick dd.mono { font-family: var(--ff-mono); font-size: 0.8rem; }
.ss-pick dd.is-unset { color: var(--text-dim); font-style: italic; }

.ss-desc { border-top: 1px solid var(--border-light); padding-top: 1.4rem; }
.ss-desc, .ss-desc p, .ss-desc li { font-size: 0.88rem; color: var(--text-muted); line-height: 1.7; }
.ss-desc ul, .ss-desc ol { list-style: disc; padding-left: 1.2rem; margin: 0.4rem 0; }
.ss-desc ol { list-style: decimal; }

/* ── Narrow ── */
@media (max-width: 900px) {
  .ss-wrap { grid-template-columns: minmax(0, 1fr); gap: 1rem; }
  .ss-filter-toggle { display: inline-flex; }
  .ss-side { position: static; max-height: none; display: none; }
  .ss-side.is-open { display: block; }
  .ss-detail { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; }
  .ss-gallery { position: static; }
  .ss-count { order: 3; }
}
@media (max-width: 520px) {
  .ss-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; }
  .ss-card-name { font-size: 0.95rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Priced catalogs (Drinkware) — a card that can be bought from
   ══════════════════════════════════════════════════════════════════════════ */

/* A priced card isn't one link: the picture and the name open the product,
   the row underneath adds it. So the card is a block with an <a> inside it,
   and the whole-card hover is carried by :focus-within above. */
.ss-card-link { display: flex; flex-direction: column; flex: 1; text-decoration: none; color: inherit; }
.ss-card-link:focus-visible { outline: none; }

.ss-badge--note { background: #b7791f; }

.ss-price { font-size: 0.95rem; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.ss-card-foot {
  display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
  padding: 0.6rem 0.85rem 0.8rem; border-top: 1px solid var(--border-light); background: var(--surface);
}
.ss-card-foot .ss-price { font-size: 0.9rem; }
/* Where the price would be on a product that has none — "Ask us for a price".
   Named for the sold-out state it also used to carry; that state is gone and
   price is now the only reason a product can't be added. */
.ss-sold-note { font-size: 0.68rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); }

/* Quantity stepper + add button. On a card the stepper is hidden and Add
   means one; the detail view shows both. */
.ss-buy { display: flex; align-items: stretch; gap: 0.5rem; }
.ss-qty { display: inline-flex; align-items: stretch; border: 1.5px solid var(--border); border-radius: 6px; overflow: hidden; background: var(--card); }
.ss-qty button {
  width: 2rem; border: none; background: transparent; color: var(--text-muted); cursor: pointer;
  font-size: 1rem; line-height: 1; padding: 0; font-family: inherit;
}
.ss-qty button:hover { background: var(--surface-2); color: var(--accent); }
.ss-qty input {
  width: 2.6rem; border: none; text-align: center; font-size: 0.86rem; font-weight: 600; color: var(--text);
  background: transparent; outline: none; padding: 0; font-variant-numeric: tabular-nums;
}
.ss-buy .btn { white-space: nowrap; }
.ss-added {
  font-size: 0.78rem; font-weight: 600; color: #2e6b3f; min-height: 1.2em; margin-top: 0.5rem;
}
.ss-added a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.ss-added.is-error { color: #b42318; }
.ss-card > .ss-added { margin: 0; padding: 0.45rem 0.85rem 0.65rem; background: var(--surface); }
.ss-pick .ss-price { font-size: 1.5rem; font-family: var(--ff-display); margin-bottom: 0.6rem; display: block; }

/* ══ Admin mode ═══════════════════════════════════════════════════════════
   Taking something off the shelf, on the page where you can see it. One set
   of rules for every catalog tab, because the controls are one component
   (js/catalog-admin.js) rendered by each tab's own card and facet markup.

   Everything here is inert without the toggle, which catalog.html renders
   only for admins — and the server re-checks on every request regardless. */

/* The toggle, in the tab strip. Deliberately quiet: it sits beside the
   catalog names and must not read as a third catalog. */
/* The toggle and its badges. The right-alignment and the baseline nudge live
   HERE rather than on .cat-admin, because the badges had to come out of the
   <label> — inside it, clicking "3 sold out" toggled admin mode off, and that
   badge names exactly what the Sold out lens shows, so it reads as a control. */
.cat-admin-wrap {
  display: inline-flex; align-items: center; gap: 0.35rem;
  margin-left: auto; margin-bottom: 0.45rem;
}
.cat-admin {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--border); border-radius: 999px; cursor: pointer;
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em;
  color: var(--text-muted); background: var(--card); user-select: none;
}
.cat-admin:hover { border-color: var(--accent); color: var(--text); }
.cat-admin input { margin: 0; accent-color: var(--accent); }
.cat-admin.is-on { border-color: var(--accent); color: var(--accent); background: var(--accent-dim); }
/* SLATE, not red. Red in this file now means exactly one thing — "we have run
   out of these" — and this badge counts the opposite kind of fact: things the
   shop deliberately switched off. They were both #b42318 until stock landed,
   which made two different instructions the same color in the same strip. */
.cat-admin-n {
  font-size: 0.66rem; font-weight: 800; color: #fff; background: #565150;
  border-radius: 999px; padding: 0.08rem 0.4rem;
}

/* The switch itself, on a card or beside a facet row. */
.cat-off-btn {
  font: inherit; font-size: 0.68rem; font-weight: 700; letter-spacing: 0.03em;
  padding: 0.2rem 0.5rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--card); color: var(--text-muted);
  white-space: nowrap; flex-shrink: 0;
}
.cat-off-btn:hover { border-color: #b42318; color: #b42318; }
/* Already off: the button now puts it BACK, so it reads as the way out. */
.cat-off-btn.is-off { border-color: #2e6b3f; color: #2e6b3f; }
.cat-off-btn.is-off:hover { background: #2e6b3f; color: #fff; }
.cat-off-btn[disabled] { opacity: 0.5; cursor: default; }

/* A product inside a switched-off collection. Its own switch is still on, so
   there is no button to show — a button that changed nothing would read as
   broken. This says which switch to go and find instead. */
.cat-off-note {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.03em;
  color: #b42318; white-space: nowrap; cursor: help;
}

/* The badge on a disabled card's photo. Over the image rather than under the
   name, because the picture is what the eye lands on first — and on the RIGHT,
   because .ss-badges already owns the top-left corner (New / Sustainable / a
   discontinued note) and two stacks in one corner overlap.
   Slate rather than red, matching the grayed-out photo below it and the hero's
   "N off" badge. Red belongs to the sold-out badge in the opposite corner: one
   card can carry both, and "we took this down" and "we ran out of this" are
   the two instructions this whole feature exists to keep apart, so they must
   not arrive in the same color. */
.cat-off-tag {
  position: absolute; right: 0.45rem; top: 0.45rem; z-index: 2;
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.04em;
  color: #fff; background: #565150; border-radius: 5px; padding: 0.1rem 0.4rem;
}
/* Grayed, not hidden: the admin is looking AT the thing they switched off. */
.ss-card.is-disabled .ss-card-img img { opacity: 0.4; filter: grayscale(1); }
.ss-card.is-disabled .ss-card-body { opacity: 0.6; }

/* A facet row in admin mode is the filter plus its switch. The filter keeps
   all the width it had; the switch only appears in admin mode. */
.ss-opt-row { display: flex; align-items: center; gap: 0.25rem; }
.ss-opt-row .ss-opt { flex: 1; min-width: 0; }
.ss-opt.is-off { text-decoration: line-through; color: var(--text-dim); }

/* ══ On hand ══════════════════════════════════════════════════════════════
   Stock, which is a SECOND reason a product can't be bought and must never
   look like the first one. "We took it down" and "we ran out" are different
   instructions to whoever is reading the card — that is the whole point of
   this feature and the reason the old inventory column was dropped in Sep
   2026 — so RED now means "we ran out" and nothing else, and the
   switched-off badge (.cat-off-tag) and the hero's "N off" were moved to
   slate to pay for it. They were all #b42318 before, which is the rule
   failing on the first card that is both.

   One amber note before anything uses it: #b7791f is this file's amber, and
   it is a badge FILL carrying white text (.ss-badge--note). As TEXT it is only
   3.2:1 on --surface-2, which is the darkest ground these labels land on and
   the one CLAUDE.md says to check against. #8a5a08 is the same amber taken
   down to 5.2:1 there, and it is what the word-sized amber below uses. Don't
   swap them back. */

/* The hero's second badge. TWO badges and never a sum: taken down and run out
   are exactly what this change exists to keep apart. They are told apart by
   HUE and not by outlining — this one carries the red that means "we ran out"
   on every other surface, while "N off" went slate to match the switched-off
   card. An outline in the same red was the first attempt and it failed the
   rule it was written for: hue is what the eye reads here, so two red pills
   side by side are one state wearing two shapes. */
.cat-admin-n--sold {
  color: #fff; background: #b42318;
}

/* The on-hand box itself, in a card foot or a product view. Blank in the box
   is a real answer — "we don't count this one" — which is why the placeholder
   is an em dash and not a 0. */
/* It WRAPS, and does not refuse to shrink. The card is `overflow: hidden` and
   the grid goes two-up under 520px, which leaves a foot about 138px wide — and
   `nowrap` + `flex-shrink: 0` there clipped the control from the right, taking
   off exactly the span that names the state: "Not counted" became "Not count",
   "Oversold by 12" became "Oversold b". The whole premise of this feature is
   that every state says itself in words, so the words are the last thing
   allowed to go. */
.cat-stock {
  display: inline-flex; align-items: center; gap: 0.3rem;
  flex-wrap: wrap; min-width: 0; max-width: 100%;
}
.cat-stock-lab {
  font-size: 0.58rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-dim);
}
.cat-stock-in {
  width: 3.5em; text-align: center; font: inherit; font-size: 0.74rem; font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--text);
  padding: 0.16rem 0.2rem; border: 1px solid var(--border); border-radius: 5px;
  background: var(--card);
}
.cat-stock-in:focus { outline: none; border-color: var(--accent); }
/* The collection this sits in is switched off, so the count decides nothing
   today. Still editable — counting a shelf is worth doing either way. */
.cat-stock.is-moot { opacity: 0.6; }

/* What the number MEANS, in words, beside it: Not counted / Low / Sold out /
   Oversold by N, plus whatever a failed save has to say. js/catalog-admin.js
   owns the wording and stashes the resting text on the element so a flashed
   message can put it back. */
.cat-stock-state {
  font-size: 0.62rem; font-weight: 700; letter-spacing: 0.03em;
  color: var(--text-muted); min-width: 0; overflow-wrap: anywhere;
}
.cat-stock-state.is-warn { color: #8a5a08; }
.cat-stock-state.is-bad  { color: #b42318; }

/* Two-up cards leave about 138px of foot. The label goes (the input carries
   the accessible name, so nothing is lost but the ink) and the state span takes
   its own line under the box rather than being cut off the right edge. */
@media (max-width: 520px) {
  .cat-stock-lab { display: none; }
  .cat-stock-state { flex-basis: 100%; }
}

/* Sold out, on the card. The price stays up beside this — a card with no
   price reads as a different failure — so the pill is what carries the news. */
.ss-sold-pill {
  font-size: 0.62rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  color: #fff; background: #b42318; border-radius: 999px; padding: 0.12rem 0.5rem;
}
/* In .ss-badges with the note badge, so there is only ever one stack in that
   corner. .cat-off-tag owns the opposite corner for the same reason. */
.ss-badge--sold { background: #b42318; }

/* "Only N left" — advice, not a refusal, so amber and never red. */
.ss-low-note {
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.02em; color: #8a5a08;
}
.ss-pick .ss-low-note { display: block; margin: -0.3rem 0 0.7rem; }

/* The foot now holds up to four things — price, a note or pill, the Disable
   switch and the on-hand box — so it wraps instead of squeezing the price
   down to nothing on a narrow card. */
.ss-card-foot { flex-wrap: wrap; }
.ss-card-foot .ss-low-note { margin-right: auto; }

/* Sold out is a LIGHTER touch than disabled, deliberately: the photo keeps its
   color, because running out is a fact about the shelf and not something
   anybody took down. Grayscale here would make the two states look alike,
   which is the one thing they must not do. */
.ss-card.is-soldout .ss-card-foot { background: var(--surface-2); }
