/* ==========================================================================
   Foshan Select — Products page gallery
   --------------------------------------------------------------------------
   Loaded ONLY on the English and Chinese Products templates (see the
   wp_enqueue_scripts call at the top of page-products.php and
   templates/zh/products.php). Every selector is namespaced under
   .product-collection / .product-gallery* so no other page is affected.

   Layout: 1 main image (16:9) above a 3-up thumbnail row (4:3).
   The image assets are cut to exactly those ratios, so object-fit:cover
   neither crops nor letterboxes - it only guards future uploads.

   Visual language follows the rest of the site: square corners (the theme
   uses no border-radius anywhere), --line hairline borders, and the same
   0 18px 40px rgba(29,33,29,.08) shadow already used in styles.css.
   ========================================================================== */

/* Gallery column -------------------------------------------------------- */
.product-collection__grid .product-gallery {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0; /* lets the column shrink inside the CSS grid */
}

/* Preserve the alternating image/text rhythm the original .media-frame had. */
.product-collection:nth-of-type(even) .product-collection__grid .product-gallery {
  order: 2;
}

/* The base grid is 1.15fr .85fr. When the gallery moves to the second cell it
   inherited the narrow .85fr track, so alternating sections rendered the
   gallery at 513px vs 695px - a 35% swing down the page. Mirroring the track
   widths keeps the gallery identical in both directions. */
.product-collection:nth-of-type(even) .product-collection__grid {
  grid-template-columns: .85fr 1.15fr;
}

/* Main hero image ------------------------------------------------------- */
.product-gallery-main {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--line);
  background: var(--cream);
  box-shadow: 0 18px 40px rgba(29, 33, 29, .08);
}

.product-gallery-main img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center;
  transition: transform .45s ease;
}

.product-gallery-main:hover img {
  transform: scale(1.035);
}

/* Thumbnail row --------------------------------------------------------- */
.product-gallery-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.product-gallery-item {
  position: relative;
  margin: 0; /* reset default <figure> margin */
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--line);
  background: var(--cream);
}

.product-gallery-item img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: center;
  transition: transform .45s ease;
}

.product-gallery-item:hover img {
  transform: scale(1.05);
}

/* Caption overlay ------------------------------------------------------- */
.product-gallery-item figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 18px 9px 7px;
  font-size: 11px;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: .05em;
  color: #fff;
  background: linear-gradient(180deg, transparent, rgba(20, 22, 19, .78));
  pointer-events: none;
}

/* Dark section variant -------------------------------------------------- */
.product-collection--dark .product-gallery-main,
.product-collection--dark .product-gallery-item {
  border-color: rgba(255, 255, 255, .14);
  background: rgba(255, 255, 255, .04);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .28);
}

/* Specification list ---------------------------------------------------- */
/* The default browser disc bullet was the last stock element on the page.
   A hairline rule in --sage matches the restrained editorial tone. */
.product-collection__grid ul {
  list-style: none;
  padding-left: 0;
}

.product-collection__grid ul li {
  position: relative;
  padding-left: 20px;
}

.product-collection__grid ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .68em;
  width: 8px;
  height: 1px;
  background: var(--sage);
}

.product-collection--dark .product-collection__grid ul li::before {
  background: rgba(255, 255, 255, .45);
}

/* Responsive ------------------------------------------------------------ */
@media (max-width: 980px) {
  /* Text drops below the gallery, so cancel both the alternating order and
     the mirrored track widths, matching what styles.css does at this width. */
  .product-collection:nth-of-type(even) .product-collection__grid .product-gallery {
    order: 0;
  }
  .product-collection:nth-of-type(even) .product-collection__grid {
    grid-template-columns: 1fr;
  }
  .product-collection__grid .product-gallery,
  .product-gallery-grid {
    gap: 10px;
  }
}

@media (max-width: 640px) {
  /* Thumbnails flow automatically: three across on a normal phone,
     wrapping gracefully on very narrow viewports. */
  .product-gallery-grid {
    grid-template-columns: repeat(auto-fit, minmax(90px, 1fr));
    gap: 8px;
  }
  .product-gallery-item figcaption {
    padding: 12px 6px 5px;
    font-size: 10px;
    line-height: 1.2;
    letter-spacing: .02em;
  }
}

/* Accessibility --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .product-gallery-main img,
  .product-gallery-item img {
    transition: none;
  }
  .product-gallery-main:hover img,
  .product-gallery-item:hover img {
    transform: none;
  }
}

/* ---------------------------------------------------------------------------
   Category figures, source note and sub-category tags
   The text column previously ran a four-line bullet list and stopped, which
   left a buyer no way to see the scale behind a category or what it actually
   covers. The figure strip carries the industry numbers with their scope
   spelled out; the tag row names the sub-categories.
   Whole-House Customization has no published share figures, so it states
   accreditation instead - same format, same visual weight, and the source
   line says plainly which it is.
   --------------------------------------------------------------------------- */
.pc-figures{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1px;
  background:var(--line);
  border:1px solid var(--line);
  margin:22px 0 0;
}
.pc-figures > div{background:var(--paper);padding:18px 18px 20px;min-width:0}
.pc-figures .v{display:block;font-family:Georgia,"Noto Serif CJK SC",serif;font-weight:400;
  font-size:26px;line-height:1.25;color:var(--gold)}
.pc-figures .k{display:block;font-size:12px;font-weight:600;line-height:1.5;color:var(--ink);margin-top:6px}
.pc-figures .m{display:block;font-size:11px;line-height:1.5;color:#9a958a;margin-top:4px}

.product-collection--dark .pc-figures{background:rgba(255,255,255,.14);border-color:rgba(255,255,255,.14)}
.product-collection--dark .pc-figures > div{background:var(--ink)}
.product-collection--dark .pc-figures .k{color:#fff}
.product-collection--dark .pc-figures .m{color:#8d897f}

.pc-src{display:block;font-size:11px;line-height:1.6;color:#9a958a;margin-top:12px}
.product-collection--dark .pc-src{color:#7d796f}

.pc-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:20px}
.pc-tags span{font-size:12px;line-height:1;color:var(--muted);border:1px solid var(--line);padding:7px 10px}
.product-collection--dark .pc-tags span{color:#bbb7ad;border-color:rgba(255,255,255,.16)}

/* Added with the 2026-08 products-page split: the collection copy block now
   carries two links - a button through to the category's own detail page,
   and the original "Request Details" contact link - shown side by side.
   Given z-index:2 (below) so both stay independently clickable above the
   whole-card overlay link added at the same time. */
.pc-links{position:relative;z-index:2;display:flex;flex-wrap:wrap;align-items:center;gap:24px;margin-top:22px}

/* ---------------------------------------------------------------------------
   Whole-card entry point to the category's detail page.
   A client asked for the entrance to feel less easy to miss - clicking
   anywhere on a category's card (not just a small text link) should open its
   detail page. .pc-card-overlay is an invisible link stretched over the
   entire card (a standard "stretched link" pattern); .pc-links sits above it
   via z-index so "Request Details" - the one link with a different
   destination - keeps working on its own. The main image's existing
   hover-zoom (above) already implied the card was interactive before it
   actually did anything on click; broadening its trigger to "hover anywhere
   on the card" ties that cue to what now actually happens.
   --------------------------------------------------------------------------- */
.product-collection__grid{position:relative}
.pc-card-overlay{position:absolute;inset:0;z-index:1}
.product-collection__grid:hover .product-gallery-main img{transform:scale(1.035)}

@media(max-width:640px){
  .pc-figures{grid-template-columns:1fr}
  .pc-links{gap:14px 24px}
}

/* ---------------------------------------------------------------------------
   Product range - the full matrix beneath a category's gallery
   Twenty-two products laid out flat in a six-column seam grid read as a
   density problem rather than a catalogue, and sat oddly against the airier
   rhythm of the rest of the site. They divide naturally into four groups of
   three to eight, which is few enough to give each card room: 24-28px between
   cards instead of a 1px seam, and the caption below the image rather than
   boxed with it.
   The existing gallery, figures and tags above are untouched; this follows them.
   --------------------------------------------------------------------------- */
.product-range{
  margin-top:64px;
  padding-top:56px;
  border-top:1px solid var(--line);
}
.product-collection--dark .product-range{border-top-color:rgba(255,255,255,.16)}

.range-group + .range-group{margin-top:52px}

.range-group__title{
  display:flex;
  align-items:baseline;
  gap:12px;
  margin:0 0 20px;
  padding-bottom:12px;
  border-bottom:1px solid var(--line);
  font-family:inherit;
  font-size:13px;
  font-weight:600;
  line-height:1.5;
  letter-spacing:.02em;
  text-transform:none;
  color:var(--ink);
}
.range-group__title span{
  font-size:11px;
  font-weight:400;
  letter-spacing:.14em;
  color:#9a958a;
}
.product-collection--dark .range-group__title{color:#fff;border-bottom-color:rgba(255,255,255,.16)}
.product-collection--dark .range-group__title span{color:#8d897f}

.range-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:28px 24px;
}
.range-item{margin:0;min-width:0}
.range-item img{
  width:100%;
  aspect-ratio:4 / 3;
  object-fit:cover;
  display:block;
  background:var(--cream);
  border:1px solid var(--line);
}
.range-item figcaption{
  margin-top:12px;
  font-size:13px;
  line-height:1.55;
  color:var(--muted);
}
.product-collection--dark .range-item img{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.14)}
.product-collection--dark .range-item figcaption{color:#bbb7ad}

@media(max-width:1100px){
  .range-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media(max-width:760px){
  .product-range{margin-top:48px;padding-top:44px}
  .range-group + .range-group{margin-top:40px}
  .range-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:24px 18px}
}

/* ---------------------------------------------------------------------------
   Range: catalogue pages, style notes, video slots
   Lighting arrives as catalogue spreads rather than loose product shots, so
   its pages run one per row at full width - a spread reduced to a quarter of
   the row would be unreadable, which is the whole point of showing it.
   Whole-house customisation carries a material note per style, taken from the
   deck slide that style came from.
   Video slots reserve a 16:9 frame each. An empty slot renders as a labelled
   placeholder, so the layout is final before any footage exists.
   --------------------------------------------------------------------------- */
.range-group__note{
  margin:-8px 0 18px;
  max-width:760px;
  font-size:13px;
  line-height:1.7;
  color:var(--muted);
}
.product-collection--dark .range-group__note{color:#bbb7ad}

.range-pages{display:grid;gap:44px}
.range-page{margin:0}
.range-page img{
  width:100%;
  height:auto;
  display:block;
  border:1px solid var(--line);
  background:#fff;
}
.range-page figcaption{
  margin-top:12px;
  font-size:13px;
  line-height:1.55;
  color:var(--muted);
}
.product-collection--dark .range-page img{border-color:rgba(255,255,255,.14)}
.product-collection--dark .range-page figcaption{color:#bbb7ad}

.range-videos{margin-top:52px}
.video-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:28px 24px}
/* Five clips read better as 3+2 than as an uneven pair of rows. */
@media(max-width:1100px){.video-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.video-slot{margin:0;min-width:0}
.video-slot video,
.video-slot__placeholder{object-fit:cover;
  width:100%;
  aspect-ratio:16 / 9;
  display:block;
  background:var(--cream);
  border:1px solid var(--line);
}
.video-slot__placeholder{
  display:grid;
  place-items:center;
  background:repeating-linear-gradient(135deg,#f4f1e9,#f4f1e9 10px,#efece2 10px,#efece2 20px);
}
.video-slot__placeholder span{
  width:38px;height:38px;border-radius:50%;
  border:1px solid var(--gold);
  position:relative;
}
.video-slot__placeholder span::after{
  content:"";position:absolute;top:50%;left:54%;transform:translate(-50%,-50%);
  border-left:11px solid var(--gold);
  border-top:7px solid transparent;
  border-bottom:7px solid transparent;
}
.video-slot figcaption{margin-top:12px;font-size:13px;line-height:1.55;color:var(--muted)}
.product-collection--dark .video-slot video,
.product-collection--dark .video-slot__placeholder{border-color:rgba(255,255,255,.14)}
.product-collection--dark .video-slot__placeholder{
  background:repeating-linear-gradient(135deg,#22251f,#22251f 10px,#1d211d 10px,#1d211d 20px);
}
.product-collection--dark .video-slot figcaption{color:#bbb7ad}

@media(max-width:760px){
  .range-pages{gap:32px}
  .video-grid{grid-template-columns:minmax(0,1fr);gap:24px}
  .range-videos{margin-top:40px}
}

/* ---------------------------------------------------------------------------
   Export packing and certification
   Both sit at the foot of the Products page, after the five categories,
   because neither belongs to any one of them.
   Packing steps are numbered - the source is a sequence, and showing it as an
   unordered grid would lose the point. Certificates are portrait documents, so
   they use object-fit:contain on a cream field rather than being cropped;
   cropping a certificate removes the very thing being shown.
   --------------------------------------------------------------------------- */
.packing-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:32px 24px;
  margin-top:36px;
}
.packing-step{margin:0;min-width:0}
.packing-step__no{
  display:block;
  margin-bottom:9px;
  font-size:10px;
  font-weight:700;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--gold);
}
/* Step photographs are diagrams as much as pictures - cropping one can remove
   the very edge strip or belt the caption is describing. Contained, not
   cropped, on a fixed frame so the grid stays even. */
.packing-step img{
  width:100%;
  aspect-ratio:4 / 3;
  object-fit:contain;
  display:block;
  background:#fff;
  border:1px solid var(--line);
}
.packing-step figcaption{
  margin-top:11px;
  font-size:13px;
  line-height:1.6;
  color:var(--muted);
}

.cert-grid{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  gap:26px 22px;
  margin-top:36px;
}
.cert-item{margin:0;min-width:0}
/* Certificates keep their own proportions. Forcing 3:4 on documents that are
   not 3:4 either letterboxes them or, worse, crops the seal or the number -
   the two things anyone actually reads. */
.cert-item img{
  width:100%;
  height:auto;
  display:block;
  padding:10px;
  background:#fff;
  border:1px solid var(--line);
}
.cert-grid{align-items:start}
.cert-item figcaption{
  margin-top:11px;
  font-size:13px;
  line-height:1.55;
  color:var(--muted);
}
.cert-pending{
  margin:26px 0 0;
  padding:18px 20px;
  border:1px dashed #c3bda9;
  max-width:760px;
  font-size:13px;
  line-height:1.7;
  color:#8a8577;
}

@media(max-width:1100px){
  .cert-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media(max-width:860px){
  .packing-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:760px){
  .cert-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:22px 16px}
}
@media(max-width:520px){
  .packing-grid{grid-template-columns:minmax(0,1fr)}
}

/* Packing runs as two stages - wrapping a cabinet, then palletising - because
   the source procedure keeps them apart and merging them lost the pallet
   steps entirely. Step numbers continue across both. */
/* Slide 11 of the deck: certificate left, production line right, at the
   slide's own 41:59 split. Held to that split neither image is asked to render
   wider than its source - 819px and 1194px against 476px and 684px in a
   1200px container - which is why they read cleanly here and did not when each
   ran full width. Below 760px there is no width left to split, so they stack. */
.standards-pair{
  display:grid;
  grid-template-columns:minmax(0,41fr) minmax(0,59fr);
  gap:28px 40px;
  align-items:start;
  margin:0;
}
.standards-item{margin:0;min-width:0}
.standards-item img{
  width:100%;
  height:auto;
  display:block;
  background:#fff;
  border:1px solid var(--line);
}
.standards-item figcaption{
  margin-top:12px;
  font-size:13px;
  line-height:1.55;
  color:var(--muted);
}
.product-collection--dark .standards-item img{border-color:rgba(255,255,255,.14)}
.product-collection--dark .standards-item figcaption{color:#bbb7ad}
@media(max-width:760px){
  .standards-pair{grid-template-columns:minmax(0,1fr);gap:26px}
}

.packing-stage + .packing-stage{margin-top:48px}
.packing-stage__title{
  display:flex;align-items:baseline;gap:12px;
  margin:0 0 16px;padding-bottom:12px;border-bottom:1px solid var(--line);
  font-family:inherit;font-size:13px;font-weight:600;line-height:1.5;
  letter-spacing:.02em;text-transform:none;color:var(--ink);
}
.packing-stage__title span{font-size:11px;font-weight:400;letter-spacing:.14em;color:#9a958a}
.packing-stage__note{margin:0 0 20px;max-width:760px;font-size:13px;line-height:1.75;color:var(--muted)}
.packing-stage .packing-grid{margin-top:0}

/* Certification now sits inside the building-materials block rather than at
   the page foot, so it needs the separator the range block has. */
.product-cert{margin-top:56px;padding-top:48px;border-top:1px solid var(--line)}
.product-collection--dark .product-cert{border-top-color:rgba(255,255,255,.16)}

/* ---------------------------------------------------------------------------
   Catalogue sheets
   These are pages, not product shots - a valve range with eleven items, a
   swatch board with twenty. Their aspect ratios run from 0.69 to 2.36, and any
   of them squeezed into a shared 4:3 cell would be unreadable, which defeats
   the reason for showing them. So they run at their own proportions, one per
   row, with a sensible ceiling on height so a tall sheet does not take over
   the page.
   --------------------------------------------------------------------------- */
/* Sheets now sit inside the group they belong to, directly beneath that
   group's product grid - a valve board is part of Hardware Fittings, not a
   module of its own. The gap above separates them from the grid without
   reading as a new section. */
.range-group--sheets .sheet-list,
.range-group .sheet-list{display:grid;gap:36px}
.range-group .range-grid + .sheet-list{margin-top:36px}
.sheet-item{margin:0}
/* No max-height: capping it made object-fit:contain letterbox the sheet, so
   the rendered ratio no longer matched the file and tall sheets sat in a band
   of white. A tall sheet is simply tall - that is what scrolling is for. */
.sheet-item img{
  width:100%;
  height:auto;
  display:block;
  background:#fff;
  border:1px solid var(--line);
}
/* The portrait sheet is the exception - full width it would run past two
   screens, so it is held to a readable column. */
.sheet-item--portrait img{max-width:620px}
.sheet-item figcaption{
  margin-top:12px;
  font-size:13px;
  line-height:1.55;
  color:var(--muted);
}
.product-collection--dark .sheet-item img{border-color:rgba(255,255,255,.14)}
.product-collection--dark .sheet-item figcaption{color:#bbb7ad}

@media(max-width:760px){
  .range-group--sheets .sheet-list{gap:28px}
}

/* ---------------------------------------------------------------------------
   PROJECT SUPPLY (building materials only, 2026-08)
   ---------------------------------------------------------------------------
   Three capability blocks taken from the case deck (slides 15-17), sitting
   above the product matrix. They address developers and main contractors,
   whereas everything below addresses product selection, so they need to read
   as a different kind of content - not another range group.

   Hence: copy on the left at a readable measure, photographs on the right in
   a row rather than a 4-across grid. The photographs run small on purpose.
   The smallest source file is 323px wide; at a ~230px cell it still renders
   above 1:1, which is the threshold below which images visibly soften on this
   site (see the image audit in STATUS.md). A 4-across grid would have blown
   past it.
   --------------------------------------------------------------------------- */
.project-supply{
  margin-top:56px;
  padding-top:52px;
  border-top:1px solid var(--line);
}
.supply-block{
  display:grid;
  grid-template-columns:minmax(0,7fr) minmax(0,9fr);
  gap:20px 44px;
  align-items:start;
  padding-top:34px;
}
.supply-block + .supply-block{
  margin-top:34px;
  border-top:1px solid var(--line);
}
.supply-block__number{
  display:block;
  font-size:11px;
  font-weight:400;
  letter-spacing:.14em;
  color:#9a958a;
  margin-bottom:10px;
}
.supply-block__copy h3{
  margin:0 0 12px;
  font-family:inherit;
  font-size:19px;
  font-weight:600;
  line-height:1.35;
  letter-spacing:0;
  text-transform:none;
  color:var(--ink);
}
.supply-block__copy p{
  margin:0;
  font-size:15px;
  line-height:1.75;
  color:var(--muted);
}
/* auto-fit rather than a fixed column count: block 01 carries five photographs
   and blocks 02-03 carry two, and a fixed grid would leave the short blocks
   with three empty cells. */
.supply-block__media{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:14px;
}
.supply-block__media img{
  width:100%;
  aspect-ratio:4 / 3;
  object-fit:cover;
  display:block;
  background:var(--cream);
  border:1px solid var(--line);
}
.supply-block__media[data-count="2"]{grid-template-columns:repeat(2,minmax(0,1fr))}
/* Five photographs on a 4-up grid leave one orphan on a second row. A 6-column
   track with 2- and 3-wide spans gives 3 + 2 instead, both rows flush. */
.supply-block__media[data-count="5"]{grid-template-columns:repeat(6,minmax(0,1fr))}
.supply-block__media[data-count="5"] img{grid-column:span 2}
.supply-block__media[data-count="5"] img:nth-child(n+4){grid-column:span 3}

.product-collection--dark .project-supply{border-top-color:rgba(255,255,255,.16)}
.product-collection--dark .supply-block + .supply-block{border-top-color:rgba(255,255,255,.16)}
.product-collection--dark .supply-block__copy h3{color:#fff}
.product-collection--dark .supply-block__copy p{color:#bbb7ad}
.product-collection--dark .supply-block__media img{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.14)}

@media(max-width:900px){
  .supply-block{grid-template-columns:minmax(0,1fr);gap:20px}
}
@media(max-width:760px){
  .project-supply{margin-top:44px;padding-top:40px}
  .supply-block{padding-top:28px}
  .supply-block + .supply-block{margin-top:28px}
  .supply-block__media,
  .supply-block__media[data-count="5"]{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
  .supply-block__media[data-count="5"] img,
  .supply-block__media[data-count="5"] img:nth-child(n+4){grid-column:auto}
}
