/* catalogue.css — product listing: cards, swatches, qty stepper, filters
   (split from storefront.css, move-only). */

.detail-photo { aspect-ratio:1/1; background:var(--kraft); object-fit:contain; width:100%; border-radius:var(--radius-lg); }

/* product cards read as clickable/buyable */
.card--product { transition:transform .15s, box-shadow .15s; }
.card--product:hover { transform:translateY(-3px); box-shadow:0 12px 26px rgba(0,0,0,.13); }

/* card media + description overlay */
.card__media { position:relative; background:var(--green-tint); }
.card__desc { position:absolute; inset:0; padding:1rem; overflow:auto; font-size:.85rem;
  line-height:1.45; color:#fff;
  background:linear-gradient(rgba(43,43,40,.78), rgba(43,43,40,.92));
  opacity:0; visibility:hidden; transition:opacity .2s; }
.card__desc.on { opacity:1; visibility:visible; }
@media (hover:hover) { .card__media:hover .card__desc { opacity:1; visibility:visible; } }
.card__info-btn { position:absolute; top:.6rem; right:.6rem; z-index:2; width:28px; height:28px;
  border:0; border-radius:999px; background:rgba(250,247,242,.92); color:var(--green);
  font-family:var(--font-head); font-weight:700; cursor:pointer; box-shadow:var(--shadow); }

/* I-2 (reviewer, 2026-07-26): on a merged card, the title itself follows
   the selected handle (the two live names differ in length -- « Sac à
   Poignées Plates » vs « Sac à Poignées Torsadées »); a reserved 2-line box
   keeps the card body from reflowing when a pill tap swaps the text. `em`
   units so it scales with the mobile font-size override below. */
.card__title { display:block; line-height:1.25; min-height:2.5em; }

/* color swatches */
.swatch-row { display:flex; align-items:center; gap:.45rem; }
.swatch { width:26px; height:26px; border-radius:6px; border:2px solid transparent;
  cursor:pointer; padding:0; box-shadow:inset 0 0 0 2px #fff; }
.swatch.on { border-color:var(--green); }
.swatch--marron { background:#9a6a38; }
.swatch--blanc { background:#f6f1e7; box-shadow:inset 0 0 0 2px #fff, inset 0 0 0 3px var(--line); }
.swatch--noir { background:#2b2b28; }
.swatch--autre { background:var(--kraft); }
.swatch-hint { font-size:.8rem; color:var(--muted); font-weight:700; text-transform:capitalize; }

/* handle selector (poignées torsadées / plates / sans poignée) -- same
   on/off idiom as .swatch above, but a text pill: a handle isn't a colour,
   so it needs a legible French label, and (client note 5, 2026-07-25)
   >=44px touch target rather than the smaller swatch dot. */
.handle-row { display:flex; align-items:center; gap:.4rem; flex-wrap:wrap; }
.handle-btn { min-height:44px; padding:.4rem .85rem; border-radius:999px;
  border:2px solid var(--line); background:#fff; color:var(--ink);
  font-family:var(--font-head); font-weight:700; font-size:.8rem; cursor:pointer; }
.handle-btn.on { border-color:var(--green); background:var(--green-tint); color:#3f7a12; }
@media (max-width:640px) {
  .handle-btn { font-size:.74rem; padding:.35rem .7rem; }
}

/* quantity stepper */
.qty-stepper { display:inline-flex; align-items:center; border:1px solid var(--line);
  border-radius:999px; overflow:hidden; }
.qty-stepper button { width:36px; height:36px; border:0; background:var(--green-tint);
  color:var(--ink); font-size:1.1rem; font-weight:700; cursor:pointer; }
.qty-stepper input { width:64px; border:0; text-align:center; font-family:var(--font-body);
  font-size:.95rem; -moz-appearance:textfield; }
.qty-stepper input::-webkit-outer-spin-button,
.qty-stepper input::-webkit-inner-spin-button { -webkit-appearance:none; margin:0; }

/* personalization pill */
.custom-pill { display:inline-flex; align-items:center; gap:.45rem; font-size:.85rem;
  font-weight:700; color:#3f7a12; background:var(--green-tint); padding:.35rem .7rem;
  border-radius:999px; cursor:pointer; align-self:flex-start; }

/* pack-of-1000 suffix next to quantity steppers */
.qty-pack { font-size:.85rem; font-weight:700; color:var(--muted); white-space:nowrap; }
.qty-hint { font-size:.72rem; color:var(--muted); }
.qty-trash { border:0; background:none; color:var(--muted); cursor:pointer; padding:.35rem;
  border-radius:8px; }
.qty-trash svg { width:20px; height:20px; fill:none; stroke:currentColor; stroke-width:1.7;
  stroke-linecap:round; stroke-linejoin:round; }
.qty-trash:hover { color:var(--action); background:var(--green-tint); }

/* catalogue header band + group filters */
.catalogue-head { background:var(--kraft); border-bottom:1px solid var(--line);
  padding:2rem 0 1.5rem; }
.catalogue-head .wrap { display:flex; flex-direction:column; align-items:flex-start;
  gap:.4rem; }
.catalogue-head__title { display:inline-flex; align-items:center; gap:.6rem; margin:0;
  font-size:clamp(1.6rem,3.4vw,2.4rem); color:var(--green); }
.catalogue-head__title svg { width:1.1em; height:1.1em; fill:currentColor; }
.catalogue-head__sub { margin:0; color:var(--muted); font-size:1rem; }
.catalogue-head__count { font-family:var(--font-head); font-weight:700; font-size:.78rem;
  color:#3f7a12; background:var(--green-tint); padding:.2rem .6rem; border-radius:999px; }

.filterbar { position:sticky; top:73px; z-index:20; background:var(--paper);
  border-bottom:1px solid var(--line); }
.filterbar__inner { display:flex; gap:.6rem; padding-top:.8rem; padding-bottom:.8rem;
  overflow-x:auto; scrollbar-width:none; }
.filterbar__inner::-webkit-scrollbar { display:none; }
.filter-btn { display:inline-flex; align-items:center; gap:.45rem; white-space:nowrap;
  font-family:var(--font-head); font-weight:700; font-size:.95rem; padding:.6rem 1.1rem;
  border-radius:999px; border:2px solid var(--green); color:var(--green); background:#fff;
  transition:transform .12s, background .12s, color .12s; }
.filter-btn svg { width:20px; height:20px; fill:currentColor; }
.filter-btn:hover { transform:translateY(-1px); background:var(--green-tint); }
.filter-btn.on { background:var(--green); color:#fff; }
@media (max-width:640px) {
  .catalogue-head { padding:1.5rem 0 1.1rem; }
  .filter-btn { font-size:.9rem; padding:.55rem .9rem; }
}

/* --- Mobile: two product cards per row (was one) ---
   Scoped to .grid--cards so the cart's own stepper/controls are untouched.
   At 375px this gives ~163px per card (~131px inner), so the stepper is
   tightened from 136px to 112px to fit with room to spare. */
@media (max-width:640px) {
  .grid--cards { grid-template-columns:repeat(2, 1fr); }
  .grid--cards .card__body { padding:.7rem; gap:.35rem; }
  .grid--cards .card__body strong { font-size:.95rem; }
  .grid--cards .price-tag { font-size:.85rem; }
  .grid--cards .qty-stepper button { width:34px; }
  .grid--cards .qty-stepper input { width:44px; font-size:.9rem; }
  .grid--cards .swatch { width:22px; height:22px; }
  .grid--cards .swatch-hint { font-size:.72rem; }
  .grid--cards .custom-pill { font-size:.78rem; }
  .grid--cards .btn--action { font-size:.85rem; }
}

/* --- Personalization warning overlay (_size_card.html) ---
   Owner instruction (2026-07-26): the blocking « Personnalisation à partir de
   N sacs » warning is stated OVER the page, not appended inline below the
   fold where the tap that triggered it can't see it. z-index 60 clears the
   cart FAB (50), the offcanvas (40) and the sticky header (30), and stays
   under the first-paint loading screen (1000) so it can never cover it.
   `position:fixed` + `inset:0` means the dialog holds the viewport centre
   even if the page behind it scrolls; `overscroll-behavior:contain` keeps a
   scroll gesture inside the box from chaining to the page underneath. */
.perso-modal { position:fixed; inset:0; z-index:60; display:flex;
  align-items:center; justify-content:center; padding:1rem;
  background:rgba(43,43,40,.5); }
.perso-modal__box { width:100%; max-width:26rem; max-height:calc(100dvh - 2rem);
  overflow:auto; overscroll-behavior:contain; background:#fff;
  border:1px solid var(--line); border-radius:var(--radius); padding:1.15rem;
  box-shadow:0 18px 48px rgba(0,0,0,.28); display:flex;
  flex-direction:column; gap:.7rem; }
.perso-modal__title { margin:0; font-weight:800; font-size:1.05rem;
  color:var(--ink); }
/* The card grid shrinks its buttons at 640px (two cards per row); the dialog
   is full-width at any size, so it opts out of that tightening. */
@media (max-width:640px) {
  .grid--cards .perso-modal .btn--action,
  .grid--cards .perso-modal .btn--ghost { font-size:1rem; }
}
