/* ==========================================================================
   Products page.
   Requires tokens.css, typography.css, layout.css, components.css, and
   sections.css (Careers, Certifications, and the call to action).
   ========================================================================== */


/* ---------- Hero ----------

   A Sand section that runs up behind the translucent header.
   Layers, back to front: aerial photo, grid, trailer drawing, text.
   The grid uses a Multiply blend, so its Dark Sand lines darken both the
   Sand and the photo beneath.

   Desktop (901px+)
   - Headline at the top, intro and button at the bottom, in columns 1–6.
   - The aerial photo fills columns 7–12, bleeding to the right frame line
     and running the full height (behind the header too).
   - The Dark Sand grid (52% of the photo's width) is centered on the visible
     hero and starts left of the photo, so it runs from the Sand onto the
     photo.
   - The trailer drawing (92.5% of the photo's width) overhangs the text
     column and is cut off by the hero's bottom edge, below the wheel hubs.
     Values measured from the design at 1440, where the photo is 670px wide.

   Tablet and mobile (up to 900px)
   - The text stacks above a full-width photo (square on mobile, 4:3 from
     600px). The grid is centered on the screen and rises 80px above the
     photo; the trailer is centered and cut off at the bottom the same way. */

.products-hero {
  position: relative;
  overflow: hidden;                           /* cuts off the trailer at the bottom edge */
  display: grid;
  grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
  column-gap: var(--gutter);
  margin-top: calc(-1 * var(--header-height));   /* runs up behind the header */
  padding: 0 var(--section-pad-x);           /* the photo runs top to bottom, so no vertical padding */
}

.products-hero__content {
  grid-column: 1 / -1;
  position: relative; z-index: 3;
  display: flex; flex-direction: column; justify-content: space-between;   /* fill: the gap grows with the photo */
  gap: var(--space-60);
  padding-block: calc(var(--header-height) + var(--space-60)) var(--space-120);
}
.products-hero__intro { display: grid; justify-items: start; gap: var(--space-40); }
.products-hero__intro p { max-width: var(--text-max); }   /* full width when stacked */

/* Photo, stacked */
.products-hero__media {
  position: relative;
  grid-column: 1 / -1;
  margin-inline: calc(-1 * var(--section-pad-x));   /* bleeds to both frame lines */
  aspect-ratio: 1;
}
.products-hero__photo {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.products-hero__grid {
  position: absolute; z-index: 1;
  top: calc(-1 * var(--space-80)); left: 50%;
  width: 50%; height: auto;
  transform: translateX(-50%);
  mix-blend-mode: multiply;
}
.products-hero__trailer {
  position: absolute; z-index: 2;
  left: 6%; bottom: 0;
  width: 88%; height: auto; max-width: none;
  transform: translateY(22.7%);              /* the bottom 22.7% of the drawing falls below the edge */
  pointer-events: none;
}

@media (min-width: 600px) {
  .products-hero__media { aspect-ratio: 4 / 3; }
}

@media (max-width: 900px) {
  .products-hero__grid { display: none; }   /* desktop only: removed once the text and photo stack */
}

@media (min-width: 901px) {
  .products-hero__content {
    grid-column: 1 / 7;
    gap: var(--space-120);
    padding-block: calc(var(--header-height) + var(--space-120)) var(--space-60);
  }
  .products-hero__intro p { max-width: min(440px, 70%); }   /* about 4 columns, as in the design; clear of the grid on narrower desktops */
  .products-hero__media {
    grid-column: 7 / -1;
    margin-inline: 0 calc(-1 * var(--section-pad-x));   /* bleeds to the right frame line only */
    aspect-ratio: auto;                                  /* as tall as the text column */
  }
  .products-hero__grid {
    top: calc(50% + var(--header-height) / 2);           /* centered on the part below the header */
    left: -27.6%;
    width: 52.2%;
    transform: translateY(-50%);
  }
  .products-hero__trailer { left: -11.2%; width: 92.5%; }
}


/* ---------- Product groups ----------

   Each group: a Sand tag, the heading, and a list of products that expand to
   show a description, beside a Mid Gray card holding a render and a caption
   pill. Groups are 120px apart.

   Desktop: text in columns 1–6 (no wider than 550px, as in the design); the
   card in columns 7–12.
   3-column tablet: text in two columns, the card in the third.
   From the 3-column tablet up, the card stays pinned 20px below the header
   until its group's text has scrolled past.
   Below that: tag, heading, card, then the list, all in one column no wider
   than 540px, with 24px between them. */

.products { display: grid; gap: var(--space-120); }

.product-group { display: grid; align-items: start; scroll-margin-top: var(--space-40); }   /* links from the homepage land 40px below the header */
.product-group .tag { justify-self: start; }
.product-group h2 { margin-top: var(--space-40); }

/* Card: Mid Gray, in the design's proportions (624 × 594). The render sits
   on a Smoke panel inset 20px, fitted without cropping, with the caption
   pill below. Wide renders (the TPQ-37 cabinet) get extra side padding so
   they don't feel oversized. */
.product-figure {
  display: grid; grid-template-rows: minmax(0, 1fr) auto;
  justify-items: center; gap: var(--space-20);
  aspect-ratio: 624 / 594;
  margin: 0;
  padding: var(--space-20);
  background: var(--color-mid-gray);
}
.product-figure img {
  width: 100%; height: 100%;
  padding: var(--space-24);
  object-fit: contain;
  background: var(--color-smoke);
}
.product-figure--wide img { padding-inline: 12%; }

@media (max-width: 810px) {
  .product-group { max-width: var(--text-max); }
  .product-group__text { display: contents; }   /* lets the card sit between the heading and the list */
  .product-group h2 { margin-top: var(--space-24); }
  .product-figure { order: 1; margin-top: var(--space-24); }
  .product-list { order: 2; margin-top: calc(var(--space-24) - 2 * var(--space-20)); }   /* 24px above the first name (rows add 40px) */
}

/* Pinned card: the card can only stay pinned while its group's text is
   taller than the card, so the text column is always at least the card's
   height plus 240px. Short groups (Range, Tracking) then pin for 240px of
   scrolling, like the longer ones. --card-h is the card's height, worked
   out from the group's width (cqi) and the card's proportions. */
@media (min-width: 811px) {
  .product-group {
    container-type: inline-size;
    grid-template-columns: repeat(var(--columns), minmax(0, 1fr));
    column-gap: var(--gutter);
  }
  .product-group__text {
    --card-h: calc((100cqi - 2 * var(--gutter)) / 3 * 594 / 624);   /* one of three columns */
    min-height: calc(var(--card-h) + 240px);
  }
  .product-group__text { grid-column: 1 / 3; }
  .product-figure {
    grid-column: 3 / -1;
    position: sticky; top: calc(var(--header-height) + var(--space-20));
  }
}

@media (min-width: 901px) {
  .product-group__text {
    --card-h: calc((100cqi - var(--gutter)) / 2 * 594 / 624);       /* half the group */
    grid-column: 1 / 7; max-width: 550px;
  }
  .product-figure { grid-column: 7 / -1; }
}


/* ---------- Product list ----------

   Each product is a row with a line under it: the name (20px Medium) on the left and
   "See More" on the right. The whole row is a button; it expands the row to
   show the description, and the label changes to "Close". site.js toggles
   aria-expanded on the button and .is-open on the row.

   Spacing: 40px above each name (20px row padding + 20px button padding),
   20px below it, and 20px below the description.

   Without JavaScript every description is shown and the labels are hidden. */

.product-list { margin: 0; padding: 0; list-style: none; }

.product-item {
  padding-top: var(--space-20);
  border-bottom: var(--line-width) solid var(--color-line);
}
.product-item__heading { font: inherit; }

.product-item__toggle {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start;
  column-gap: var(--space-40);
  width: 100%;
  padding: var(--space-20) 0;
  border: 0; background: none; color: inherit;
  font: inherit; text-align: left;
  cursor: pointer;
}

/* List name style: 20px Medium, 120% line height, −1% letter spacing (tokens.css). */
.product-item__title {
  font-family: var(--font-sans);
  font-size: var(--text-item-size);
  font-weight: var(--text-item-weight);
  line-height: var(--text-item-leading);
  letter-spacing: var(--text-item-tracking);
}

/* "See More" / "Close". Both labels share one grid cell, so the link keeps
   the same width in both states and the icon stays put. The link is 22px
   tall; the margin centers it on the first line of the name. */
.product-item__action {
  display: grid; grid-template-columns: auto 23px; justify-content: space-between;
  column-gap: var(--space-8);
  margin-top: calc(var(--text-item-size) * var(--text-item-leading) / 2 - 11px);
  margin-right: var(--space-8);              /* room for the hover slide, so the link's footprint never changes */
  transition: padding-right .25s cubic-bezier(.2, .7, .3, 1), margin-right .25s cubic-bezier(.2, .7, .3, 1);
}
.product-item__more,
.product-item__close { grid-area: 1 / 1; }
.product-item__action::after { grid-area: 1 / 2; align-self: center; }
.product-item__close { visibility: hidden; }
.is-open .product-item__more { visibility: hidden; }
.is-open .product-item__close { visibility: visible; }

/* Icon: the shared arrow, or an X when open. The X gets its own 14px box,
   right-aligned in the arrow's space, so the label keeps its width. */
.product-item__action::after {
  content: "";
  flex: none;
  justify-self: end;
  width: 23px; height: 14px;
  background: currentColor;
  -webkit-mask: url("../assets/icons/icon-arrow.svg") center / contain no-repeat;
          mask: url("../assets/icons/icon-arrow.svg") center / contain no-repeat;
  transition: transform .25s cubic-bezier(.2, .7, .3, 1);
}
.is-open .product-item__action::after {
  width: 14px;
  -webkit-mask-image: url("../assets/icons/icon-close.svg");
          mask-image: url("../assets/icons/icon-close.svg");
}

/* Hover and keyboard focus on the row: the arrow slides and the underline
   follows it, as on other text links. When open, the X stays still. */
.product-item__toggle:hover .product-item__action,
.product-item__toggle:focus-visible .product-item__action { padding-right: var(--space-8); margin-right: 0; }
.product-item__toggle:hover .product-item__action::after,
.product-item__toggle:focus-visible .product-item__action::after { transform: translateX(8px); }
.is-open .product-item__toggle:hover .product-item__action,
.is-open .product-item__toggle:focus-visible .product-item__action { padding-right: 0; margin-right: var(--space-8); }
.is-open .product-item__toggle:hover .product-item__action::after,
.is-open .product-item__toggle:focus-visible .product-item__action::after { transform: none; }

/* Description: collapses to zero height and is hidden from assistive tech
   while closed. */
.product-item__panel {
  display: grid; grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows .3s ease, visibility 0s linear .3s;
}
.is-open .product-item__panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows .3s ease;
}
.product-item__content { min-height: 0; overflow: hidden; }
.product-item__content p { padding-bottom: var(--space-20); max-width: var(--text-max); }

/* Closing on its own after scrolling off the top: no animation (site.js) */
.product-item.is-instant .product-item__panel { transition: none; }

/* No JavaScript: descriptions shown, labels hidden. */
.no-js .product-item__panel { grid-template-rows: 1fr; visibility: visible; }
.no-js .product-item__action { display: none; }
.no-js .product-item__toggle { cursor: default; }

@media (prefers-reduced-motion: reduce) {
  .product-item__panel,
  .is-open .product-item__panel,
  .product-item__action,
  .product-item__action::after { transition: none; }
}
