/* ==========================================================================
   IRONBEASTS - PRODUCT CARDS AND GRIDS
   Ported from the static draft (new-theme-draft/assets/css/components.css).
   Loaded anywhere products are listed. Depends on the tokens in base.css.
   ========================================================================== */

/* ==========================================================================
   GRID
   ========================================================================== */
/* A tighter gap than the draft's, so the cards themselves take more of the
   row. */
.product-grid {
  display: grid;
  gap: clamp(.6rem, 1vw, .9rem);
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}

.product-grid--4 {
  grid-template-columns: repeat(4, 1fr);
}

@media (max-width: 1024px) {
  .product-grid--4 {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 959px) {
  .product-grid,
  .product-grid--4 {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* ==========================================================================
   CARD
   ========================================================================== */
.card {
  background: transparent;
}

/* Wraps the image and everything laid over it. The badges and the sold-out
   label centre against this rather than the whole card, which would put them
   halfway down the text below. */
.card__frame {
  position: relative;
}

/* Square corners -- the draft overrides its own rounded rule further down the
   file ("Square photos - no rounded corners").
   aspect-ratio holds the space before the image arrives, so the grid never
   jumps as products load. 5:6 matches the 1000x1200 the product photos are
   shot at, so `cover` has nothing to trim. */
.card__media {
  position: relative;
  display: block;
  aspect-ratio: 5 / 6;
  overflow: hidden;
  background: var(--surface-2);
}

.card__media .card__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: var(--surface);
}

/* Second photo sits on top of the first, revealed on hover -- or, on a touch
   screen, on the card a finger touched (`.is-touched`, set in header.js).
   Hidden by default.

   Slower on the way in than on the way out, and eased at both ends, so the
   swap reads as a crossfade rather than a flicker when the cursor crosses
   several cards. Promoted to its own layer so the fade is composited on the
   GPU instead of repainting a large photo every frame. */
.card__img--hover {
  opacity: 0;
  transition: opacity .5s cubic-bezier(.33, 0, .2, 1);
  will-change: opacity;
  transform: translateZ(0);
}

.card__frame.is-touched .has-hover .card__img--hover {
  opacity: 1;
  transition-duration: .65s;
}

/* Hover only where there is a real pointer: a touch screen fakes :hover on
   tap and would leave it stuck on whichever card was last tapped. On the
   frame, not the photo link: the sizes sit over the link, and with the hover
   on the link the second photo flipped back to the first the moment the
   pointer reached them. */
@media (hover: hover) {
  .card__frame:hover .has-hover .card__img--hover {
    opacity: 1;
    transition-duration: .65s;
  }
}

@media (prefers-reduced-motion: reduce) {
  .card__img--hover {
    transition: none;
  }
}

.card__body {
  padding-top: var(--sp-2);
}

.card__title {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-15);
  line-height: var(--lh-heading);
  text-transform: none;
  color: var(--text);
  margin-top: .25rem;
}

/* The price is the one thing that should read at a glance, so it carries the
   weight instead of the title. tabular-nums keeps the digits in line down the
   grid. */
.card__price {
  display: flex;
  align-items: baseline;
  gap: .4rem;
  margin-top: .3rem;
  font-size: var(--fs-14);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}

/*
 * WooCommerce prints the old price first and the new one second. `order` puts
 * what you pay on the left and what it was on the right, without reversing the
 * flow -- so the pair still aligns from the left like every other card.
 */
.card__price ins {
  order: 1;
  text-decoration: none;
  color: var(--text);
}

.card__price del {
  order: 2;
  color: var(--ib-red);
  font-weight: 500;
}

/* Sold out: a dark veil over the photo, so the card reads as unavailable at a
   glance without hiding what the product looks like. */
.card.is-soldout .card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: var(--veil-soldout);
  pointer-events: none;
}

/* Said across the middle of the image rather than tucked in the corner, so it
   cannot be mistaken for one of the badges. Set like the theme's other
   overlay labels: uppercase, widely spaced, no box. */
.card__soldout {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
  color: var(--ib-white);
  font-family: var(--font-display);
  line-height: var(--lh-snug);
  font-size: var(--fs-13);
  font-weight: 500;
  letter-spacing: var(--ls-9);
  text-transform: uppercase;
  text-indent: .28em;
  white-space: nowrap;
  pointer-events: none;
}

.card.is-soldout .card__title,
.card.is-soldout .card__price {
  color: var(--text-muted);
}

/* ==========================================================================
   BADGES
   ========================================================================== */
.card__badges {
  position: absolute;
  top: .7rem;
  left: .7rem;
  z-index: 2;
  display: flex;
  flex-direction: column;
  /* Each badge only as wide as its own text; a column flex box would otherwise
     stretch them all to match the widest. */
  align-items: flex-start;
  gap: .3rem;
}

.badge {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: var(--fs-10);
  letter-spacing: var(--ls-7);
  text-transform: uppercase;
  line-height: var(--lh-tight);
  padding: .42rem .6rem;
  color: var(--ib-ink);
  background: var(--badge-bg);
}

/* New keeps its blue, now declared in the palette rather than sitting as a
   loose hex here. White text on it is 5.2:1, which clears the 4.5 these small
   caps need.

   Pre-Order was a second, unrelated blue and takes gold instead -- red is
   spoken for by sale and stock-off, and two near-identical blues on the same
   card said nothing. Ink text, because white on gold is 2.4:1. */
.badge--new {
  color: var(--ib-white);
  background: var(--ib-blue);
}

.badge--pre {
  color: var(--ib-ink);
  background: var(--ib-gold);
}

/* Back in stock: ink, so it reads as news without taking New's blue or the
   reds that mean a price. */
.badge--restock {
  color: var(--ib-white);
  background: var(--ib-ink);
}

/* Pairs with the discount above it. A word rather than a number, so it is set
   slightly smaller. */
.badge--stockoff {
  color: var(--ib-white);
  background: var(--ib-red);
  font-size: var(--fs-8);
  letter-spacing: var(--ls-6);
  padding: .36rem .5rem;
}

.badge--sale {
  color: var(--ib-white);
  background: var(--ib-red);
}

.badge--soldout {
  color: var(--ib-white);
  background: var(--shade-4);
}

/* Cards are around half the width on a phone, so the badges come down with
   them. */
@media (max-width: 760px) {
  .card__badges {
    top: .45rem;
    left: .45rem;
    gap: .25rem;
  }

  .badge {
    font-size: var(--fs-8);
    letter-spacing: var(--ls-5);
    padding: .32rem .45rem;
  }

  .badge--stockoff {
    font-size: var(--fs-8);
    padding: .28rem .4rem;
  }

  .card__soldout {
    font-size: var(--fs-11);
    letter-spacing: var(--ls-8);
    text-indent: .22em;
  }
}

/* ==========================================================================
   QUICK ADD
   Pressing a size adds it to the cart. Where the sizes are depends on the
   screen:

   - With a mouse they appear over the foot of the photo when the card is
     pointed at, as a dark strip of chips. Nothing is shown until then.
   - A touch screen has nothing to point with. There the bag icon in the
     photo's top right corner -- the badges have the left -- opens a sheet at
     the bottom of the screen, where the sizes are large enough to press. A
     simple product has nothing to choose, so its icon adds it directly. The
     keyboard uses the icon too, since it cannot hover either.
   ========================================================================== */

/* A layer over the photo that takes no clicks of its own: the photo under it
   is the link to the product, and everything but the controls below has to
   keep reaching it. */
.card__quick {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
}

/* Forty pixels to press; what shows is the icon on a small square backing. */
.card__quick-toggle {
  position: absolute;
  top: .25rem;
  right: .25rem;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  color: var(--heading);
  pointer-events: auto;
}

/* The backing: the page's own surface, just larger than the icon, so it
   reads on any photo -- a dark hoodie as well as a white wall. Square, like
   the badges across from it and every button on the site; a disc read as
   borrowed from another design. No border, no shadow. */
.card__quick-toggle svg {
  box-sizing: content-box;
  padding: 5px;
  background: var(--surface);
}

/* Between the press and the cart's answer, for a simple product's icon. */
.card__quick-toggle.is-adding {
  opacity: .55;
}

/* The strip over the photo belongs to the mouse. On a touch screen it is not
   drawn at all -- its buttons are what the sheet is filled from. */
.card__sizes {
  display: none;
}

@media (hover: hover) {
  /* The hover does the opening, so the icon steps aside -- but not out of the
     page: it stays focusable and shows itself when the keyboard lands on it.
     It takes no pointer clicks while invisible, or that corner of the photo
     would stop being a link to the product. */
  .card__quick-toggle {
    opacity: 0;
    pointer-events: none;
  }

  .card__quick-toggle:focus-visible {
    opacity: 1;
  }

  .card__sizes {
    position: absolute;
    inset-inline: 0;
    bottom: 0;
    display: block;
    padding: .7rem .5rem;
    background: var(--shade-4);
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity var(--t-fast), transform var(--t-fast), visibility var(--t-fast);
    pointer-events: auto;
  }

  .card:hover .card__sizes {
    opacity: 1;
    visibility: visible;
    transform: none;
  }

  .card__sizes-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .35rem;
  }
}

/* ---- A size, on the strip and in the sheet -------------------------------- */
.card__size {
  font-family: var(--font-display);
  line-height: var(--lh-snug);
  font-weight: 600;
  letter-spacing: var(--ls-4);
  text-transform: uppercase;
  transition: background-color var(--t-fast), border-color var(--t-fast), color var(--t-fast), opacity var(--t-fast);
}

/* Not for a sold-out size: a disabled button still reports :hover, and it
   must not light up as if it could be pressed. */
.card__size:not(.is-out):hover,
.card__size:not(.is-out):focus-visible {
  background: var(--heading);
  border-color: var(--heading);
  color: var(--bg);
}

/* Sold out: still there, crossed out, so a shopper can see the size exists
   and is only gone for now. */
.card__size.is-out {
  text-decoration: line-through;
  cursor: not-allowed;
}

/* Between the press and the cart's answer. */
.card__size.is-adding {
  opacity: .55;
  cursor: progress;
}

/* On the strip: small white chips on the dark. */
.card__sizes .card__size {
  min-width: 40px;
  height: 36px;
  padding-inline: .55rem;
  background: var(--surface);
  color: var(--heading);
  border: 1px solid var(--surface);
  font-size: var(--fs-12);
}

.card__sizes .card__size.is-out {
  background: none;
  border-color: var(--on-dark-line-2);
  color: var(--on-dark-text);
}

/* ---- The sheet -------------------------------------------------------------
   Up from the bottom of the screen, the page dimmed behind it by header.js's
   overlay. Square, like everything else here. On a wide screen -- someone
   using the keyboard -- it is a column in the middle rather than a band the
   width of the monitor. */
.quick-sheet {
  position: fixed;
  inset-inline: 0;
  bottom: 0;
  z-index: var(--z-drawer);
  max-width: 520px;
  max-height: 80vh;
  margin-inline: auto;
  padding: var(--sp-5) var(--sp-5) calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--surface);
  box-shadow: var(--shadow-lg);
  visibility: hidden;
  transform: translateY(100%);
  transition: transform var(--t), visibility var(--t);
}

.quick-sheet.is-open {
  visibility: visible;
  transform: none;
}

.quick-sheet__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-4);
}

.quick-sheet__title {
  font-size: var(--fs-16);
  letter-spacing: var(--ls-2);
  margin: 0 0 var(--sp-1);
}

.quick-sheet__price {
  font-size: var(--fs-15);
  color: var(--text);
}

.quick-sheet__label {
  margin: var(--sp-5) 0 var(--sp-3);
  font-size: var(--fs-11);
  letter-spacing: var(--ls-7);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* As many equal cells as fit, so five sizes break into even rows. */
.quick-sheet__sizes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: var(--sp-2);
}

.quick-sheet__sizes .card__size {
  height: 48px;
  border: 1px solid var(--border);
  color: var(--heading);
  font-size: var(--fs-14);
}

.quick-sheet__sizes .card__size.is-out {
  background: var(--surface-2);
  color: var(--text-muted);
}

@media (prefers-reduced-motion: reduce) {
  .card__sizes,
  .quick-sheet {
    transition: none;
  }
}

/* ==========================================================================
   SECTION FURNITURE
   ========================================================================== */
.section-head-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-bottom: var(--sp-6);
}

.section-cta {
  text-align: center;
  margin-top: clamp(2rem, 4vw, 3.5rem);
}
