/* Catalog, search and product-page styles (WP2). Loaded after site.css. */

/* ── Toolbar ───────────────────────────────────────────────────────────────────────────────────────────────── */
.toolbar__count{margin:0;color:var(--text-2);font-size:var(--fs-sm)}
.toolbar__controls{display:flex;flex-wrap:wrap;gap:var(--s-2);align-items:center}
.sort-form{display:flex;gap:6px;align-items:center}
/* The Apply button exists for visitors without JavaScript; with JS the select submits itself. */
.has-js .sort-form button{display:none}
.per-page a,.view-toggle a{min-width:38px;text-align:center}

/* ── Filter sidebar ────────────────────────────────────────────────────────────────────────────────────────── */
.filters-form{display:flex;flex-direction:column;gap:var(--s-2)}
.filters-form summary{cursor:pointer;align-items:center}
.filters-form summary svg{opacity:.6;flex:none}
.filters-form details[open]>summary svg{transform:rotate(180deg)}
.filters .check>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.filters .check.is-zero{opacity:.45}
.filters .check.is-zero small{opacity:.8}
.facet-filter{min-height:32px;padding:4px 8px;font-size:var(--fs-sm);margin-bottom:6px}
.filters details.more{border:0;padding:0}
.filters details.more>summary{font-weight:500;color:var(--text-link);font-size:var(--fs-xs)}
.price-range{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-2)}
.price-range input{min-height:34px;padding:4px 8px}
.price-range .hint{font-size:var(--fs-xs);color:var(--text-muted)}
.filters-actions{margin-top:var(--s-3);gap:8px}
/* The sidebar's compact controls are a DESKTOP density. They only started applying when base.css stopped out-specifying
   them (v1.7 fix round), so on a touch screen they take the 44px target DESIGN.md §4 commits to — same as
   .market-facet__opt below. */
@media (pointer:coarse){.facet-filter,.price-range input{min-height:44px}}

/* Mobile filter sheet: a <dialog> the JS fills with the same form. Without JS the form stays inline. */
.filters.has-sheet .filters-body{display:none}
.filters-sheet{width:min(560px,100%);max-width:100%;margin:auto auto 0;padding:0;border:1px solid var(--border);border-radius:var(--r-lg) var(--r-lg) 0 0;background:var(--surface-solid,var(--bg-1));color:var(--text);max-height:86vh;overflow:hidden}
.filters-sheet::backdrop{background:rgba(0,0,0,.55)}
.filters-sheet__head{display:flex;align-items:center;justify-content:space-between;padding:var(--s-3) var(--s-4);border-bottom:1px solid var(--divider)}
.filters-sheet__body{padding:0 var(--s-4);overflow:auto;max-height:60vh}
.filters-sheet__foot{padding:var(--s-3) var(--s-4);border-top:1px solid var(--divider);position:sticky;bottom:0;background:inherit}
@media (min-width:1024px){.filters-sheet{display:none}}

/* ── Chips ─────────────────────────────────────────────────────────────────────────────────────────────────── */
.chip--btn{display:inline-flex;align-items:center;gap:6px}
.hint-chips{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:0 0 var(--s-3)}

/* ── Cards and rows ────────────────────────────────────────────────────────────────────────────────────────── */
.pcard__meta{display:flex;flex-wrap:wrap;gap:8px;align-items:center;font-size:var(--fs-xs);color:var(--text-muted)}
.pcard__meta .lead{display:inline-flex;align-items:center;gap:4px}
.per-unit{font-size:var(--fs-xs);color:var(--text-2);white-space:nowrap}
/* The compare table carries the photo too (ADR-158): it is the DEFAULT view of a category, so a shop with pictures
   was showing none of them where most buyers look. The box is always there, photo or not, so rows never shift. */
.ptable td.title{display:flex;align-items:flex-start;gap:10px}
.prow__thumb{flex:none;display:flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:var(--r-sm,7px);background:#fff;overflow:hidden;text-decoration:none!important}
.prow__thumb img{width:100%;height:100%;object-fit:contain;padding:3px}
.prow__thumb .pcard__nophoto{border-radius:inherit}
.prow__name{min-width:0}
@media (max-width:760px){.prow__thumb{width:36px;height:36px}}
.ptable th a.th-sort{color:inherit;text-decoration:none;display:inline-flex;gap:4px;align-items:center;white-space:nowrap}
.ptable th a.th-sort:hover,.ptable th a.th-sort.is-active{color:var(--text-link)}
.ptable td.add{white-space:nowrap}
/* 64px, or the box stretches to 130px and pushes the Add button out of the table at every desktop width (v1.5.1
   integration walk). This used to replicate base.css's :not() chain to out-specify it; base.css wraps the chain in
   :where() since the v1.7 fix round, so a plain selector is heard. */
.ptable td.add .qty{width:64px;min-height:32px;padding:2px 6px;margin:0 6px}
.ptable-foot{display:flex;justify-content:flex-end;padding:var(--s-3) 0}

/* ── Search page ───────────────────────────────────────────────────────────────────────────────────────────── */
.search-correction{margin-bottom:var(--s-3)}
.did-you-mean{color:var(--text-2);margin:0 0 var(--s-3)}
.did-you-mean a{margin-right:8px}
.mpn-misses{margin-bottom:var(--s-4)}
.mpn-misses__title{font-size:var(--fs-md);margin:0 0 4px}
.mpn-list{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:6px}
.mpn-list li{display:flex;flex-wrap:wrap;gap:10px;align-items:baseline;padding:6px 0;border-bottom:1px solid var(--divider);font-size:var(--fs-sm)}
.mpn-list li:last-child{border-bottom:0}
.mpn-list .ok{color:var(--success)}
/* rgb(… / a), never rgba(<space-separated channels>, a): --accent-rgb is declared as "r g b" (tokens.css), so the
   comma form is invalid at computed-value time and the highlight silently loses its background altogether. */
mark{background:rgb(var(--accent-rgb) / .28);color:var(--text);border-radius:3px;padding:0 1px}

.empty-state{display:flex;flex-direction:column;gap:var(--s-3)}
.empty-state h2{font-size:var(--fs-lg);margin:0}
.sourcing-form .cols{display:grid;gap:var(--s-3);grid-template-columns:1fr}
@media (min-width:640px){.sourcing-form .cols{grid-template-columns:repeat(2,1fr)}}
.popular{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin:0}
.brand-tiles small,.brand-cats small{color:var(--text-muted);display:block}

/* ── Suggest dropdown ──────────────────────────────────────────────────────────────────────────────────────── */
.suggest__group{padding:6px 12px 2px;font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted)}
.site-search__suggest a{display:grid;grid-template-columns:minmax(0,1fr);gap:2px}
.suggest__meta{display:flex;gap:6px;align-items:center;font-size:var(--fs-xs);color:var(--text-muted)}
.suggest__meta .dot{width:8px;height:8px;border-radius:50%;background:var(--stock-out);display:inline-block}
.suggest__meta .dot.ok{background:var(--stock-in)}
/* The unavailable state in words beside the dot (contract §6.2); --text-2 keeps it readable on the dropdown. */
.suggest__out{color:var(--text-2);white-space:nowrap}
.suggest__all{font-weight:600}

/* ── Product page ──────────────────────────────────────────────────────────────────────────────────────────── */
.back-to{margin:0 0 var(--s-2);font-size:var(--fs-sm)}
.back-to a{display:inline-flex;align-items:center;gap:6px}
:root{--buy-bar-h:52px}
.buy-bar{position:fixed;left:0;right:0;bottom:0;z-index:40;min-height:var(--buy-bar-h);background:var(--surface-solid,var(--bg-1));border-top:1px solid var(--border);padding:8px 0;box-shadow:var(--shadow-2)}
.buy-bar__inner{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3)}
@media (min-width:900px){.buy-bar{display:none}}
/* The opaque bar never covers the end of the page: nothing added bottom space for it, so at maximum scroll on a
   375 px phone the footer's last line ("Prices and availability update automatically. Last update: …") sat behind the
   bar and could not be brought into view. Same shape as the configurator's bar (configurator.css §sticky bar),
   safe-area inset included — the home indicator sits in the same band. */
@media (max-width:899px){
  body:has(.buy-bar){padding-bottom:calc(var(--buy-bar-h) + env(safe-area-inset-bottom))}
  /* …and never covers what has keyboard focus (WCAG 2.4.11) at the foot of the page. */
  html:has(.buy-bar){scroll-padding-bottom:calc(var(--buy-bar-h) + env(safe-area-inset-bottom) + 8px)}
}

/* ── Markets (v1.3, design §2.6) ───────────────────────────────────────────────────────────────────────────────
   Every market control is a POST button (no `market=` link, D20). 44px targets on touch, codes never colour-only. */
.market-facet{margin-bottom:var(--s-2)}
.market-facet>summary{cursor:pointer;display:flex;align-items:center;gap:6px;font-weight:600}
.market-facet>summary svg:last-child{margin-left:auto;opacity:.6}
.market-facet[open]>summary svg:last-child{transform:rotate(180deg)}
.market-facet__opts{display:flex;flex-direction:column;gap:4px;margin-top:6px}
.market-facet__opt{display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:36px;padding:6px 10px;border:1px solid var(--border);border-radius:var(--r-sm,6px);background:transparent;color:var(--text);font:inherit;font-size:var(--fs-sm);text-align:left;cursor:pointer}
.market-facet__opt small{color:var(--text-muted)}
.market-facet__opt:hover{border-color:var(--accent)}
.market-facet__opt.is-current{border-color:var(--accent);background:rgb(var(--accent-rgb) / .12);font-weight:600}
.market-facet__opt:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (pointer:coarse){.market-facet__opt{min-height:44px}}

.chips .market-switch-form{display:inline-flex}
.market-chip{cursor:pointer;font:inherit;font-size:var(--fs-sm)}

.market-note{display:flex;flex-wrap:wrap;gap:var(--s-2) var(--s-3);align-items:center;justify-content:space-between;margin:0 0 var(--s-3);padding:var(--s-2) var(--s-3);border:1px dashed var(--border);border-radius:var(--r-md);font-size:var(--fs-sm);color:var(--text-2)}
.market-note p{margin:0;display:inline-flex;align-items:center;gap:6px}
.market-note__opts{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.market-note__opts .chip--btn{cursor:pointer;font:inherit;font-size:var(--fs-sm)}

.market-empty__list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.market-empty__list li{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:6px 0;border-bottom:1px solid var(--divider)}
.market-empty__list li:last-child{border-bottom:0}
.market-empty__list .market-switch-form{margin-left:auto}
.market-alt__code,.market-tag{display:inline-block;min-width:2.2em;padding:0 5px;border:1px solid var(--border);border-radius:4px;font-size:var(--fs-xs);font-weight:600;letter-spacing:.03em;text-align:center;color:var(--text-2)}
.market-tags{display:inline-flex;gap:4px;align-items:center}
.market-tags>span[aria-hidden]{display:inline-flex;gap:4px}
.market-source>summary{cursor:pointer;font-weight:600;color:var(--text-link)}
.market-source[open]>summary{margin-bottom:var(--s-2)}
.ticker__market a{color:inherit;text-decoration:underline}

/* ── Product photos (ADR-152) ────────────────────────────────────────────────────────────────────────────────────
   A photo box is always the same size whether or not there is a photo, so a grid never jumps while images load, and
   a catalogue that is half photographed does not look broken. Since ADR-167 the empty plate is the SAME WHITE as a
   photographed one and draws its own category (a memory module, a drive, a CPU) rather than one generic carton: two
   different background colours alternating down a grid was itself the thing that read as broken, and a line drawing
   of the right category can never be mistaken for a photograph of the actual unit. `contain` on a white plate: manufacturer shots are cut
   out on white and must not be cropped — the part has to stay recognisable, which is the whole point of the photo. */
.pcard__media{display:flex;align-items:center;justify-content:center;aspect-ratio:4/3;margin:-2px -2px 10px;border-radius:var(--r-md);background:#fff;overflow:hidden}
.pcard__media img{width:100%;height:100%;object-fit:contain;padding:8px}
.pcard__nophoto{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:#c2cad6;background:#fff}
.product__photo{display:block;width:100%;max-width:320px;aspect-ratio:4/3;object-fit:contain;background:#fff;border-radius:var(--r-md);padding:10px;margin-bottom:16px}
.product__photo--none{display:flex;align-items:center;justify-content:center;background:#fff;color:#c2cad6}
@media (forced-colors:active){.pcard__media,.product__photo{background:Canvas;border:1px solid CanvasText}}
