/* ==========================================================================
   sections.css  —  one block per home-page section
   ========================================================================== */

/* ==========================================================================
   Section rhythm
   A band supplies its own vertical padding and butts against its neighbours,
   so the page has no gap between them. The rounded image panels still need
   cream around them, so those sections keep their page padding.
   ========================================================================== */
.section:has(.block) { padding-block: 0; }

/* Each band's own vertical padding, taken from the comp's frame heights
   (hero 834, about 846, products 1071 at 1280). */
#about    { --band-y: var(--block-pad-y); }
#products { --band-y: var(--band-pad-y-lg); }

.section:has(.band__frame),
.section:has(.why__frame),
.section:has(.cta__frame) { padding-block: var(--section-y); }

/* ==========================================================================
   Site header
   Sits transparent over the hero, then condenses into a navy bar once the
   page scrolls. Show/hide uses transform only.
   ========================================================================== */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 60;
  transform: translateY(0);
  transition:
    transform  var(--t-slow) var(--ease-out),
    background var(--t-base) var(--ease-out),
    padding    var(--t-base) var(--ease-out);
}

.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--c-navy);
  opacity: 0;
  transition: opacity var(--t-base) var(--ease-out);
}

.site-header.is-stuck { box-shadow: var(--shadow-md); }

.site-header.is-stuck .site-header__inner {
  padding-top: var(--s-3);
  padding-bottom: var(--s-3);
}
.site-header.is-stuck::before { opacity: 1; }

.site-header.is-hidden { transform: translateY(-115%); }

/* The admin bar is only ever shown to logged-in users, but the fixed header
   has to sit below it or it covers the logo. */
.admin-bar .site-header { top: 32px; }

@media screen and (max-width: 782px) {
  .admin-bar .site-header { top: 46px; }
}

@media screen and (max-width: 600px) {
  /* Below this width the admin bar stops being fixed and scrolls away. */
  .admin-bar .site-header { top: 0; }
}

/* The shell carries the page margin so the bar lines up with the hero frame
   below it; the inner box then insets the logo from the photograph's edge. */
.site-header > .shell { padding-inline: var(--hero-inset); }

.site-header__inner {
  position: relative;
  width: 100%;
  margin-inline: auto;
  padding-top: calc(var(--hero-inset) + var(--nav-drop));
  padding-bottom: var(--s-5);
  padding-inline: var(--logo-inset);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-5);
  min-height: var(--nav-h);
}

.site-header__nav { margin-inline: auto; }

/* Carried by the panel, not the bar — hidden until the burger takes over. */
.site-header__nav-cta { display: none; }

/* Over the hero photograph the logo has no ground of its own. */
.site-header:not(.is-stuck) .logo__text { text-shadow: 0 1px 12px rgba(0, 20, 38, 0.6); }

/* ==========================================================================
   Hero
   One screen: the frame takes the viewport height less the cream margin above
   and below, runs the page's full width, and the photograph covers it. The
   export is a plain rectangle, so every piece of the comp's shape is drawn
   here — the rounded corners, the notch around the quote button, and the
   cream panel the wordmark sits in.
   ========================================================================== */
/* These two are the cream above and below, so the section comes to exactly one
   viewport once the frame takes the rest. */
.hero {
  padding-top: var(--hero-inset);
  padding-bottom: var(--hero-tail);
}

.hero > .shell { padding-inline: var(--hero-inset); }

.hero__frame {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* min- rather than a fixed height: on a phone the copy stacks and is allowed
     to push the frame taller, which is the one case where the hero may run
     past the fold. Everywhere else it lands on exactly this. */
  min-height: max(
    calc(100vh  - var(--wp-bar) - var(--hero-inset) - var(--hero-tail)),
    calc(100svh - var(--wp-bar) - var(--hero-inset) - var(--hero-tail))
  );
  padding: calc(var(--nav-drop) + var(--nav-h) + var(--s-5)) var(--block-pad-x) var(--s-11);
  /* A defined ground, so any part of the frame the photograph does not reach
     reads as the page rather than as whatever sits behind. */
  background: var(--bg-page);
  border-radius: var(--r-xl);
  overflow: hidden;
  isolation: isolate;
}

.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: 0;
}

/* The frame's ratio follows the viewport, not the photograph, so the
   photograph covers and crops. The frame's own radius rounds the corners. */
.hero__bg img { object-fit: cover; }

/* Slideshow. The frames are stacked and cross-faded rather than slid, so the
   header never shows a seam or an empty edge between two photographs -- one
   simply becomes the other. Only the shown frame is opaque, so the scrim and
   the copy above it see a single, steady picture throughout. */
.hero__bg--show img {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1500ms var(--ease-out);
}
.hero__bg--show img.is-on { opacity: 1; }

/* Someone who has asked for less motion gets the first photograph, held. */
@media (prefers-reduced-motion: reduce) {
  .hero__bg--show img { transition: none; }
}

/* The comp notches the photograph around the header's quote button. Drawn as a
   page-coloured tile rather than baked into the export, so it stays aligned at
   any width. A real element rather than a pseudo, because it needs two pseudos
   of its own: where the tile meets the frame's top and right edges the
   photograph has to curve into it, and a cream box cannot round a corner that
   belongs to the photo — so each junction gets a small "ear" that paints cream
   outside a quarter circle. The frame's overflow rounds the outer corner. */
.hero__notch {
  position: absolute;
  z-index: -1;
  top: 0;
  right: 0;
  width: var(--hero-notch-w);
  height: var(--hero-notch-h);
  background: var(--bg-page);
  border-bottom-left-radius: var(--r-lg);
}

.hero__notch::before,
.hero__notch::after,
.hero__card::before,
.hero__card::after {
  content: "";
  position: absolute;
  width: var(--r-lg);
  height: var(--r-lg);
  pointer-events: none;
}

/* Photo below-left of the junction: cream fills outside a circle centred on
   the ear's bottom-left. */
.hero__notch::before,
.hero__notch::after {
  background: radial-gradient(circle at 0 100%, transparent calc(var(--r-lg) - 0.6px), var(--bg-page) var(--r-lg));
}
.hero__notch::before { top: 100%; right: 0; }     /* meets the right edge   */
.hero__notch::after  { top: 0; right: 100%; }     /* meets the top edge     */

/* Stops solved against the photograph's measured luminance in each band of
   copy: light where nothing sits over it, heavy from 52% down where the
   headline, intro and button are. */
.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Clipped to the photograph's own alpha, sized and placed exactly as the
     img is (cover, centre). An export with the notches cut into it then
     shows plain cream through them instead of a tinted shadow of the notch,
     and an opaque export is unaffected. Without a photograph --hero-img is
     unset and the fallback drops the mask. */
  -webkit-mask-image: var(--hero-img, none);
          mask-image: var(--hero-img, none);
  -webkit-mask-size: cover;
          mask-size: cover;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  /* Near-black, not navy. Measured against the comp: down a clean column of
     its hero the blue channel runs 2 to 5 points above red -- the photograph
     keeps its own browns and greys. The navy this replaced ran 50 points of
     blue over red and painted the whole picture a single colour. The stops
     also ramp evenly now: 0.30 at 45% jumping to 0.72 at 52% drew a visible
     horizontal band across the photograph, which no comp has. */
  background: linear-gradient(
    180deg,
    rgba(8, 12, 18, 0.34) 0%,
    rgba(8, 12, 18, 0.14) 20%,
    rgba(8, 12, 18, 0.22) 38%,
    rgba(8, 12, 18, 0.46) 56%,
    rgba(8, 12, 18, 0.62) 76%,
    rgba(8, 12, 18, 0.72) 100%
  );
}

/* Deliberately not a containing block: the card is positioned against the
   frame, whose bottom-left corner it fills. */
.hero__copy {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 34%;
  column-gap: var(--s-8);
  row-gap: var(--s-5);
  align-items: start;
}

/* One <h1> for semantics, two grid cells for layout. */
.hero__title { display: contents; }

.hero__title-a,
.hero__title-b {
  font-family: var(--font-head);
  font-weight: var(--fw-bold);
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  color: var(--c-white);
}

.hero__title-a {
  grid-column: 1 / -1;
  grid-row: 1;
  /* Reserves the tag's lane so the two can never collide. */
  padding-right: calc(34% + var(--s-8));
}

.hero__title-b {
  grid-column: 1 / -1;
  grid-row: 2;
  text-align: right;
}

.hero__tag {
  text-shadow: 0 1px 14px rgba(0, 20, 38, 0.55);
  grid-column: 2;
  grid-row: 1;
  align-self: end;
  font-size: var(--fs-sm);
  line-height: 1.4;
  color: var(--text-on-dark-mut);
}

.hero__pitch {
  grid-column: 1 / -1;
  grid-row: 3;
  justify-self: end;
  /* Keeps clear of the wordmark panel in the opposite corner. */
  max-width: min(44rem, 68%);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-6);
}

.hero__lead {
  text-shadow: 0 1px 14px rgba(0, 20, 38, 0.55);
  font-size: var(--fs-lead);
  color: var(--text-on-dark-mut);
}

/* The wordmark panel, notched into the bottom-left corner. Held in
   percentages of the frame, off the comp's own notch, so it keeps its
   proportion whatever height the viewport gives the frame. */
.hero__card {
  position: absolute;
  left: 0;
  bottom: 0;
  width: var(--hero-card-w);
  min-height: var(--hero-card-h);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: var(--s-6) var(--s-7) var(--s-6) var(--block-pad-x);
  background: var(--c-cream);
  border-radius: 0 var(--r-xl) 0 0;
}

/* Photo above-right of the junction: circle centred on the ear's top-right. */
.hero__card::before,
.hero__card::after {
  background: radial-gradient(circle at 100% 0, transparent calc(var(--r-lg) - 0.6px), var(--c-cream) var(--r-lg));
}
.hero__card::before { bottom: 100%; left: 0; }     /* meets the left edge    */
.hero__card::after  { bottom: 0; left: 100%; }     /* meets the bottom edge  */

.hero__card-title {
  font-family: var(--font-head);
  font-weight: var(--fw-bold);
  font-size: clamp(19px, 1.85vw, 26px);
  line-height: 1.22;
  letter-spacing: -0.3px;
  color: var(--c-navy);
  text-transform: uppercase;
  margin-bottom: var(--s-3);
}

.hero__card-note {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* ==========================================================================
   About
   ========================================================================== */
/* Two columns split 43/57 (the comp puts the heading at 41% of the width;
   the extra 2% centres the button on the notch below it). */
.about__grid {
  display: grid;
  grid-template-columns: 43fr 57fr;
  column-gap: var(--s-8);
  row-gap: var(--s-6);
  align-items: start;
}

.about__grid > * { min-width: 0; }

.about__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-6);
  max-width: 62ch;
}

/* The short rule under the heading — 161x2 in the comp. */
.about__body h2::after {
  content: "";
  display: block;
  width: 161px;
  height: 2px;
  margin-top: var(--s-3);
  background: var(--c-navy);
}

.about__text { color: var(--text-muted); }
.about__text strong { color: var(--c-navy); }

/* The button straddles the top edge of the photograph, sitting in a notch cut
   into it. It has to paint above the media, which comes later in the DOM. */
.about__body .btn {
  position: relative;
  z-index: 2;
  margin-bottom: -17px;   /* the comp sinks a fifth of the button into the photo */
}

.about__media { aspect-ratio: 20 / 7; }

/* The notch. The supplied export has it cut in already (as transparency), so
   this tile is drawn at the same place and size — 35.4% wide from 30.3% in,
   8.6% deep — and swallows it exactly, whichever crop the box applies.
   Concave shoulders on the tile, convex ears where the photo meets it. */
.about__media::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: 0;
  left: 30.3%;
  width: 35.4%;
  height: 8.6%;
  background: var(--c-white);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
}

.about__media::after {
  content: "";
  position: absolute;
  z-index: 1;
  top: 0;
  left: calc(30.3% - var(--r-lg));
  width: calc(35.4% + var(--r-lg) * 2);
  height: var(--r-lg);
  background:
    radial-gradient(circle at 0 100%,    transparent calc(var(--r-lg) - 0.6px), var(--c-white) var(--r-lg)) left  top / var(--r-lg) 100% no-repeat,
    radial-gradient(circle at 100% 100%, transparent calc(var(--r-lg) - 0.6px), var(--c-white) var(--r-lg)) right top / var(--r-lg) 100% no-repeat;
  pointer-events: none;
}

/* ==========================================================================
   Products
   ========================================================================== */
.products__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-5);
}

.products__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
  padding-right: var(--s-6);
}

.products__intro h2 { margin-block: var(--s-2); }

.products__intro p {
  font-size: var(--fs-sm);
  color: var(--text-on-dark-mut);
}

/* ==========================================================================
   Band — "Powering Projects With Quality Minerals"
   ========================================================================== */
.band__frame {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 380px;
  padding: var(--block-pad-y) var(--block-pad-x);
  border-radius: var(--r-xl);
  overflow: hidden;
  isolation: isolate;
}

.band__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: 0;
}
.band__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    95deg,
    rgba(0, 20, 38, 0.86) 0%,
    rgba(0, 20, 38, 0.55) 46%,
    rgba(0, 20, 38, 0.18) 100%
  );
}

.band__copy {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-5);
  max-width: 30rem;
}

.band__copy h2 { color: var(--c-white); }
.band__copy p { color: var(--text-on-dark-mut); }
.band__copy p strong { color: var(--c-white); }

/* ==========================================================================
   Industries
   ========================================================================== */
.industries__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--s-6);
  margin-bottom: var(--s-8);
}

.industries__intro {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
  max-width: 44ch;
}

.industries__intro p {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.industries__controls {
  display: flex;
  gap: var(--s-3);
}

/* Horizontal scroller. The row takes HORIZONTAL gestures only --
   data-lenis-prevent-horizontal, not data-lenis-prevent: the blanket form made
   Lenis step aside for vertical wheels too, and since the row is a scroll
   container that cannot move vertically (overflow: auto hidden) and the
   framework's stylesheet contains its overscroll, the page stopped scrolling
   whenever the pointer was over the row. The x containment below is kept on
   its own so a swipe past the last tile still does not navigate back. */
.industries__track {
  display: flex;
  gap: var(--s-5);
  /* Setting one axis makes the other compute to auto, which was adding a
     vertical scrollbar inside the row. Both axes are declared here. */
  overflow: auto hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: var(--s-2);
  overscroll-behavior-x: contain;
  /* The row hides its vertical overflow to keep a scrollbar out of it, which
     would also crop the tiles' hover lift. The padding buys the lift its room
     back and the negative margin gives the layout the space again. */
  padding-top: 10px;
  margin-top: -10px;
}
.industries__track::-webkit-scrollbar { display: none; }

/* While the row is carrying itself along, both of these have to stand down:
   a snap point would fight every sub-pixel frame of the drift, and
   scroll-behavior: smooth would turn each frame's write into an animation of
   its own. The arrows still ask for smooth explicitly, which still works. */
.industries__track.is-looping {
  scroll-snap-type: none;
  scroll-behavior: auto;
}

/* Tiles fade in rather than travelling upward, so their entrance transform
   never overflows the row it lives in. */
.js .industries__track [data-reveal] { transform: none; }

.industries__track > * {
  flex: 0 0 clamp(200px, 23%, 264px);
  scroll-snap-align: start;
}

.industries__foot {
  display: flex;
  justify-content: center;
  margin-top: var(--s-8);
}

/* ==========================================================================
   Why choose Reva
   ========================================================================== */
.why__frame {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--s-9);
  align-items: center;
  padding: var(--block-pad-y) var(--block-pad-x);
  border-radius: var(--r-xl);
  overflow: hidden;
  isolation: isolate;
}

.why__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: 0;
}
.why__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgba(0, 20, 38, 0.88) 0%,
    rgba(0, 20, 38, 0.70) 52%,
    rgba(0, 20, 38, 0.42) 100%
  );
}

.why__intro {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
}

.why__intro h2 { color: var(--c-white); }
.why__intro p { color: var(--text-on-dark-mut); }
.why__intro p strong { color: var(--c-white); }

.why__cards {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
}

/* ==========================================================================
   Global presence
   ========================================================================== */
.presence__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s-3);
  text-align: center;
  margin-bottom: var(--s-9);
}

.presence__head p {
  max-width: 52ch;
  color: var(--text-muted);
}

.presence__map {
  position: relative;
  isolation: isolate;   /* keeps the ::before fallback above the block's fill */
  width: 100%;
  max-width: 880px;
  margin-inline: auto;
}

/* The pins are placed in percentages of this box, so the box has to BE the
   map. Giving the frame an aspect ratio of its own and fitting the image
   inside it letterboxes the artwork, and every pin then drifts away from the
   coastline it was measured against. Only a frame with no usable map of its
   own — none set, or one that failed to load — needs a shape given to it. */
.presence__map:not(:has(img)),
.presence__map:has(img.is-missing) { aspect-ratio: 2 / 1; }

.presence__map img {
  position: relative;
  z-index: 1;
  display: block;
  width: 100%;
  height: auto;
}

/* Shown only while the map export is missing (see main.js / .is-missing). */
.presence__map:not(:has(img))::before,
.presence__map:has(img.is-missing)::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: var(--r-lg);
  background-image: radial-gradient(circle, var(--c-navy-200) 1.9px, transparent 2px);
  background-size: 16px 16px;
}

/* ==========================================================================
   Closing CTA
   ========================================================================== */
.cta__frame {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  align-items: stretch;
  gap: 0;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--c-terracotta);
}

.cta__media {
  border-radius: 0;
  min-height: 260px;
}

.cta__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: var(--s-5);
  padding: var(--block-pad-y) var(--block-pad-x);
}

.cta__copy h2 { color: var(--c-white); max-width: 16ch; }
/* A product CTA names the product, which needs the longer measure the comp gives it. */
.product-cta .cta__copy h2 { max-width: 22ch; }
.cta__copy p { color: rgba(255, 255, 255, 0.86); max-width: 52ch; }
.cta__copy p strong { color: var(--c-white); }

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer { padding-bottom: var(--s-6); }

.footer__frame {
  position: relative;
  padding: var(--block-pad-y) var(--block-pad-x) var(--s-7);
  border-radius: var(--r-xl);
  background: var(--c-navy);
  color: var(--text-on-dark);
  overflow: hidden;
  isolation: isolate;
}

.footer__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  opacity: 0.16;
  border-radius: 0;
}

.footer__grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  gap: var(--s-9);
  padding-bottom: var(--s-10);
}

.footer__brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-5);
}

.footer__tagline {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  letter-spacing: 1.1px;
  text-transform: uppercase;
  color: var(--c-white);
}

.footer__col-title {
  font-family: var(--font-head);
  font-size: var(--fs-body);
  font-weight: var(--fw-bold);
  color: var(--c-white);
  margin-bottom: var(--s-4);
}

.footer__list {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  font-size: var(--fs-sm);
  color: var(--text-on-dark-mut);
}

.footer__list a {
  position: relative;
  display: inline-block;
  transition: transform var(--t-base) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}

.footer__list a:hover {
  color: var(--c-white);
  transform: translateX(4px);
}

.footer__contact li {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
}

.footer__contact svg {
  width: 14px;
  height: 14px;
  margin-top: 5px;
  flex: 0 0 14px;
  color: var(--c-navy-200);
}

.footer__bar {
  position: relative;
  padding-top: var(--s-6);
  border-top: 1px solid var(--c-line-on-dark);
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--text-on-dark-mut);
}

.footer__bar strong { color: var(--c-white); }

/* ==========================================================================
   Responsive layout
   ========================================================================== */

@media (max-width: 1180px) {
  .hero__pitch { max-width: min(40rem, 68%); }
}

@media (max-width: 1100px) {
  .products__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .products__intro { grid-column: 1 / -1; padding-right: 0; }
  .why__frame { grid-template-columns: 1fr; }
  .footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-8); }
  .footer__brand { grid-column: 1 / -1; }
  .industries__track > * { flex-basis: clamp(200px, 34%, 260px); }
}

/* Measured: the logo (144), the full nav (527) and the quote button (157) need
   about 990px of bar between them. The burger takes over a little above that,
   and variables.css narrows the hero notch at the same threshold. */
@media (max-width: 1060px) {
  .burger { display: grid; }
  .site-header__cta { display: none; }

  /* A navy sheet rather than a white card: the panel belongs to the same
     family as the bands it drops over, and a white slab on a navy hero read
     as a browser artefact rather than part of the site. */
  .site-header__nav {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    margin-inline: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: var(--s-2) var(--s-6) var(--s-6);
    border-radius: var(--r-lg);
    background: var(--c-navy);
    box-shadow: var(--shadow-lg);
    transform: translateY(-10px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition:
      transform  var(--t-base) var(--ease-out),
      opacity    var(--t-base) var(--ease-out),
      visibility 0s linear var(--t-base);
  }

  .site-header.nav-open .site-header__nav {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition-delay: 0s;
  }

  .site-header__nav .nav__item + .nav__item {
    border-top: 1px solid var(--c-line-on-dark);
  }

  .site-header__nav .nav__link {
    justify-content: flex-start;
    padding: var(--s-4) 0;
    border-radius: 0;
    font-size: var(--fs-body);
    font-weight: var(--fw-semi);
    color: var(--text-on-dark);
  }

  /* The sliding pill is a bar-only gesture: in a list it lands as a block of
     navy on navy. The row marks itself in the accent instead. */
  .site-header__nav .nav__link::before { display: none; }

  .site-header__nav .nav__item:hover .nav__link,
  .site-header__nav .nav__link:focus-visible,
  .site-header__nav .nav__link[aria-current="page"] {
    color: var(--c-terracotta);
  }

  .site-header__nav-cta {
    display: inline-flex;
    justify-content: center;
    margin-top: var(--s-5);
  }

  /* Dropdowns collapse on small screens; top-level links still resolve — so
     the chevron goes too, rather than promising a submenu that never opens. */
  .site-header__nav .nav__menu { display: none; }
  .site-header__nav .nav__link svg { display: none; }

  /* A scrim behind the panel, so the menu reads as a layer over the page.
     Absolute rather than fixed: the header carries a transform, which makes it
     the containing block for fixed children and would crop this to the bar.
     It lets taps through, so they reach the page and the close handler. */
  .site-header.nav-open::after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 100vh;
    z-index: -1;
    pointer-events: none;
    background: rgba(0, 20, 38, 0.45);
    animation: nav-scrim var(--t-base) var(--ease-out);
  }

  @keyframes nav-scrim { from { opacity: 0; } }
}

@media (max-width: 900px) {
  /* The copy stacks here, so the wordmark panel comes out of the corner and
     takes the full width at the foot of the frame. The frame is still one
     screen tall, but it is the one place the copy is allowed to push it
     past that. */
  .hero__frame { padding-bottom: 0; }

  .site-header__nav { top: calc(100% + 2px); }

  .hero__copy {
    grid-template-columns: minmax(0, 1fr);
    row-gap: var(--s-5);
  }
  /* The headline goes back to being one block here. Split across two grid rows
     it picked up the row gap between its own two lines and read as two
     separate headings. */
  .hero__title { display: block; grid-column: 1; grid-row: 1; }
  .hero__title-a,
  .hero__title-b { display: block; text-align: left; padding-right: 0; }
  .hero__tag { grid-column: 1; grid-row: 2; align-self: start; }
  .hero__pitch { grid-column: 1; grid-row: 3; justify-self: start; max-width: none; }
  .hero__card {
    position: static;
    grid-column: 1;
    grid-row: 4;
    width: calc(100% + var(--block-pad-x) * 2);
    min-height: 0;
    margin-top: var(--s-7);
    margin-left: calc(-1 * var(--block-pad-x));
    margin-right: calc(-1 * var(--block-pad-x));
    padding: var(--s-6) var(--block-pad-x);
    border-radius: var(--r-xl) var(--r-xl) 0 0;
  }
  .hero__card::before,
  .hero__card::after { display: none; }

  .about__grid { grid-template-columns: minmax(0, 1fr); margin-bottom: var(--s-7); }
  .about__body .btn { margin-bottom: 0; }
  .about__media { aspect-ratio: 16 / 9; }
  .about__media::before,
  .about__media::after { display: none; }

  .band__frame { min-height: 320px; }
  .band__copy { max-width: none; }

  .industries__head { grid-template-columns: minmax(0, 1fr); }
  .industries__controls { justify-content: flex-start; }

  .cta__frame { grid-template-columns: minmax(0, 1fr); }
  .cta__media { min-height: 200px; aspect-ratio: 16 / 9; }
}

@media (max-width: 640px) {
  .products__grid { grid-template-columns: minmax(0, 1fr); }

  /* Two short lists side by side rather than one column a screen and a half
     long. The address block keeps the full width — its lines wrap. */
  .footer__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--s-5);
    row-gap: var(--s-8);
  }
  .footer__grid > :has(.footer__contact) { grid-column: 1 / -1; }
  .footer__col-title { margin-bottom: var(--s-3); }
  .industries__track > * { flex-basis: min(72%, 260px); }
  .presence__map:not(:has(img)),
  .presence__map:has(img.is-missing) { aspect-ratio: 3 / 2; }
}

/* ==========================================================================
   About page
   Composed from template-parts/about/*. Measurements are from the 1280 comp
   and held as shares of their container so they scale with the 1340 column.
   ========================================================================== */

/* ---- Hero: full-bleed photograph tinted navy, copy centred ---------------- */
.about-hero {
  position: relative;
  display: grid;
  align-items: center;
  min-height: clamp(380px, 39.6vw, 507px);
  margin-inline: calc(50% - 50vw);
  padding-block: calc(var(--nav-h) + var(--s-10)) var(--s-10);
  background: var(--c-navy);
  color: var(--c-white);
  isolation: isolate;
  text-align: center;
}

.about-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 0;
}

/* Photograph reads as a navy-tinted backdrop, not a picture. */
.about-hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 34, 63, 0.62);
}

.about-hero h1 { color: var(--c-white); }

.about-hero__lead {
  max-width: 70ch;
  margin: var(--s-3) auto 0;
  font-size: var(--fs-lead);
  color: var(--text-on-dark-mut);
}
.about-hero__lead strong { color: var(--c-white); }

/* The bar floats over the photograph here, as on the home page. */
.page-template-page-about .site-header:not(.is-stuck)::before { opacity: 0; }

/* ---- Intro ------------------------------------------------------------------ */
.intro {
  display: grid;
  grid-template-columns: minmax(0, 47fr) minmax(0, 53fr);
  grid-template-areas:
    "head  badge"
    "photo body";
  column-gap: 6.5%;
  row-gap: var(--s-7);
  align-items: start;
}

.intro__head { grid-area: head; }
.intro__head h2 { max-width: 22ch; }

.intro__badge {
  grid-area: badge;
  justify-self: end;
  position: relative;
  width: 150px;
  height: 150px;
  margin-top: calc(-1 * var(--s-7));
  display: grid;
  place-items: center;
}

.intro__badge-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  font-family: var(--font-body);
  font-size: 12.5px;
  letter-spacing: 1.6px;
  fill: var(--c-ink-faint);
  animation: intro-spin 24s linear infinite;
}

@keyframes intro-spin { to { transform: rotate(360deg); } }

.intro__badge-core {
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--c-terracotta-200);
  color: var(--c-white);
}
.intro__badge-core svg { width: 26px; height: 26px; }

/* The collage: a tall photograph, the stat card beside it and a second
   photograph laid over the corner with a white ring around it. */
.intro__collage {
  grid-area: photo;
  position: relative;
  aspect-ratio: 508 / 452;
}

.intro__photo {
  position: absolute;
  border-radius: var(--r-md);
}
.intro__photo--tall  { left: 0; top: 0; width: 65.2%; height: 100%; }
.intro__photo--small {
  left: 39.2%;
  top: 41.6%;
  width: 60.8%;
  height: 58.4%;
  box-shadow: 0 0 0 8px var(--c-white);
}

.intro__stat {
  position: absolute;
  left: 66.7%;
  top: 0;
  width: 33.3%;
  height: 38.9%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: var(--c-white);
  box-shadow: var(--shadow-md);
}

.intro__stat-label {
  position: relative;
  padding-bottom: var(--s-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  line-height: 1.3;
  color: var(--c-navy);
}
.intro__stat-label::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--c-line-strong);
}

.intro__stat-value {
  font-family: var(--font-head);
  font-weight: var(--fw-bold);
  font-size: clamp(28px, 2.8vw, 40px);
  line-height: 1;
  letter-spacing: -0.5px;
  color: var(--c-navy);
}

.intro__body {
  grid-area: body;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
}

.intro__text {
  font-size: var(--fs-lead);
  color: var(--text-muted);
}
.intro__text strong { color: var(--c-navy); }

.intro__list-label {
  margin-top: var(--s-2);
  font-weight: var(--fw-semi);
  color: var(--c-navy);
}

.intro__list {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  color: var(--text-muted);
}
.intro__list li {
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
.intro__list svg {
  flex: 0 0 19px;
  width: 19px;
  height: 19px;
  color: var(--c-navy);
}
.intro__list strong { color: var(--c-navy); }

.intro__body .btn { margin-top: var(--s-4); }

/* ---- Mission & vision -------------------------------------------------------- */
.mission {
  display: grid;
  grid-template-columns: minmax(0, 47fr) minmax(0, 53fr);
  grid-template-rows: 1fr auto;
  min-height: 560px;
}

.mission__media {
  grid-area: 1 / 1 / 3 / 2;
  border-radius: 0;
}

/* Left to itself the photograph sets the band's height out of its own
   proportions, so every wider screen made this section taller — a portrait
   export across a 47% column came out past a thousand pixels at 1920. Taking
   it out of flow hands the height back to the copy and the card beside it,
   and the picture crops to whatever those two need. */
.mission__media img {
  position: absolute;
  inset: 0;
}

/* The photograph beside this column is as tall as the column makes it, so
   every line the copy does not need is a band of sky nobody asked for. The
   rhythm here is a step tighter than the page's default for that reason. */
.mission__copy {
  grid-area: 1 / 2 / 2 / 3;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-3);
  max-width: 640px;
  padding: var(--s-7) var(--block-pad-x) var(--s-8) var(--s-7);
}

/* The heading decides its own break, with the | token in Reva Settings. This
   cap is only here to stop a heading written without one from running the
   column's full width — at 14ch it was narrower than the line the break had
   already chosen, so "Purity, Performance" wrapped and the heading came out
   three lines deep instead of two. */
.mission__copy h2 { max-width: 18ch; }

.mission__text { color: var(--text-on-dark-mut); }
.mission__text strong { color: var(--c-white); }

.mission__copy .btn { margin-top: var(--s-2); }

/* The experience figure, laid over the photograph's right-hand edge. */
.mission__stat {
  grid-area: 2 / 1 / 3 / 2;
  justify-self: end;
  align-self: end;
  z-index: 1;
  width: min(223px, 60%);
  padding: var(--s-8) var(--s-7);
  background: rgba(0, 20, 38, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.mission__stat-value {
  font-family: var(--font-head);
  font-weight: var(--fw-bold);
  font-size: 48px;
  line-height: 1;
  color: var(--c-white);
}

.mission__stat-label {
  margin-top: var(--s-3);
  font-size: var(--fs-lead);
  font-weight: var(--fw-medium);
  line-height: 1.3;
  color: var(--text-on-dark-mut);
}

.mission__card {
  grid-area: 2 / 2 / 3 / 3;
  align-self: end;
  display: grid;
  grid-template-columns: 1fr 1fr;
  max-width: 600px;
  background: var(--c-white);
  border-top-right-radius: var(--r-lg);
  color: var(--text-default);
}

.mission__item {
  padding: var(--s-6) var(--s-5) var(--s-5);
}
.mission__item + .mission__item { border-left: 1px solid var(--c-line); }

.mission__icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: var(--s-4);
  border-radius: 50%;
  background: var(--c-terracotta);
  color: var(--c-white);
}
.mission__icon svg { width: 22px; height: 22px; }

.mission__item h3 {
  font-size: 20px;
  color: var(--c-navy);
}

.mission__item p {
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.mission__item strong { color: var(--c-navy); }

/* ---- What sets Reva apart --------------------------------------------------- */
.values__head { margin-bottom: var(--s-7); }
.values__head h2 { margin-top: var(--s-2); }

.values__grid {
  display: grid;
  grid-template-columns: minmax(0, 398fr) minmax(0, 366fr) minmax(0, 366fr);
  grid-auto-rows: minmax(250px, auto);
  gap: 12px;
}

.values__feature {
  grid-row: 1 / 3;
  display: flex;
  align-items: flex-end;
  padding: var(--s-6);
  border-radius: var(--r-lg);
  color: var(--c-white);
}
.values__feature img { position: absolute; inset: 0; }
.values__feature::after { z-index: 0; }

.values__feature-copy { position: relative; z-index: 1; }
.values__feature-copy h3 { color: var(--c-white); font-size: var(--fs-h3); }
.values__feature-copy p {
  margin-top: var(--s-2);
  max-width: 36ch;
  font-size: var(--fs-sm);
  color: var(--text-on-dark-mut);
}

.v-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--s-5) var(--s-5) var(--s-6);
  border-radius: var(--r-lg);
  background: var(--c-white);
  isolation: isolate;
  transition: translate var(--t-base) var(--ease-out);
}

/* Same fill as the product cards, so the two read as one system. */
.v-card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: var(--c-navy);
  clip-path: inset(100% 0 0 0 round var(--r-lg));
  transition: clip-path var(--t-base) var(--ease-smooth);
}

.v-card:hover::before,
.v-card:focus-within::before { clip-path: inset(0 0 0 0 round var(--r-lg)); }

.v-card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base) var(--ease-out);
}

.v-card:hover::after { opacity: 1; }

.v-card__icon {
  display: grid;
  place-items: center;
  width: 55px;
  height: 55px;
  margin-bottom: auto;
  border-radius: 50%;
  background: var(--c-navy);
  color: var(--c-white);
  transition: background var(--t-base) var(--ease-out), color var(--t-base) var(--ease-out);
}
.v-card__icon svg { width: 26px; height: 26px; }

.v-card__title {
  margin-top: var(--s-8);
  font-size: var(--fs-h4);
  color: var(--c-navy);
  transition: color var(--t-base) var(--ease-out);
}

.v-card__text {
  margin-top: var(--s-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
  transition: color var(--t-base) var(--ease-out);
}

.v-card:hover { translate: 0 -5px; }

.v-card:hover .v-card__title { transition-delay: 120ms; }
.v-card:hover .v-card__text  { transition-delay:  70ms; }
.v-card:hover .v-card__icon  { transition-delay: 150ms; }
.v-card:hover .v-card__icon  { background: var(--c-white); color: var(--c-navy); }
.v-card:hover .v-card__title { color: var(--c-white); }
.v-card:hover .v-card__text  { color: var(--text-on-dark-mut); }

@media (max-width: 1100px) {
  .intro {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "head" "photo" "body";
  }
  .intro__badge { display: none; }
  .intro__collage { max-width: 560px; }

  .mission { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; min-height: 0; }
  .mission__media { grid-area: 1 / 1 / 2 / 2; aspect-ratio: 16 / 9; }
  .mission__copy  { grid-area: 2 / 1 / 3 / 2; max-width: none; padding-inline: var(--block-pad-x); }
  .mission__stat  { grid-area: 1 / 1 / 2 / 2; width: min(223px, 50%); }
  .mission__card  { grid-area: 3 / 1 / 4 / 2; max-width: none; border-radius: 0; }

  .values__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .values__feature { grid-row: auto; grid-column: 1 / -1; min-height: 320px; }
}

@media (max-width: 640px) {
  .about-hero { min-height: 360px; }
  .intro__stat { padding: var(--s-3); }
  .mission__card { grid-template-columns: 1fr; }
  .mission__item + .mission__item { border-left: 0; border-top: 1px solid var(--c-line); }
  .values__grid { grid-template-columns: minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .intro__badge-ring { animation: none; }
}

/* ==========================================================================
   Inner pages
   The header floats over a photograph on the home page; everywhere else it
   needs its own ground from the first pixel.
   ========================================================================== */
.is-inner .site-header::before { opacity: 1; }

.page-hero { padding-top: var(--s-4); }

.page-hero > .shell { padding-inline: var(--hero-inset); }

.page-hero__frame {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  min-height: 340px;
  padding: calc(var(--nav-h) + var(--s-10)) var(--block-pad-x) var(--s-9);
  border-radius: var(--r-xl);
  background: var(--c-navy);
  overflow: hidden;
  isolation: isolate;
}

.page-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  border-radius: 0;
  opacity: 0.55;
}

.page-hero__frame h1 {
  color: var(--c-white);
  max-width: 20ch;
}

.page-hero__eyebrow { margin-bottom: var(--s-4); }

.page-hero__meta {
  margin-top: var(--s-4);
  max-width: 60ch;
  color: var(--text-on-dark-mut);
}

/* ---- Editor content ------------------------------------------------------ */
.prose {
  max-width: 68ch;
  color: var(--text-muted);
}

.prose > * + * { margin-top: var(--s-5); }

.prose h2,
.prose h3,
.prose h4 { margin-top: var(--s-9); }

.prose h2 { font-size: calc(var(--fs-h2) * 0.78); }

.prose a {
  color: var(--c-navy);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--t-fast) var(--ease-out);
}
.prose a:hover { color: var(--c-terracotta); }

.prose strong { color: var(--c-navy); }

.prose ul,
.prose ol {
  padding-left: var(--s-6);
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
}
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }

.prose blockquote {
  padding: var(--s-5) var(--s-6);
  border-radius: var(--r-md);
  background: var(--c-navy-050);
  color: var(--c-navy);
}

.prose img,
.prose figure img { border-radius: var(--r-md); }

.prose table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.prose table th,
.prose table td {
  padding: var(--s-3);
  border-bottom: 1px solid var(--c-line);
  text-align: left;
}

.prose__scroll { overflow-x: auto; }

/* ---- Two-column inner layout --------------------------------------------- */
.entry__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: var(--s-10);
  align-items: start;
}

.entry__aside {
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  padding: var(--s-6);
  border-radius: var(--r-lg);
  background: var(--c-navy-050);
}

.entry__aside h2 {
  font-size: var(--fs-h3);
  margin-bottom: var(--s-1);
}

.entry__aside p {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* ---- Grades -------------------------------------------------------------- */
.grades {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--s-4);
  margin-top: var(--s-6);
}

.grade {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  padding: var(--s-5);
  border-radius: var(--r-md);
  background: var(--c-white);
  border: 1px solid var(--c-line);
}

.grade__name {
  font-family: var(--font-head);
  font-weight: var(--fw-bold);
  font-size: var(--fs-h4);
  color: var(--c-navy);
}

.grade__row {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

.grade__row span {
  display: block;
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--c-ink-faint);
}

/* ---- Archive grids ------------------------------------------------------- */
.archive-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-5);
}

.archive-grid--tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.archive-grid .p-card { background: var(--c-white); }

.pagination {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  justify-content: center;
  margin-top: var(--s-9);
}

.pagination .page-numbers {
  display: grid;
  place-items: center;
  min-width: 40px;
  height: 40px;
  padding-inline: var(--s-3);
  border-radius: var(--r-pill);
  background: var(--c-white);
  color: var(--c-navy);
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  transition: transform var(--t-base) var(--ease-spring),
              background var(--t-base) var(--ease-out);
}

.pagination .page-numbers:hover { transform: translateY(-2px); }

.pagination .page-numbers.current {
  background: var(--c-navy);
  color: var(--c-white);
}

/* ---- Empty state --------------------------------------------------------- */
.empty {
  padding: var(--s-11) var(--s-6);
  text-align: center;
  color: var(--text-muted);
}

@media (max-width: 1100px) {
  .entry__layout { grid-template-columns: minmax(0, 1fr); }
  .archive-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .archive-grid--tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .archive-grid,
  .archive-grid--tiles { grid-template-columns: minmax(0, 1fr); }
  .page-hero__frame { min-height: 260px; }
}

/* ==========================================================================
   Product pages
   One product (a type within a category): header photograph, overview with
   gallery, features and grades, applications, the other products in its
   category, and the closing call to action. Measurements are from the 1280
   comp (frame 564:472) and held as shares of the column where they scale.
   ========================================================================== */

/* The bar floats over the photograph, as on the home and about pages. */
.single-reva_product .site-header:not(.is-stuck)::before,
.post-type-archive-reva_product .site-header:not(.is-stuck)::before,
.tax-reva_product_cat .site-header:not(.is-stuck)::before { opacity: 0; }

/* ---- Header ------------------------------------------------------------------ */
.product-hero {
  position: relative;
  display: grid;
  align-content: end;
  /* The comp's 537 assumed a photograph worth that much room. Without one
     it is a colour band holding a pill, a title and three lines, so it is
     cut to the copy: tall enough to clear the bar, no taller. */
  min-height: clamp(320px, 26vw, 400px);
  padding-top: calc(var(--hero-inset) + var(--nav-drop) + var(--nav-h) + var(--s-6));
  padding-bottom: var(--s-8);
  padding-inline: max(var(--block-pad-x), calc(50vw - var(--container-max) / 2));
  background: var(--c-navy-900);
  color: var(--c-white);
  isolation: isolate;
}

.product-hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: 0;
  background: var(--c-navy-900);
}

/* No band photograph: brand navy, deepening towards the foot so the copy sits
   on the darker end and the band still has somewhere to go. The photo scrim
   would only muddy a flat colour, so it stands down. */
.product-hero--plain .product-hero__bg {
  background: linear-gradient(168deg, var(--c-navy) 0%, var(--c-navy) 42%, var(--c-navy-900) 100%);
}

.product-hero--plain .product-hero__bg::after { content: none; }

/* The comp's photograph is darkened towards the foot, where the copy sits,
   and only lightly at the top, where the bar floats. */
.product-hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(4, 10, 18, 0.42) 0%,
    rgba(4, 10, 18, 0.16) 34%,
    rgba(4, 10, 18, 0.58) 68%,
    rgba(4, 10, 18, 0.86) 100%
  );
}

.product-hero__copy {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
}

.product-hero__cat {
  display: inline-flex;
  align-items: center;
  margin-bottom: var(--s-5);
  padding: 9px 18px;
  border-radius: var(--r-pill);
  background: var(--c-white);
  color: var(--c-navy);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  line-height: 1.3;
  transition:
    transform  var(--t-base) var(--ease-spring),
    background var(--t-base) var(--ease-out);
}

.product-hero__cat:hover,
.product-hero__cat:focus-visible {
  background: var(--c-terracotta-100);
  transform: translateY(-2px);
}

.product-hero h1 {
  color: var(--c-white);
  max-width: 18ch;
}

.product-hero__lead {
  max-width: 52ch;
  margin-top: var(--s-3);
  font-size: var(--fs-lead);
  line-height: var(--lh-snug);
  color: rgba(255, 255, 255, 0.88);
}
.product-hero__lead strong { color: var(--c-white); }

/* ---- Overview ---------------------------------------------------------------- */
.product-intro { --band-y: var(--block-pad-y); }

/* 510 | 32 | 618 of the comp's 1160 column. */
.product-intro__grid {
  display: grid;
  grid-template-columns: minmax(0, 510fr) minmax(0, 618fr);
  column-gap: clamp(24px, 2.8vw, 40px);
  row-gap: var(--s-8);
  align-items: start;
}

/* The photograph holds while the specification scrolls past it and lets go at
   the foot of the column -- which is the Enquire button, since the grid row
   ends there. Below 900 the grid is a single column and there is nothing to
   scroll past, and on a short viewport the frame would hold with its foot off
   the screen, so both sit this out. */
@media (min-width: 901px) and (min-height: 700px) {
  .product-gallery {
    position: sticky;
    top: calc(var(--nav-h) + var(--s-7));
    align-self: start;
  }

  /* Never taller than the room it has to hold in. */
  .product-gallery__main {
    max-height: calc(100vh - var(--nav-h) - var(--s-7) - var(--s-10));
  }

  /* A thumbnail rail rides below the frame and needs its own share. */
  .product-gallery:has(.product-gallery__rail) .product-gallery__main {
    max-height: calc(100vh - var(--nav-h) - var(--s-7) - var(--s-10) - 124px);
  }
}

/* Gallery */
.product-gallery__main {
  aspect-ratio: 510 / 590;
  border-radius: var(--r-lg);
}

.product-gallery__main img {
  transition: opacity var(--t-base) var(--ease-out);
}
.product-gallery__main img.is-swapping { opacity: 0.25; }

.product-gallery__rail {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 28px;
  align-items: center;
  gap: var(--s-2);
  margin-top: var(--s-5);
}

.product-gallery__thumbs {
  --thumb-gap: 16px;
  display: flex;
  gap: var(--thumb-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  padding: 3px;              /* room for the active ring */
  margin: -3px;
}
.product-gallery__thumbs::-webkit-scrollbar { display: none; }

/* Four to a row, as drawn: 98 x 86. */
.product-gallery__thumb {
  flex: 0 0 calc((100% - 3 * var(--thumb-gap)) / 4);
  aspect-ratio: 98 / 86;
  border-radius: var(--r-xs);
  overflow: hidden;
  scroll-snap-align: start;
  background: var(--ph-mineral);
  box-shadow: 0 0 0 0 var(--c-navy);
  opacity: 0.72;
  transition:
    opacity    var(--t-base) var(--ease-out),
    box-shadow var(--t-base) var(--ease-out);
}

.product-gallery__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.product-gallery__thumb:hover { opacity: 1; }

.product-gallery__thumb.is-active {
  opacity: 1;
  box-shadow: 0 0 0 2px var(--c-navy);
}

.product-gallery__arrow {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  color: var(--c-navy);
  transition:
    transform var(--t-base) var(--ease-spring),
    opacity   var(--t-base) var(--ease-out);
}
.product-gallery__arrow svg { width: 20px; height: 20px; }
.product-gallery__arrow:hover:not(:disabled) { transform: scale(1.12); }
.product-gallery__arrow:disabled { opacity: 0.3; cursor: default; }

/* Copy */
.product-intro__body h2 {
  font-size: calc(var(--fs-h2) * 1.3);
  line-height: var(--lh-display);
}

.product-intro__text {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  margin-top: var(--s-3);
  line-height: 1.45;
}
.product-intro__text strong { color: var(--c-navy); }

/* The underline the comp draws under "Key Features" and "Grades". */
.u-underlined {
  display: inline-block;
  padding: 0 4px 6px 0;
  border-bottom: 2px solid var(--c-terracotta);
  font-size: calc(var(--fs-h3) + 4px);
  line-height: 1.2;
}

.product-spec { margin-top: var(--s-5); }

.product-spec__tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-4);
}

.product-spec__tab {
  padding: 10px 18px;
  border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1.5px var(--c-navy);
  color: var(--c-navy);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  line-height: 1.2;
  transition:
    background var(--t-base) var(--ease-out),
    color      var(--t-base) var(--ease-out),
    transform  var(--t-base) var(--ease-spring);
}
.product-spec__tab:hover { transform: translateY(-2px); }
.product-spec__tab[aria-selected="true"] {
  background: var(--c-navy);
  color: var(--c-white);
}

/* Tabs switch panels only once the script is running; without it every
   version stays visible under its own name. */
.js .product-spec__panel.is-inactive { display: none; }
.js [data-tabs] .product-spec__name { display: none; }

.product-spec__name {
  margin: var(--s-5) 0 var(--s-2);
  font-family: var(--font-head);
  font-weight: var(--fw-bold);
  font-size: var(--fs-h4);
  color: var(--c-navy);
}

.features-card {
  padding: 21px 26px 26px;
  border-radius: var(--r-lg);
  background: var(--c-mist);
}

.features {
  display: grid;
  /* Columns sized to their items, as drawn: the second starts where the
     first's longest line ends rather than at the card's midpoint. */
  grid-template-columns: repeat(2, auto);
  justify-content: start;
  gap: 14px clamp(20px, 3vw, 40px);
  margin-top: var(--s-5);
}

.features__item {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  font-size: calc(var(--fs-xs) - 1px);
  font-weight: var(--fw-semi);
  line-height: 1.3;
  color: var(--c-ink);
}

.features__icon {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: 50%;
  background: var(--c-navy);
  color: var(--c-white);
}
.features__icon svg { width: 15px; height: 15px; }

/* Grades and what follows line up with the card's text, as drawn. */
.grade-block,
.product-intro__after { padding-inline: 26px; }

.grade-block { margin-top: var(--s-6); }

.grade-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 16px 18px;
  margin-top: var(--s-5);
}

.grade-pills li {
  min-width: 94px;
  padding: 10px 18px;
  border-radius: var(--r-pill);
  background: var(--c-slate-200);
  color: var(--c-navy);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  line-height: 1.3;
  text-align: center;
}

.product-intro__note {
  margin-top: var(--s-5);
  font-size: var(--fs-sm);
  color: var(--c-ink);
}

.product-intro__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4);
  margin-top: var(--s-6);
}

/* ---- Applications ------------------------------------------------------------ */
.product-apps__band {
  --band-y: calc(var(--block-pad-y) + var(--s-2));
  --notch-bg: var(--c-mist);
  background: var(--notch-bg);
}

.product-apps__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
  margin-bottom: var(--s-8);
}
.product-apps__head h2 { max-width: 18ch; }

/* Four across, as the industry listing already runs them. The comp drew three
   at 366 apiece; four of 1160 is 266, which the card's notches and type still
   carry, and a product with nine or eleven applications reads as a set rather
   than a column. The row steps down with the width rather than squeezing. */
.app-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(24px, 3.6vw, 46px) clamp(16px, 2.4vw, 31px);
}

@media (max-width: 1200px) {
  .app-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Below the widest layout a card is 250 to 310 across against the comp's 366,
   so the drawn notches -- and the body insets measured off them -- come down
   in proportion, or the title loses its line. Stops at 900, where the phone
   sizing further down takes over. */
@media (min-width: 901px) and (max-width: 1420px) {
  .app-grid .app-card {
    --nw-a: 54px;
    --nh-a: 49px;
    --nw-b: 68px;
    --nh-b: 43px;
  }
}

.app-card {
  --r-card:  20px;
  --nw-a:    68px;   /* top-left notch, from the comp */
  --nh-a:    62px;
  --nw-b:    86px;   /* bottom-right notch */
  --nh-b:    54px;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  aspect-ratio: 366 / 466;
  /* Only the two open corners are rounded: the notched ones are drawn over,
     and a rounded clip there would leave a hairline of the card's own colour
     where the notch meets its curve. */
  border-radius: 0 var(--r-card) 0 var(--r-card);
  /* No clip here: the notch overlays reach a pixel past the card's edges so
     that on a fractional pixel ratio (125%, 150% display scaling) the card's
     own edge never shows through them as a hairline. The media clips itself,
     and a card whose list of uses outgrows the drawn proportion still grows
     to fit it. */
  isolation: isolate;
  background: var(--c-navy-900);
  color: var(--c-white);
}

.app-card__media {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  border-radius: inherit;
}

.app-card__media img {
  transition: transform var(--t-slow) var(--ease-out);
}
.app-card:hover .app-card__media img { transform: scale(1.06); }

.app-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(9, 12, 17, 0) 44%, rgba(9, 12, 17, 0.78) 72%, rgba(9, 12, 17, 0.94) 100%);
}
.app-card--listed .app-card__media::after {
  background: linear-gradient(180deg, rgba(9, 12, 17, 0.05) 18%, rgba(9, 12, 17, 0.72) 50%, rgba(9, 12, 17, 0.94) 100%);
}

.app-card__body {
  position: relative;
  /* The top inset keeps a card that has grown clear of the top-left notch;
     the right inset clears the bottom-right one. */
  padding: calc(var(--nh-a) + var(--s-4)) calc(var(--nw-b) + var(--s-2)) 27px 26px;
}

.app-card__grade {
  display: inline-block;
  margin-bottom: var(--s-3);
  padding: 5px 11px;
  border-radius: var(--r-pill);
  background: var(--c-terracotta);
  color: var(--c-white);
  font-size: calc(var(--fs-badge) + 2px);
  font-weight: var(--fw-semi);
  letter-spacing: 0.4px;
  line-height: 1.2;
}

.app-card .app-card__title {
  font-size: clamp(20px, 2.2vw, 28px);
  line-height: 1.15;
  letter-spacing: var(--ls-heading);
  color: var(--c-white);
}

.app-card__items {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: var(--s-3);
  font-size: calc(var(--fs-xs) - 1px);
  line-height: 1.3;
  color: rgba(255, 255, 255, 0.84);
}

.app-card__items li {
  position: relative;
  padding-left: 14px;
}
.app-card__items li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--c-terracotta);
}

/* The two notched corners. Each is one box painted in the band's colour: the
   notch itself with its inner corner rounded, and the two "ears" that round
   the card's own corners where the notch meets its edges. Drawn rather than
   masked because the band behind is one flat colour.
   Every box reaches 1px past the card's outer edges, and the layers inside it
   overlap by 1px instead of meeting edge to edge: two edges that merely touch
   on a fractional device pixel each let a sliver through, which reads as a
   hairline grid on 125-175% display scaling. */
.app-card::before,
.app-card::after {
  content: "";
  position: absolute;
  z-index: 2;
  pointer-events: none;
}

.app-card::before {
  top: -1px;
  left: -1px;
  width: calc(var(--nw-a) + var(--r-card) + 1px);
  height: calc(var(--nh-a) + var(--r-card) + 1px);
  background:
    /* notch, top part then left part */
    linear-gradient(var(--notch-bg), var(--notch-bg)) 0 0 / calc(var(--nw-a) + 1px) calc(var(--nh-a) - var(--r-card) + 2px) no-repeat,
    linear-gradient(var(--notch-bg), var(--notch-bg)) 0 0 / calc(var(--nw-a) - var(--r-card) + 2px) calc(var(--nh-a) + 1px) no-repeat,
    /* its inner corner, rounded */
    radial-gradient(circle at 0 0, var(--notch-bg) calc(var(--r-card) - 0.5px), transparent var(--r-card))
      calc(var(--nw-a) - var(--r-card) + 1px) calc(var(--nh-a) - var(--r-card) + 1px) / var(--r-card) var(--r-card) no-repeat,
    /* ear beside it on the top edge */
    radial-gradient(circle at 100% 100%, transparent calc(var(--r-card) - 0.5px), var(--notch-bg) var(--r-card))
      var(--nw-a) 0 / calc(var(--r-card) + 1px) calc(var(--r-card) + 1px) no-repeat,
    /* ear below it on the left edge */
    radial-gradient(circle at 100% 100%, transparent calc(var(--r-card) - 0.5px), var(--notch-bg) var(--r-card))
      0 var(--nh-a) / calc(var(--r-card) + 1px) calc(var(--r-card) + 1px) no-repeat;
}

.app-card::after {
  right: -1px;
  bottom: -1px;
  width: calc(var(--nw-b) + var(--r-card) + 1px);
  height: calc(var(--nh-b) + var(--r-card) + 1px);
  background:
    /* notch, bottom part then right part */
    linear-gradient(var(--notch-bg), var(--notch-bg)) 100% 100% / calc(var(--nw-b) + 1px) calc(var(--nh-b) - var(--r-card) + 2px) no-repeat,
    linear-gradient(var(--notch-bg), var(--notch-bg)) 100% 100% / calc(var(--nw-b) - var(--r-card) + 2px) calc(var(--nh-b) + 1px) no-repeat,
    /* its inner corner, rounded */
    radial-gradient(circle at 100% 100%, var(--notch-bg) calc(var(--r-card) - 0.5px), transparent var(--r-card))
      var(--r-card) var(--r-card) / var(--r-card) var(--r-card) no-repeat,
    /* ear above it on the right edge */
    radial-gradient(circle at 0 0, transparent calc(var(--r-card) - 0.5px), var(--notch-bg) var(--r-card))
      100% 0 / calc(var(--r-card) + 1px) calc(var(--r-card) + 1px) no-repeat,
    /* ear beside it on the bottom edge */
    radial-gradient(circle at 0 0, transparent calc(var(--r-card) - 0.5px), var(--notch-bg) var(--r-card))
      0 100% / calc(var(--r-card) + 1px) calc(var(--r-card) + 1px) no-repeat;
}

/* ---- Other products in the category ------------------------------------------ */
.product-related .block { --band-y: calc(var(--block-pad-y) + var(--s-4)); }

.product-related__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-4);
  margin-bottom: var(--s-8);
}
.product-related__head h2 { max-width: 16ch; }

.product-related__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-6);
}

/* ---- Industry listing ---------------------------------------------------------- */
.industries-list__band {
  --band-y: var(--band-pad-y);
  /* The card's corner notches are painted in the band's own colour, so the
     two have to be set from one value or the notch shows the card through. */
  --notch-bg: var(--c-mist);
  background: var(--notch-bg);
}

/* An industry photograph comes out of the design already in the card's shape,
   notches cut away. So the moment one is in place the card stops drawing that
   — no notch overlay, no rounded corners, no colour of its own behind the
   cut-away. What was exported is what shows, which is also why it is contained
   rather than covered: a crop would eat into the notch it was exported with.
   An industry with no photograph keeps the drawn shape, or it would be a blank
   rectangle. */
.industries-list .app-card:has(.app-card__media img) {
  border-radius: 0;
  background: none;
}

.industries-list .app-card:has(.app-card__media img)::before,
.industries-list .app-card:has(.app-card__media img)::after {
  content: none;
}

.industries-list .app-card__media img { object-fit: contain; }

/* The fade is not in the export, and the title underneath it is white on
   whatever the photograph happens to be — a pink sky, a green field. So the
   card keeps its scrim and wears the photograph as the mask for it, which is
   what stops a rectangle of navy filling the two cut-away corners. */
.industries-list .app-card:has(.app-card__media img) .app-card__media::after {
  background: linear-gradient(
    180deg,
    rgba(0, 34, 63, 0) 40%,
    rgba(0, 34, 63, 0.32) 66%,
    rgba(0, 34, 63, 0.86) 100%
  );
  -webkit-mask-image: var(--tile-shape, linear-gradient(#000, #000));
          mask-image: var(--tile-shape, linear-gradient(#000, #000));
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

/* The photograph is doing the masking, so it cannot zoom — the tile lifts and
   the scrim warms instead. */
.industries-list .app-card:hover .app-card__media img { transform: none; }

.industries-list .app-card:has(.app-card__media img):hover { translate: 0 -6px; }

.industries-list .app-card:has(.app-card__media img) .app-card__media::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(
    180deg,
    rgba(0, 34, 63, 0) 36%,
    rgba(153, 74, 8, 0.26) 66%,
    rgba(153, 74, 8, 0.62) 100%
  );
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base) var(--ease-out);
  -webkit-mask-image: var(--tile-shape, linear-gradient(#000, #000));
          mask-image: var(--tile-shape, linear-gradient(#000, #000));
  -webkit-mask-size: contain;
          mask-size: contain;
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
}

.industries-list .app-card:has(.app-card__media img):hover .app-card__media::before { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .industries-list .app-card:has(.app-card__media img):hover { translate: none; }
}

/* Four across, so each tile is about two thirds the width it has on a product
   page. The photograph's notches shrink with it, so the inset that keeps the
   label clear of them is written as a share of the tile rather than in pixels
   — a fixed inset that sits right at 366px swallows the label at 170. */
.industries-list .app-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.industries-list .app-card__body { padding: 17.5% 24.5% 7% 7%; }

.industries-list .app-card__title { font-size: clamp(14px, 1.5vw + 6px, 26px); }

/* ---- Product listing ----------------------------------------------------------- */
.products-list__band {
  --band-y: var(--band-pad-y);
  background: var(--c-mist);
}

/* The search box. It sits in the header, under the sentence that says what
   the page holds, on the same pill radius as the nav above it. */
.product-search {
  display: flex;
  justify-content: center;
  gap: var(--s-3);
  max-width: 560px;
  margin: var(--s-7) auto 0;
}

.product-search__field {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex: 1 1 auto;
  min-width: 0;
  padding: 0 var(--s-3) 0 var(--s-5);
  border-radius: var(--r-pill);
  background: var(--c-white);
  /* A ring alone disappears against a photograph, so the field carries a
     shadow as well and reads as something laid on top of the header. */
  box-shadow: inset 0 0 0 1.2px rgba(0, 34, 63, 0.1), var(--shadow-md);
  transition:
    box-shadow var(--t-base) var(--ease-out),
    background var(--t-base) var(--ease-out);
}

.product-search__field:focus-within {
  box-shadow: inset 0 0 0 1.6px var(--c-navy), var(--shadow-lg);
}

.product-search__field > svg {
  flex: 0 0 18px;
  width: 18px;
  height: 18px;
  color: var(--c-navy-500);
}

.product-search__input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 13px 0;
  border: 0;
  background: none;
  font: inherit;
  font-size: var(--fs-sm);
  line-height: 1.3;
  color: var(--c-ink);
}

.product-search__input:focus { outline: none; }
.product-search__input::placeholder { color: var(--text-muted); }

/* The field draws its own, in the right place and the right colour. */
.product-search__input::-webkit-search-cancel-button,
.product-search__input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; }

.product-search__clear {
  flex: 0 0 28px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--c-navy-050);
  color: var(--c-navy);
  transition:
    background var(--t-fast) var(--ease-out),
    color      var(--t-fast) var(--ease-out);
}

.product-search__clear:hover,
.product-search__clear:focus-visible { background: var(--c-navy); color: var(--c-white); }
.product-search__clear svg { width: 11px; height: 11px; }

/* The button is the no-script path. Once the box answers on its own it is a
   second way to do what Return already does, so it goes. */
.js .product-search__submit { display: none; }

.product-search__status {
  max-width: 560px;
  margin: var(--s-3) auto 0;
  text-align: center;
  font-size: var(--fs-sm);
  line-height: var(--lh-snug);
  color: var(--text-on-dark-mut);
}

.product-search__status:empty { display: none; }

/* While a request is out the cards stay where they are and dim, rather than
   emptying and snapping the page height about under the reader. The class
   goes on the cards themselves: the box is in the header now, three sections
   away from what it is changing. */
.catalogue.is-loading { opacity: 0.45; }

.catalogue { transition: opacity var(--t-fast) var(--ease-out); }

.filter-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s-3);
  max-width: 820px;
  margin: 0 auto var(--s-9);
}

.filter-pill {
  padding: 9px 20px;
  border-radius: var(--r-pill);
  box-shadow: inset 0 0 0 1.2px var(--c-ink);
  color: var(--c-ink);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  line-height: 1.2;
  transition:
    background var(--t-base) var(--ease-out),
    color      var(--t-base) var(--ease-out),
    box-shadow var(--t-base) var(--ease-out),
    transform  var(--t-base) var(--ease-spring);
}

.filter-pill:hover { transform: translateY(-2px); box-shadow: inset 0 0 0 1.2px var(--c-terracotta); color: var(--c-terracotta-700); }

.filter-pill.is-active {
  background: var(--c-terracotta);
  box-shadow: none;
  color: var(--c-white);
}

/* Three to a row; a short last row sits centred, as drawn. */
.catalogue {
  --cat-gap: var(--s-5);
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--cat-gap);
}

.catalogue > .p-card {
  flex: 0 0 calc((100% - 2 * var(--cat-gap)) / 3);
  background: var(--c-white);
}

.products-list .empty {
  margin: 0 auto;
  text-align: center;
  color: var(--text-muted);
}

@media (max-width: 1100px) {
  .product-intro__grid { column-gap: var(--s-6); }
}

@media (max-width: 900px) {
  .product-intro__grid { grid-template-columns: minmax(0, 1fr); }
  .product-gallery { max-width: 560px; }

  .app-grid,
  .product-related__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .catalogue > .p-card { flex-basis: calc((100% - var(--cat-gap)) / 2); }
}

@media (max-width: 640px) {
  .features { grid-template-columns: minmax(0, 1fr); }
  .product-related__grid { grid-template-columns: minmax(0, 1fr); }
  .catalogue > .p-card { flex-basis: 100%; }
}

@media (max-width: 560px) {
  /* No min-height here. On a phone the band holds a pill, a short title and
     three lines -- about 200px -- while 420 forced on top of a 108px top
     inset left well over a screen-third of empty navy above the pill, because
     the content aligns to the foot. Padding alone now sets the height: clear
     the bar, draw the copy, stop. */
  .product-hero {
    min-height: 0;
    padding-top: calc(var(--hero-inset) + var(--nav-drop) + var(--nav-h) + var(--s-4));
    padding-bottom: var(--s-8);
  }

  .product-hero__cat { padding: 7px 14px; }

  .features-card { padding: 18px 18px 20px; }
  .grade-block,
  .product-intro__after { padding-inline: 4px; }

  .grade-pills { gap: 10px; }
  .grade-pills li { min-width: 0; padding: 8px 14px; }

  /* Two across is the floor on a phone, same as the industry listing. */
  .app-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px 10px;
  }

  /* At half a phone's width the drawn notch would eat the card, and the body
     insets are measured off it, so both come down together. */
  .app-card {
    --nw-a: 32px;
    --nh-a: 29px;
    --nw-b: 40px;
    --nh-b: 25px;
  }

  .app-card__body { padding: calc(var(--nh-a) + var(--s-3)) calc(var(--nw-b) + 6px) 16px 14px; }
  .app-card .app-card__title { font-size: 17px; }
  .app-card__grade { padding: 4px 8px; margin-bottom: var(--s-2); }
  .app-card__items { gap: 4px; margin-top: var(--s-2); }
  .app-card__items li { padding-left: 11px; }
  .app-card__items li::before { width: 5px; height: 5px; }

  /* Both requests on one row. The arrow steps aside so the two labels fit
     side by side without shrinking to nothing. */
  .product-intro__actions {
    flex-wrap: nowrap;
    gap: var(--s-3);
  }

  .product-intro__actions .btn {
    flex: 1 1 0;
    min-width: 0;
    justify-content: center;
    padding: var(--s-4) var(--s-3);
    font-size: var(--fs-btn);
  }

  .product-intro__actions .btn__label {
    white-space: normal;
    line-height: 1.25;
    text-align: center;
  }

  .product-intro__actions .btn__icon { display: none; }
}

/* ==========================================================================
   Contact page
   Composed in page.php, since the template has no file of its own.
   Measurements are from the 1280 comp and held as shares of their container
   so they scale with the 1340 column.
   ========================================================================== */

/* The bar floats over the photograph, as on the other inner pages. */
.page-template-page-contact .site-header:not(.is-stuck)::before { opacity: 0; }

/* 80 above the card in the comp, 96 under it. */
.contact-main { --band-y: var(--s-11); }
.contact-main .block--pad { padding-bottom: var(--band-pad-y); }

/* 501 | 42 | 615 of the comp's 1158 column. */
.contact-main__grid {
  display: grid;
  grid-template-columns: minmax(0, 501fr) minmax(0, 615fr);
  column-gap: clamp(24px, 3.3vw, 44px);
  row-gap: var(--s-9);
  align-items: start;
}

/* ---- The details card -------------------------------------------------------- */
.contact-card {
  padding: 34px 32px 44px;
  border-radius: var(--r-lg);
  background: var(--c-navy);
  color: var(--text-on-dark);
}

/* The comp's rule is the width of the label rather than the page's usual one. */
.contact-card__eyebrow .eyebrow { --eyebrow-rule: 84px; }

.contact-card .contact-card__title {
  margin-top: var(--s-2);
  /* Two lines in the comp: "Discuss Your Mineral" then "Requirements." */
  max-width: 24ch;
  font-size: calc(var(--fs-h2) - 4px);
  line-height: var(--lh-heading);
  color: var(--c-white);
}

.contact-list { margin-top: var(--s-6); }

.contact-list__item {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 20px 0 24px;
}

.contact-list__item + .contact-list__item { border-top: 1px solid var(--c-line-on-dark); }
.contact-list__item:last-child { padding-bottom: 0; }

.contact-list__icon {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  flex: 0 0 52px;
  border-radius: 50%;
  background: var(--c-white);
  color: var(--c-terracotta);
}
.contact-list__icon svg { width: 22px; height: 22px; }

.contact-list__label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semi);
  line-height: 1.35;
  color: var(--c-white);
}

.contact-list__value {
  margin-top: 6px;
  font-size: calc(var(--fs-xs) - 1px);
  line-height: 1.5;
  color: var(--text-on-dark-mut);
}

.contact-list__value a {
  color: inherit;
  transition: color var(--t-base) var(--ease-out);
}
.contact-list__value a:hover,
.contact-list__value a:focus-visible { color: var(--c-white); }

.contact-list__social {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 12px;
}

.contact-list__social a {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--c-white);
  color: var(--c-navy);
  transition:
    transform  var(--t-base) var(--ease-spring),
    background var(--t-base) var(--ease-out),
    color      var(--t-base) var(--ease-out);
}
.contact-list__social a:hover,
.contact-list__social a:focus-visible {
  transform: translateY(-2px);
  background: var(--c-terracotta);
  color: var(--c-white);
}
.contact-list__social svg { width: 17px; height: 17px; }

/* ---- The form ---------------------------------------------------------------- */
.contact-form .contact-form__title {
  font-size: calc(var(--fs-h2) - 6px);
  line-height: var(--lh-heading);
  color: var(--c-ink);
}

/* ---- The map ----------------------------------------------------------------- */
.contact-map {
  position: relative;
  margin-inline: calc(50% - 50vw);
}

.contact-map__frame {
  position: relative;
  height: clamp(300px, 36.4vw, 520px);
  background: var(--c-mist);
}

.contact-map__frame iframe,
.contact-map__frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  object-fit: cover;
}

/* The card floats over the map without taking its clicks. */
.contact-map .shell {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.contact-map__over {
  display: flex;
  align-items: flex-end;
  height: 100%;
  padding-bottom: 42px;
}

.contact-map__card {
  pointer-events: auto;
  width: min(369px, 100%);
  padding: 22px 24px 24px;
  border-radius: var(--r-md);
  background: var(--c-terracotta);
  color: var(--c-white);
  box-shadow: var(--shadow-md);
}

.contact-map__title {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  line-height: 1.3;
}
.contact-map__pin { display: inline-flex; }
.contact-map__pin svg { width: 18px; height: 18px; }

.contact-map__text {
  margin-top: 10px;
  font-size: calc(var(--fs-xs) - 1px);
  line-height: 1.7;
}

/* ---- Responsive -------------------------------------------------------------- */
@media (max-width: 1100px) {
  .contact-card .contact-card__title { max-width: none; }
  .contact-main__grid { column-gap: var(--s-7); }
}

@media (max-width: 900px) {
  .contact-main__grid { grid-template-columns: minmax(0, 1fr); }
  .contact-map__over { padding-bottom: 28px; }
}

@media (max-width: 640px) {
  .contact-card { padding: 28px 22px 34px; }
  .contact-list__icon {
    width: 44px;
    height: 44px;
    flex-basis: 44px;
  }
  .contact-list__icon svg { width: 19px; height: 19px; }
  .form__row { grid-template-columns: minmax(0, 1fr); }
  .contact-map__card { padding: 18px 20px 20px; }
  .contact-map__over { padding-bottom: 20px; }
}


/* ---- Industry listing, narrower ----------------------------------------------- */
/* Four across needs a desktop; below that the row steps down rather than
   letting the tiles squeeze. Two across is the floor — a phone keeps two. */
@media (max-width: 1200px) {
  .industries-list .app-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 900px) {
  .industries-list .app-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 560px) {
  .industries-list .app-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px 10px;
  }

  /* An industry with no photograph yet still draws its own notch, so that has
     to come down with the tile or it eats half of it. */
  .industries-list .app-card {
    --nw-a: 32px;
    --nh-a: 29px;
    --nw-b: 40px;
    --nh-b: 25px;
  }
}
