/* --- catalog: gapped grid of floating cards (4-up) --- */
/* outer gap: inset the grid by --gutter on top/sides so its edges line up
   with the navbar/hero gutter (bottom keeps its 40px rhythm) */
.catalog{ padding: var(--gutter) var(--gutter) 40px; }
.shop-head{
  padding: clamp(28px, 4vw, 52px) var(--gutter);
  text-align: center;
}
.shop-head h1{
  margin: 0;
  font: var(--font-display);
  font-size: clamp(2.2rem, 5vw, 4rem);
  line-height: 0.95;
  letter-spacing: -0.03em;
  text-transform: uppercase;
}

/* --- shop collections: each category renders as an editorial "chapter" —
   an indexed header (01 / RUN / count) then that collection's card grid.
   Separate from the generic .section-head used by cart/checkout/auth. --- */
.collection + .collection{ margin-top: clamp(36px, 5vw, 64px); }
.collection-head{
  display: flex; align-items: baseline; gap: 14px;
  padding-bottom: 12px; margin-bottom: clamp(16px, 2vw, 24px);
  border-bottom: 1px solid var(--line);
}
.collection-idx{
  font: var(--font-display); font-size: 1rem; color: var(--accent-text);
  font-variant-numeric: tabular-nums;
}
.collection-name{
  margin: 0; font: var(--font-display);
  font-size: clamp(1.3rem, 3vw, 2rem); letter-spacing: -0.02em; text-transform: uppercase;
}
.collection-count{
  margin-left: auto; align-self: center;
  font: var(--font-mono); font-size: 0.66rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted);
}

/* --- fade-up: banner, collection headers and cards rise + fade as they
   scroll into view (IntersectionObserver toggles .is-in). Deliberate scroll
   choreography, so it honors reduced-motion by rendering them at rest. --- */
.fade-up{
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.2,0.7,0.2,1);
}
.fade-up.is-in{ opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce){
  .fade-up{ opacity: 1; transform: none; transition: none; }
}

.section-head{
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding: 26px var(--gutter) 12px;
}
.section-head h2{
  margin: 0;
  font: var(--font-display);
  font-size: 1rem;
  letter-spacing: 0.01em;
  text-transform: uppercase;
}
.section-head .count{
  font: var(--font-mono);
  color: var(--muted);
}
/* cards float on the surface, separated by a small gap — no hairline grid.
   fixed 4-up on desktop, drops to 2-up on phones (see media query below) */
.grid{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.5vw, 16px);
}
@media (max-width: 720px){
  .grid{ grid-template-columns: repeat(2, 1fr); }
}
.card{
  display: flex;
  flex-direction: column;
  background: var(--surface);
  cursor: pointer;
}
.card:focus-visible{ outline: 1px solid var(--ink); outline-offset: -1px; }
.swatch{
  position: relative;
  aspect-ratio: 4 / 4;
  background: linear-gradient(135deg, var(--tint-a), var(--tint-b));
  overflow: hidden;
}
.swatch img{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 58%;
  opacity: 0.9;
  transform: translate(-50%, -50%);
  filter: invert(var(--logo-invert, 1)); /* default = light theme (inverted white->black logo) */
  transition: filter 0.25s ease;
}
:root[data-theme="light"] .swatch img{ --logo-invert: 1; }
:root[data-theme="dark"] .swatch img{ --logo-invert: 0; }
/* real product photo: full-bleed instead of the small centered logo watermark,
   and skip the invert filter (that's a white-mask-only trick) */
.swatch.has-photo img{
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  transform: none;
  object-fit: cover;
  object-position: center 80%;
  opacity: 1;
  filter: none;
}
/* placeholder image-swap demo: stands in for a second product angle until
   real photography exists — class toggled on hover, see setupTilt below */
.swatch.is-swap img{
  /* logo is a flat black/white mask, so recolor it from scratch (brightness(0)
     resets both themes to the same baseline) instead of layering onto the
     theme's own invert(), which would just cancel out to black again */
  filter: brightness(0) invert(1) sepia(1) saturate(20) hue-rotate(190deg) brightness(0.65);
}
/* the recolor above assumes a flat logo mask — on a real photo it crushes to a
   solid color block, so real-photo cards skip it and just hold steady on hover
   until a second angle exists to swap in */
.swatch.has-photo.is-swap img{ filter: none; }
.sold-out-badge{
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  font: var(--font-display);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #100F0A;
  background: var(--accent);
  padding: 4px 8px;
  transform: rotate(3deg);
}
.card-meta{
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 2px 14px;
}
.card-meta .name{
  font: var(--font-display);
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  transition: color 0.2s ease;
}
.card:hover .card-meta .name{ color: var(--accent-text); }
.card-meta .price{
  font: var(--font-mono);
  color: var(--muted);
  flex: none;
}
.hoverable:disabled,
.hoverable[aria-disabled="true"]{ cursor: not-allowed; opacity: 0.5; }
.hoverable:disabled::before,
.hoverable[aria-disabled="true"]::before{ transform: scaleX(0) !important; }
