/* ==========================================================================
   Rotec Transmissions Private Limited
   Design system — international manufacturing.
   Open Sans across display, body and technical data.

   Rotec blue remains primary and signal yellow is reserved for calls to action
   and small section markers. Familiar typography and clear product photography
   keep the presentation direct and credible.
   ========================================================================== */

/* --- Fonts -------------------------------------------------------------
   Self-hosted latin subset. Fonts render locally; Google Maps embeds in
   the footer and Contact section are external integrations.
   Source: Google Fonts (SIL Open Font License 1.1).
   ----------------------------------------------------------------------- */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("../fonts/open-sans-latin.woff2") format("woff2");
}

/* Montserrat carries every heading, label and button. The reference the client
   approved sets its headlines in a wide geometric sans at heavy weights in
   caps; Open Sans is too narrow and too soft to hold that. Body copy stays on
   Open Sans, which matches the reference's humanist body text. */
@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-weight: 400 900;
  font-display: swap;
  src: url("../fonts/montserrat-latin.woff2") format("woff2");
}

/* --- Tokens ------------------------------------------------------------ */
:root {
  /* Brand — built out from the blue in the registered logo, which measures
     #485395 in the supplied artwork. `--brand` keeps that hue but carries more
     saturation, so headlines and buttons have punch and still read as the same
     blue as the mark sitting next to them. `--brand` is the workhorse:
     headlines, buttons, links, section bands. */
  --brand-ink: #101a40;      /* darkest — dark bands, footer */
  --brand-deep: #1e2e75;     /* hover states on blue */
  --brand: #2a3e96;          /* primary */
  --brand-mid: #4a5fc0;      /* on dark backgrounds */
  --brand-soft: #b0bce6;     /* dividers on blue */
  --brand-wash: #ebeefa;     /* tinted surfaces */
  --brand-tint: rgba(42, 62, 150, 0.06);

  /* Accent — safety orange, matching the reference the client benchmarks
     against. Every eyebrow marker, step number, primary button and hover state.
     Kept to small areas so it stays a signal rather than decoration.

     Measured against #f5f8fc and #101a40 rather than picked by eye:
       --accent      #ea6a10  ink on it 5.28:1 (button labels, AA normal text)
                              as a rule/dot on light 3.00:1 (AA non-text)
                              as text on the navy band 5.28:1
       --accent-deep #cf5a0b  hover; ink on it 4.12:1, so it is used for fills
                              and shadows, never as a background for body text
       --accent-ink  #a8480a  accent-coloured TEXT on light, 5.48:1 on surface
       --on-accent   #101a40  the ink that sits ON an orange fill

     White on this orange is 3.20:1 and is NOT used: the buttons set 13px bold,
     which WCAG counts as normal text and wants 4.5:1. The reference site does
     put white on its orange; it fails there. Navy on orange is the swap.

     Worth noting against the yellow this replaced: as a rule or dot on a light
     surface the yellow measured 1.71:1 and was effectively invisible. Every one
     of those marks now clears the 3:1 the guidelines ask of non-text. */
  --accent: #ea6a10;
  --accent-deep: #cf5a0b;
  --accent-ink: #a8480a;
  --on-accent: #101a40;
  --accent-wash: #fdeee4;

  /* Header navigation — the client asked for the bar's links in red.
     #b3122a measures 6.93:1 on the bar's white, so the 12px bold links clear
     the 4.5:1 AA bar for normal text with room to spare; the hover step is
     darker still. Used nowhere but the nav, so it stays out of the accent
     ramp that the rest of the site is built on. */
  --nav-link: #b3122a;
  --nav-link-hover: #8a0f20;

  /* Surfaces — very slightly blue-tinted greys so white cards read as raised
     against the page rather than merging with it. */
  --surface: #f5f8fc;
  --surface-lowest: #ffffff;
  --surface-low: #eff4fb;
  --surface-container: #e7eef8;
  --surface-high: #dae5f3;
  --surface-highest: #cbdaee;

  /* Ink */
  --primary: #2a3e96;
  --on-primary: #ffffff;
  --on-surface: #14243d;
  --on-surface-variant: #46566d;
  /* Muted captions/labels. Measured rather than picked: #5d6c83 is 5.0:1 on
     --surface and stays >=4.5 on every surface this text actually sits on,
     clearing the 4.5:1 AA bar for the small text it renders. The earlier
     #66768c landed at 4.35:1 and failed every one of those captions. */
  --secondary: #5d6c83;
  --on-dark: #ffffff;
  --on-dark-variant: rgba(255, 255, 255, 0.76);

  /* Lines */
  --outline: #93a4bc;
  --outline-variant: #cfdaea;

  /* Type */
  --font-display: "Montserrat", "Open Sans", Arial, Helvetica, sans-serif;
  --font-body: "Open Sans", Arial, Helvetica, sans-serif;
  --font-mono: "Open Sans", Arial, Helvetica, sans-serif;
  --font-headline: "Montserrat", "Open Sans", Arial, Helvetica, sans-serif;

  /* Type scale — single source of truth for every font-size on the site.
     Microcopy at 12px (not 11px) reads calmer for international audiences.
     Body is unified at 16px/1.6, with one consistent size for each heading
     level across the page templates. */
  --text-micro: 12px;
  --text-ui: 13px;
  --text-data: 14px;
  --text-body: 16px;
  --text-prose: 17px;
  --text-lede: 18px;
  --text-h3: 19px;
  --text-drawer: 28px;
  --text-quote: clamp(24px, 4vw, 32px);
  --text-h2: clamp(26px, 2.8vw, 38px);
  --text-h1: clamp(34px, 4.2vw, 54px);
  --text-stat: clamp(28px, 3.4vw, 44px);

  /* Elevation — Quiet International v2: soft depth, not heavy shadows */
  --radius-sm: 10px;
  --radius-lg: 16px;
  --radius-xl: 22px;
  --radius-pill: 999px;
  --shadow-soft: 0 8px 24px rgba(16, 26, 64, 0.08);
  --shadow-card: 0 16px 40px rgba(16, 26, 64, 0.12);
  --shadow-nav: 0 10px 30px rgba(16, 26, 64, 0.08);
  --ease-spring: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-smooth: cubic-bezier(0.65, 0, 0.35, 1);

  /* Layout — Quiet International: more air at the edges */
  --margin-desktop: 80px;
  --margin-mobile: 24px;
  --gutter: 24px;
  --max-width: 1440px;
  --hairline: 1px;
  --nav-height: 72px;
  /* Utility strip above the nav. Zero on small screens, where it is hidden, so
     every `--head-height` consumer stays correct without a second override. */
  --topbar-height: 0px;
  --head-height: calc(var(--nav-height) + var(--topbar-height));
}

/* --- Reset ------------------------------------------------------------- */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0 solid var(--outline-variant);
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--head-height) + 32px);
}

body {
  background: var(--surface);
  color: var(--on-surface);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* `height: auto` matters here. The width/height attributes on every <img> are
   presentational hints that map to CSS width/height, so without this an image
   whose rule only sets `width: 100%` renders at its literal attribute height —
   a 638px-wide photo stretched to 1050px tall, overriding its aspect-ratio.
   Component rules that set a real height are class-level and still win. */
img,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
  background: none;
  border-radius: 0;
}

button {
  cursor: pointer;
}

ul {
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-color: var(--brand);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* --- Typography scale ---------------------------------------------------
   Open Sans gives the site the familiar, straightforward corporate tone used
   by established construction and manufacturing businesses.
   ------------------------------------------------------------------------- */
.t-headline-lg {
  font-family: var(--font-display);
  font-size: var(--text-h1);
  font-weight: 700;
  line-height: 1.04;
  letter-spacing: -0.025em;
  text-transform: uppercase;
  color: var(--brand);
}

.t-headline-md {
  font-family: var(--font-display);
  font-size: var(--text-h2);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--brand);
}

.t-headline-sm {
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: var(--brand);
}

/* Below ~400px the 40px floor is too wide for a single long word set in caps.
   "MANUFACTURING" on its own runs past the page margin, and because body clips
   overflow-x that shows up as silently cropped letters rather than a scrollbar
   you could notice. Caps are wider than the mixed-case serif this replaced, so
   the floor has to come down with the viewport. */
@media (max-width: 399px) {
  .t-headline-lg {
    font-size: clamp(24px, 7.3vw, 32px);
  }

  .t-headline-md {
    font-size: clamp(20px, 6.1vw, 26px);
  }

  /* The home hero's bigger scale needs its own floor — "INDUSTRIAL PRECISION"
     in caps must never run past the page margin (body clips overflow-x, so
     overflow shows up as silently cropped letters, not a scrollbar). */
  .hero__title {
    font-size: clamp(26px, 8vw, 32px);
  }
}

@media (max-width: 480px) {
  .hero__title {
    font-size: clamp(28px, 8.4vw, 38px);
  }
}

/* Small caps label. Was monospace; monospace now earns its place only on
   measured values, where character alignment actually means something. */
.t-label {
  font-family: var(--font-display);
  font-size: var(--text-ui);
  font-weight: 700;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.t-mono {
  font-family: var(--font-body);
  font-size: var(--text-data);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.02em;
  font-variant-numeric: tabular-nums;
}

.t-body-lg {
  font-size: var(--text-lede);
  line-height: 1.6;
}

.t-body {
  font-size: var(--text-body);
  line-height: 1.6;
}

.muted {
  color: var(--on-surface-variant);
}

.secondary {
  color: var(--secondary);
}

.accent {
  color: var(--accent);
}

/* --- Layout primitives -------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: var(--margin-mobile);
}

.section {
  padding-block: 72px;
}

.section--tight {
  padding-block: 56px;
}

/* Phones — cut the desktop air. 96px section pads stacked eight times were
   adding nearly a full viewport of empty scroll before any real content. */
@media (max-width: 767px) {
  .section {
    padding-block: 52px;
  }

  .section--tight {
    padding-block: 44px;
  }

  .home-head {
    margin-bottom: 40px;
  }

  .svc-card {
    padding: 22px 20px 20px;
  }

  .svc-card__title {
    min-height: 0;
  }

  .hero__slide {
    padding-block: 108px 56px;
  }
}

/* Small accent marks follow the same light/dark split as accent text. A pure
   yellow 9px square on a near-white surface is 1.71:1 and effectively vanishes;
   graphical objects need 3:1 to be perceivable. So the markers run amber on
   light and full yellow on the dark bands, where yellow is at its best. */
.rule {
  display: block;
  width: 28px;
  height: 2px;
  background: var(--accent-ink);
}

.bg-brand .rule,
.bg-ink .rule {
  background: var(--accent);
}

/* Section opener — Quiet: thin yellow rule, not a square block. */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 18px;
  color: var(--accent-ink);
  font-size: var(--text-micro);
  letter-spacing: 0.14em;
}

.eyebrow::before {
  content: "";
  flex: none;
  width: 20px;
  height: 2px;
  background: var(--accent-ink);
}

.bg-brand .eyebrow::before,
.bg-ink .eyebrow::before {
  background: var(--accent);
}

.section-head {
  margin-bottom: 40px;
}

.section-head .eyebrow {
  margin-bottom: 14px;
}

.section-head .t-headline-md,
.section-head .t-headline-lg {
  max-width: 22ch;
}

.bg-white {
  background: var(--surface-lowest);
}

.bg-container {
  background: var(--surface-container);
}

/* --- Coloured bands -----------------------------------------------------
   Flat brand surfaces keep the page closer to established corporate
   manufacturing sites and give photography and content the visual priority. */
.bg-brand {
  background-color: var(--brand);
  color: var(--on-dark);
}

.bg-ink {
  background-color: var(--brand-ink);
  color: var(--on-dark);
}

.bg-wash {
  background: var(--brand-wash);
}

.bg-brand .t-headline-lg,
.bg-brand .t-headline-md,
.bg-brand .t-headline-sm,
.bg-ink .t-headline-lg,
.bg-ink .t-headline-md,
.bg-ink .t-headline-sm {
  color: var(--on-dark);
}

.bg-brand .eyebrow,
.bg-ink .eyebrow {
  color: var(--on-dark);
}

.bg-brand .muted,
.bg-ink .muted,
.bg-brand .secondary,
.bg-ink .secondary {
  color: var(--on-dark-variant);
}

.border-y {
  border-block: var(--hairline) solid var(--outline-variant);
}

.border-b {
  border-bottom: var(--hairline) solid var(--outline-variant);
}

/* Hover-reactive technical values — the signature interaction of this design. */
.value {
  display: inline-block;
  transition: color 0.1s, transform 0.1s;
}

.value:hover {
  color: var(--accent-ink);
  transform: scale(1.05);
}

/* Scroll reveal.
   Visible by DEFAULT. Only the inline head script (which also arms a failsafe)
   adds `.js`, which opts the page into the hidden-then-reveal behaviour. So a
   blocked, 404'd or broken main.js leaves a readable page rather than a blank one. */
.fade-up {
  opacity: 1;
  transform: none;
}

.js .fade-up {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.225s ease, transform 0.225s ease;
}

.js .fade-up.is-visible {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .fade-up,
  .js .fade-up {
    opacity: 1;
    transform: none;
  }
}

.sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 200;
  padding: 12px 20px;
  background: var(--primary);
  color: var(--on-primary);
  transition: top 0.1s;
}

.skip-link:focus {
  top: 8px;
}

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 15px 28px;
  background: var(--brand);
  color: var(--on-primary);
  font-family: var(--font-display);
  font-size: var(--text-ui);
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  transition: background 0.1s, transform 0.075s, box-shadow 0.1s;
}

/* While the enquiry form is mid-send the button is disabled; without a
   visible state the only signal is the label text, so double-taps follow. */
.btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}

.btn:disabled:hover {
  background: var(--brand);
  box-shadow: none;
}

.btn:hover {
  background: var(--brand-deep);
  box-shadow: 0 10px 24px rgba(42, 62, 150, 0.26);
}

.btn:active {
  transform: scale(0.97);
}

.btn .icon {
  width: 16px;
  height: 16px;
  transition: transform 0.1s;
}

.btn:hover .icon {
  transform: translateX(3px);
}

/* The one orange button per page — reserved for the action we actually want. */
.btn--accent {
  background: var(--accent);
  color: var(--on-accent);
}

.btn--accent:hover {
  background: var(--accent-deep);
  box-shadow: 0 10px 24px rgba(234, 106, 16, 0.35);
}

/* On a blue band a blue button disappears, so it inverts. */
.bg-brand .btn,
.bg-ink .btn {
  background: var(--on-dark);
  color: var(--brand);
}

.bg-brand .btn:hover,
.bg-ink .btn:hover {
  background: var(--accent);
  color: var(--on-accent);
}

/* The hero sits on a soft navy wash over photography, so the secondary
   action outlines in white rather than filling navy (which disappears into
   the scrim). Accent stays the primary push. */
.hero .btn:not(.btn--accent) {
  background: transparent;
  color: var(--on-dark);
  border: 1.5px solid rgba(255, 255, 255, 0.55);
}

.hero .btn:not(.btn--accent):hover {
  background: var(--on-dark);
  color: var(--brand);
  border-color: var(--on-dark);
}

.btn--block {
  width: 100%;
  padding-block: 22px;
  letter-spacing: 0.2em;
}

.btn--block:hover {
  background: var(--brand-deep);
  box-shadow: 0 12px 28px rgba(16, 26, 64, 0.24);
  transform: translateY(-2px);
}

.btn-text {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  transition: color 0.1s;
}

.btn-text:hover {
  color: var(--accent-ink);
}

.btn-text .icon {
  width: 18px;
  height: 18px;
  transition: transform 0.1s;
}

.btn-text:hover .icon {
  transform: translateX(8px);
}

/* Inline SVG icons. The four glyphs this site needs used to cost a 1.1 MB
   Material Symbols webfont; these are a few hundred bytes total. */
.icon {
  display: block;
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* --- Site header — utility strip above a nav with a solid logo block ------ */

/* The whole header travels as one fixed unit so the utility strip scrolls with
   the bar rather than sliding under it. */
.site-head {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

.topbar {
  display: none;
  height: var(--topbar-height);
  background: var(--surface-lowest);
  border-bottom: var(--hairline) solid var(--outline-variant);
  color: var(--on-surface-variant);
  font-family: var(--font-body);
  font-size: var(--text-micro);
}

.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 100%;
}

.topbar__group {
  display: flex;
  align-items: center;
  gap: 26px;
  min-width: 0;
}

.topbar__item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.topbar__item .icon {
  width: 14px;
  height: 14px;
  color: var(--accent-ink);
  stroke-width: 1.9;
}

a.topbar__item {
  transition: color 0.1s;
}

a.topbar__item:hover {
  color: var(--brand);
}

.nav {
  position: relative;
  display: flex;
  align-items: center;
  gap: 24px;
  width: 100%;
  max-width: none;
  height: var(--nav-height);
  /* Both insets match the drawer / page margin so the logo, the hamburger and
     the drawer links share the same two vertical edges. */
  padding: 0 var(--margin-mobile);
  background: rgba(255, 255, 255, 0.94);
  /* Hairline is drawn with ::after so it does not shrink the content box and
     leave a pale seam under the bar. */
  border-bottom: 0;
  transition: box-shadow 0.15s, background 0.15s;
}

.nav::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 0;
  height: var(--hairline);
  background: var(--outline-variant);
  pointer-events: none;
}

/* The bar carries no backdrop-filter in either state. A blurred, full-width
   position:fixed strip is re-sampled and re-blurred on every scroll frame,
   and Safari pays that far more heavily than Chrome. The tint alone holds
   the surface now — 0.94 at the top over hero imagery, 0.96 once scrolled. */
.nav.is-scrolled {
  background: rgba(255,255,255,0.96);
  box-shadow: var(--shadow-nav);
}

/* The mark sits on the bar itself. It used to be set in a solid orange block
   flush to the left edge; the client asked for the block removed, so the logo
   now starts on the page margin like every other first element on the page.

   Nothing replaced the block, though, and the mark was left floating: the link
   row began right after it with no boundary, so the bar read as one undivided
   run of items rather than a brand followed by navigation. A hairline closes
   the brand zone off instead. Structure, not colour — the bar already carries
   three colour events (blue mark, red links, orange Enquire) and a fourth
   would put a second orange in the header competing with the CTA, which is
   the argument that got the block removed in the first place. */
.nav__logo {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  align-self: stretch;
  flex-shrink: 0;
  height: 100%;
  margin: 0;
  padding-inline: 0;
}

/* Only where the link row is actually rendered. Below 1350px navigation is the
   hamburger at the far edge, so there is nothing on the right to divide from
   and the rule would just be a mark hanging in space.

   The rule pins to the padding edge, so mark-to-rule is whatever padding-inline
   the 900px block sets (30px) and rule-to-first-link is the bar's own gap.
   Do not set padding-right here to tune it: that block is further down the
   file and wins on source order at equal specificity. */
@media (min-width: 1350px) {
  .nav__logo::after {
    content: "";
    position: absolute;
    top: 50%;
    right: 0;
    width: var(--hairline);
    height: 46%;
    transform: translateY(-50%);
    background: var(--outline-variant);
  }
}

.nav__logo img {
  height: 42px;
  width: auto;
  max-width: min(285px, 60vw);
  object-fit: contain;
  object-position: left center;
}

/* The gap is fluid on purpose. The logo block is wide and fixed, the actions
   are fixed, so the link row is the only thing that can absorb the difference
   between a 1200px laptop and a 1600px display. A static gap either clipped
   the Enquire button at the narrow end or left a hole at the wide end. */
.nav__links {
  display: none;
  flex: 1 1 auto;
  min-width: 0;
  gap: clamp(18px, 1.9vw, 34px);
  align-items: center;
  justify-content: flex-start;
  padding-left: 16px;
}

.nav__link {
  position: relative;
  padding-block: 6px;
  padding-bottom: 4px;
  font-family: var(--font-display);
  white-space: nowrap;
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--nav-link);
  transition: color 0.1s;
}

.nav__link:hover,
.nav__link.is-active {
  color: var(--nav-link-hover);
}

.nav__actions {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-left: auto;
  flex: none;
}

.nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  /* 44px hit area — glyph stays 26px and centred. Pull only the right edge
     into the nav padding so the bars sit on the page margin, not floating
     inside a dead strip. */
  width: 44px;
  height: 44px;
  margin: 0 -10px 0 0;
  padding: 0;
  color: var(--primary);
  background: transparent;
  border: 0;
  line-height: 0;
}

.nav__toggle .icon {
  display: block;
  width: 26px;
  height: 26px;
  stroke-width: 1.75;
}

/* Menu / close swap rides on the aria state the JS already maintains. */
.nav__toggle .icon-close,
.nav__toggle[aria-expanded="true"] .icon-menu {
  display: none;
}

.nav__toggle[aria-expanded="true"] .icon-close {
  display: block;
}

.nav__drawer {
  position: fixed;
  /* Sit under the fixed header rather than covering it — the close control
     stays reachable and the first link lines up with the page margin. */
  top: var(--head-height);
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: stretch;
  gap: 0;
  padding: 12px var(--margin-mobile) 40px;
  overflow-y: auto;
  background: linear-gradient(180deg, var(--brand-tint), transparent 40%), var(--surface-lowest);
  transform: translateY(-100%);
  visibility: hidden;
  transition: transform 0.225s cubic-bezier(0.16, 1, 0.3, 1), visibility 0.225s;
}

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

.nav__drawer a {
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: 0;
  /* Hairlines run edge to edge; the label stays on the page margin so it
     lines up with the hamburger and the rest of the layout. */
  margin-inline: calc(-1 * var(--margin-mobile));
  padding-inline: var(--margin-mobile);
  border-bottom: var(--hairline) solid var(--outline-variant);
  font-family: var(--font-headline);
  font-size: clamp(20px, 5.5vw, 28px);
  font-weight: 700;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--brand);
  line-height: 1;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.2s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.2s cubic-bezier(0.16, 1, 0.3, 1), color 0.1s;
}

.nav__drawer a:hover {
  color: var(--accent-ink);
}

/* Last item is the enquire action — separate it slightly so it reads as the
   conversion control rather than another page link. */
.nav__drawer a:last-child {
  margin-top: 12px;
  border-bottom: 0;
  color: var(--accent-ink);
}

/* --- Hero — full-bleed plant photography, light type on a soft navy scrim -
   The photograph runs edge to edge. A thin navy wash on the left clears
   contrast for white headlines without bleaching the plant out of the frame.
   ------------------------------------------------------------------------- */
/* The slider frame. The block that used to carry the padding and centring is
   now .hero__slide — the hero itself is just the window the track scrolls
   inside, so it owns the overflow clip and nothing else. */
.hero {
  position: relative;
  overflow: hidden;
  width: 100%;
  background: #0c1536;
  color: var(--on-surface);
  isolation: isolate;
}

.hero__track {
  display: flex;
  width: 100%;
  touch-action: pan-y;
  /* Horizontal scroll between slides. transform is compositor-only, so this
     stays smooth even with a 1400px photograph in each slide. */
  transition: transform 0.3s cubic-bezier(0.65, 0, 0.35, 1);
  will-change: transform;
}

.hero__slide {
  position: relative;
  display: flex;
  flex: 0 0 100%;
  width: 100%;
  min-width: 100%;
  max-width: 100%;
  flex-direction: column;
  justify-content: center;
  /* On a phone `vh` resolves against the LARGE viewport — the height the page
     would have with the browser toolbars retracted — so 86vh renders taller
     than what is actually on screen while the toolbar is showing. svh is the
     small viewport, which is what the visitor can really see. The vh line
     stays first as the fallback for anything without svh. */
  min-height: 88vh;
  min-height: 88svh;
  padding-block: 132px 84px;
  overflow: hidden;
}

.hero::before {
  display: none;
}

.hero::after {
  display: none;
}

.hero__photo {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero__photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
  /* Mild lift only — the dark scrim already protects type, so a heavy grade
     just washes the plant out of the frame again. Parallax is driven via
     --parallax-y in JS; fallback is 0. */
  filter: brightness(1.08) contrast(1.04) saturate(0.95);
  transform: translateY(var(--parallax-y, 0)) scale(1.04);
  will-change: transform;
  transition: transform 0.05s linear;
}

/* Two stops carry the work. A navy wash on the left clears contrast for light
   type without bleaching the photograph — the machines have to stay visible,
   which is the whole point of putting one behind the type. The left stops run
   deep because the gear-cutting frame is bright polished steel exactly where
   the headline sits; a lighter wash left the type at roughly 2:1.
   v2 adds a faint spotlight vignette + hairline top fade so the nav reads. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(900px 520px at 28% 42%, rgba(255,255,255,0.08) 0%, rgba(255,255,255,0) 62%),
    linear-gradient(
      180deg,
      rgba(16, 26, 64, 0.48) 0%,
      rgba(16, 26, 64, 0.12) 22%,
      rgba(16, 26, 64, 0) 38%
    ),
    linear-gradient(
      90deg,
      rgba(16, 26, 64, 0.88) 0%,
      rgba(16, 26, 64, 0.72) 28%,
      rgba(16, 26, 64, 0.42) 50%,
      rgba(16, 26, 64, 0.14) 70%,
      rgba(16, 26, 64, 0) 86%
    );
}

.hero__grain {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.18;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160' viewBox='0 0 160 160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.35'/%3E%3C/svg%3E");
  background-size: 160px 160px;
  mix-blend-mode: soft-light;
}

.hero__vignette {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(120% 85% at 50% 100%, rgba(0,0,0,0) 55%, rgba(8,14,38,0.32) 100%);
}

/* On phones the copy sits over the full frame. A lighter vertical fade keeps
   the headline readable and still lets the plant show under the buttons. */
@media (max-width: 899px) {
  .hero__scrim {
    background: linear-gradient(
      180deg,
      rgba(16, 26, 64, 0.55) 0%,
      rgba(16, 26, 64, 0.34) 42%,
      rgba(16, 26, 64, 0.14) 74%,
      rgba(16, 26, 64, 0.04) 100%
    );
  }

  .hero__lede {
    max-width: none;
  }
}

.hero__shader {
  display: none;
}

.hero__art {
  display: none;
}

/* The wrap keeps the page margin; the children carry the measure. */
.hero__inner {
  position: relative;
  z-index: 1;
}

.hero__kicker {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 18px;
  padding: 8px 12px;
  background: rgba(12, 21, 54, 0.78);
  border: 1px solid rgba(255,255,255,0.22);
  border-radius: var(--radius-pill);
  color: rgba(255,255,255,0.92);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}

.hero__kicker-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 6px rgba(234,106,16,0.18);
  flex: none;
}

.hero__proof {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
  margin-top: 22px;
  align-items: center;
}

.hero__proof-item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(255,255,255,0.92);
  border: 1px solid rgba(207,218,234,0.9);
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand);
  box-shadow: var(--shadow-soft);
}

.hero__proof-item--ghost {
  background: rgba(12, 21, 54, 0.78);
  border-color: rgba(255,255,255,0.26);
  color: rgba(255,255,255,0.92);
  box-shadow: none;
}

/* 720px forced "INDUSTRIAL DRIVES." onto two lines, which put slide 1 at four
   lines against slide 2's two — and in a slider an uneven headline moves the
   buttons and the controls every time it advances. 880px lets every headline
   in HERO_SLIDES sit on two lines; .hero__lede keeps its own 44ch measure so
   the body copy does not stretch with it. */
.hero__inner > * {
  max-width: 880px;
}

/* Slide 1 is the page's <h1>; any later slide repeats the same look with a
   <p> so the page keeps exactly one top-level heading. Both carry
   .hero__title, so the styling has to hang off the class, not the tag.

   The two-line min-height reserve that used to sit here existed only to stop
   the lede and buttons drifting as the slider advanced. HERO_SLIDES is a
   single static slide now, so there is nothing to hold still. */
.hero__title {
  position: relative;
  z-index: 1;
  margin-bottom: 18px;
  color: var(--on-dark);
  font-size: clamp(36px, 5.1vw, 64px);
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 0.98;
  text-wrap: balance;
  text-shadow: 0 2px 22px rgba(16, 26, 64, 0.42), 0 1px 0 rgba(16,26,64,0.18);
}

.hero__title .accent {
  display: block;
  color: var(--accent);
  font-weight: 800;
}

.hero__lede {
  max-width: 46ch;
  margin-bottom: 0;
  /* Near-solid rather than the 0.86 it carried over the old photograph: this
     frame runs a bright polished edge diagonally through the third line. */
  color: rgba(255, 255, 255, 0.94);
  line-height: 1.62;
  font-size: clamp(16px, 1.35vw, 18px);
  text-wrap: pretty;
  text-shadow: 0 1px 12px rgba(16, 26, 64, 0.55);
}


.hero__cert {
  display: none;
  margin-top: 28px;
  animation: heroIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.32s both;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 28px;
  animation: heroIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.4s both;
}

.hero__actions .btn {
  min-height: 48px;
  border-radius: var(--radius-pill);
  box-shadow: 0 10px 24px rgba(16,26,64,0.18);
}

.hero__actions .btn:not(.btn--accent) {
  background: rgba(12, 21, 54, 0.78);
  border: 1px solid rgba(255,255,255,0.26);
  color: #fff;
  box-shadow: none;
}

.hero__actions .btn:not(.btn--accent):hover {
  background: rgba(12, 21, 54, 0.92);
  border-color: rgba(255,255,255,0.26);
  color: #fff;
}

.hero__stats {
  display: none;
  animation: heroIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.5s both;
}

.hero__scroll {
  display: none;
}

/* --- Proof / ticker — Quiet International v2 --------------------------- */
.proof-strip {
  background: var(--surface-lowest);
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.proof-strip__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 24px;
  padding-block: 28px;
}

.proof-strip__item {
  font-family: var(--font-display);
  font-size: var(--text-ui);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-surface-variant);
}

.proof-strip__sep {
  display: none;
  width: 1px;
  height: 16px;
  background: var(--outline-variant);
  flex-shrink: 0;
}

@media (min-width: 900px) {
  .proof-strip__sep {
    display: block;
  }
}

/* Infinite marquee — industries ticker */
.ticker {
  background: var(--brand-ink);
  color: var(--on-dark);
  border-block: 1px solid rgba(255,255,255,0.08);
  overflow: hidden;
}

.ticker__track {
  display: flex;
  width: max-content;
  animation: tickerMove 28s linear infinite;
  will-change: transform;
}

.ticker:hover .ticker__track {
  animation-play-state: paused;
}

.ticker__item {
  display: inline-flex;
  align-items: center;
  gap: 18px;
  padding: 16px 18px;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.92);
}

.ticker__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 6px rgba(234,106,16,0.16);
  flex: none;
}

@keyframes tickerMove {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

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

/* --- Stats strip — single trust band, even column rhythm ----------------
   v2: subtle top accent hairline + number reveal */
.stats-strip {
  position: relative;
  background: var(--surface-lowest);
  border-block: var(--hairline) solid var(--outline-variant);
  overflow: hidden;
}

.stats-strip::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent) 0%, rgba(234,106,16,0) 62%);
  opacity: 0.9;
}

.stats-strip__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 0;
  row-gap: 0;
  padding-block: 0;
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  min-width: 0;
  padding: 40px 28px;
  border: 0;
  border-bottom: var(--hairline) solid var(--outline-variant);
  border-right: var(--hairline) solid var(--outline-variant);
}

.stat:nth-child(odd) {
  padding-left: 0;
}

.stat:nth-child(even) {
  padding-right: 0;
  border-right: 0;
}

.stat:nth-child(n + 3) {
  border-bottom: 0;
}

/* Two lines per stat, both of them loud. The grey third line that used to sit
   under each one ("Established 1984 · ISO 9001:2015" and friends) came out at
   the client's request — with it gone the number and its label carry the whole
   band, so both step up in size and weight. */
.stat__num {
  font-family: var(--font-display);
  font-size: clamp(46px, 5.6vw, 64px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.04em;
  color: var(--accent-ink);
  font-variant-numeric: tabular-nums;
}

.stat__num.is-counting {
  opacity: 0.92;
}

.stat__label {
  font-family: var(--font-display);
  /* Two columns on a phone leave each label about 130px of content box, and
     "MANUFACTURING" set at the full 16px runs straight through the divider
     into the next cell. The floor is what the label used to be set at. */
  font-size: clamp(13px, 3.2vw, 16px);
  font-weight: 800;
  line-height: 1.3;
  /* Tighter tracking than the 0.08em the small labels use — at 16px the wide
     setting reads airy rather than emphatic. */
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--brand);
}

@media (min-width: 900px) {
  .stats-strip__grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .stat,
  .stat:nth-child(odd),
  .stat:nth-child(even),
  .stat:nth-child(n + 3) {
    padding: 52px 40px;
    border-bottom: 0;
    border-right: var(--hairline) solid var(--outline-variant);
  }

  .stat:first-child {
    padding-left: 0;
  }

  .stat:last-child {
    padding-right: 0;
    border-right: 0;
  }
}

/* --- Capability strip ----------------------------------------------------
   A static, scannable service strip mirrors established construction and
   manufacturing sites. It replaces the decorative moving ticker. */
.capability-strip {
  background: var(--surface-lowest);
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.capability-strip__grid {
  display: grid;
  grid-template-columns: 1fr;
}

.capability-strip__item {
  display: flex;
  min-height: 92px;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  padding: 20px 0;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.capability-strip__item strong {
  color: var(--brand);
  font-size: var(--text-body);
  line-height: 1.3;
}

.capability-strip__item span {
  color: var(--on-surface-variant);
  font-size: var(--text-ui);
}

.capability-strip__item::before {
  content: "";
  width: 32px;
  height: 3px;
  margin-bottom: 5px;
  background: var(--accent);
}

.capability-strip__item:hover strong {
  color: var(--brand-deep);
}

@media (min-width: 640px) {
  .capability-strip__grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .capability-strip__item {
    padding-inline: 24px;
    border-right: var(--hairline) solid var(--outline-variant);
  }
}

@media (min-width: 900px) {
  .capability-strip__grid {
    grid-template-columns: repeat(4, 1fr);
  }

  .capability-strip__item {
    min-height: 118px;
    border-bottom: 0;
  }
}

/* --- Vision ------------------------------------------------------------- */
.vision {
  display: grid;
  gap: 48px;
}

.vision__quote {
  margin-bottom: 40px;
  padding-left: 24px;
  border-left: var(--hairline) solid var(--primary);
  font-family: var(--font-display);
  font-size: var(--text-quote);
  font-style: italic;
  font-weight: 500;
  line-height: 1.3;
}

.vision__body p {
  margin-bottom: 24px;
  color: var(--on-surface-variant);
}

.pillars {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 32px 0;
}

.pillars li {
  padding: 8px 14px;
  border: var(--hairline) solid var(--outline-variant);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* --- Product grid ------------------------------------------------------- */
.products {
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px 32px;
}

.product {
  display: flex;
  flex-direction: column;
}

.product__art {
  display: block;
  position: relative;
  aspect-ratio: 4 / 5;
  margin-bottom: 24px;
  background: var(--surface-container);
  border: var(--hairline) solid var(--outline-variant);
  overflow: hidden;
}

.product__art img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.product:hover .product__art img {
  transform: scale(1.05);
}

.product__head h3 a {
  transition: color 0.1s;
}

.product__head h3 a:hover {
  color: var(--accent-ink);
}

.product__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 16px;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.product__head h3 {
  margin-bottom: 6px;
}

.product__sub {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.05em;
  color: var(--secondary);
}

.product__attr {
  flex-shrink: 0;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-align: right;
  color: var(--accent-ink);
}

.product__body {
  padding-top: 16px;
  font-size: var(--text-body);
  line-height: 1.6;
  color: var(--on-surface-variant);
}

.product__meta {
  margin-top: 14px;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: var(--secondary);
}

.product__meta strong {
  display: block;
  margin-bottom: 4px;
  color: var(--on-surface);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* --- Capability list ---------------------------------------------------- */
.capability {
  display: grid;
  gap: 48px;
}

.cap-list {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.cap-list li {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 20px 8px;
  border-bottom: var(--hairline) solid var(--outline-variant);
  transition: background 0.125s, padding-left 0.125s;
}

.cap-list li:hover {
  background: var(--surface-lowest);
  padding-left: 20px;
}

.cap-list .num {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--accent-ink);
}

.cap-list .name {
  font-size: var(--text-body);
}

/* --- Quality steps ------------------------------------------------------ */
.steps {
  display: grid;
  gap: 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.step {
  display: grid;
  grid-template-columns: 1fr;
  row-gap: 10px;
  padding: 32px 0;
  border-bottom: var(--hairline) solid var(--outline-variant);
  transition: background 0.15s;
}

.step:hover {
  background: rgba(255, 255, 255, 0.6);
}

/* Quiet: typographic stage label, not a filled chip. */
.step__num {
  display: inline-block;
  justify-self: start;
  padding: 0;
  background: transparent;
  color: var(--accent-ink);
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}

.step__body {
  color: var(--on-surface-variant);
  max-width: 62ch;
}

/* --- Reason columns — Quiet: hairlines, no card chrome ------------------- */
.cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

.card {
  position: relative;
  padding: 28px 0;
  border: 0;
  border-bottom: var(--hairline) solid var(--outline-variant);
  background: transparent;
  transition: opacity 0.1s;
}

.card:hover {
  box-shadow: none;
  transform: none;
  opacity: 0.92;
}

.card__num {
  display: inline-block;
  margin-bottom: 14px;
  padding: 0;
  background: transparent;
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--accent-ink);
}

.card h3 {
  margin-bottom: 12px;
}

.card p {
  color: var(--on-surface-variant);
  font-size: var(--text-body);
  line-height: 1.6;
}

/* Home “Why Rotec” — Quiet columnar list */
.reasons {
  gap: 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.reasons .card {
  border: 0;
  border-right: var(--hairline) solid var(--outline-variant);
  border-top: 0;
  background: transparent;
  /* Equal inset from the hairlines — the old 0 left pad sat the copy flush
     against the column rule on every right-hand card. */
  padding: 40px 36px;
  box-shadow: none;
  transform: none;
}

.reasons .card:last-child {
  border-right: 0;
}

.reasons .card:hover {
  border-top-color: transparent;
  box-shadow: none;
  transform: none;
}

.reasons .card__num {
  margin-bottom: 18px;
  padding: 0;
  background: transparent;
  font-size: var(--text-micro);
  letter-spacing: 0.14em;
  color: var(--accent-ink);
}

.reasons .card h3 {
  margin-bottom: 16px;
}

.reasons .card p {
  line-height: 1.65;
}

.reasons .card:hover .card__num {
  background: transparent;
  color: var(--accent-ink);
}

.reasons .card::after {
  content: "";
  position: absolute;
  left: 36px;
  bottom: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: width 0.15s ease;
}

.reasons .card:hover::after {
  width: 48px;
}

@media (min-width: 640px) and (max-width: 1199px) {
  /* Two-up: drop the outer right rule on the right column, and draw a row
     rule between the pairs so the second row isn’t jammed under the first. */
  .reasons .card:nth-child(2n) {
    border-right: 0;
  }

  .reasons .card:nth-child(n + 3) {
    border-top: var(--hairline) solid var(--outline-variant);
  }
}

@media (max-width: 639px) {
  .reasons .card {
    border-right: 0;
    border-bottom: var(--hairline) solid var(--outline-variant);
    padding: 32px 0;
  }

  .reasons .card:last-child {
    border-bottom: 0;
  }

  .reasons .card::after {
    left: 0;
  }
}

.split {
  display: grid;
  gap: 40px;
}

.split__aside p {
  max-width: 42ch;
  margin-bottom: 32px;
  color: var(--on-surface-variant);
}

.split__aside .rule,
.capability .rule,
.cert-split .rule {
  margin-top: 32px;
}

/* --- Contact ------------------------------------------------------------ */
.contact-box {
  display: grid;
  grid-template-columns: 1fr;
  border: var(--hairline) solid var(--outline-variant);
  background: var(--surface-lowest);
}

.contact-form-side {
  padding: 40px var(--margin-mobile);
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.contact-form-side h2 {
  margin-bottom: 48px;
}

.form {
  display: flex;
  flex-direction: column;
  gap: 36px;
}

.field {
  position: relative;
  /* A grid item's automatic minimum is its content's min-content width, and an
     <input> reports roughly 20 characters regardless of `width: 100%`. Without
     this the enquiry form holds its column open at ~343px and pushes the page
     wider than a 320px phone. */
  min-width: 0;
}

/* Honeypot for enquiry spam bots — must stay off-screen, not display:none. */
.field--hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.field label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  /* Labels are text, not a hairline — --outline (#93a4bc) measured 2.4:1
     here and failed badly. Secondary keeps the muted register but reads. */
  color: var(--secondary);
  transition: color 0.1s;
}

.field:focus-within label {
  color: var(--primary);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  /* Form controls carry an intrinsic width (input size=20, textarea cols=20)
     that `width: 100%` does not remove. It propagates up through every grid
     ancestor as an automatic minimum, so it has to be cleared here too, not
     just on `.field`. */
  min-width: 0;
  padding: 8px 0;
  border-bottom: var(--hairline) solid var(--outline);
  font-family: var(--font-mono);
  font-size: var(--text-data);
  letter-spacing: 0.05em;
  transition: border-color 0.1s;
}

.field textarea {
  resize: vertical;
  min-height: 84px;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--primary);
}

.field--select {
  position: relative;
}

.field--select .caret {
  position: absolute;
  right: 4px;
  bottom: 12px;
  pointer-events: none;
  color: var(--outline);
}

.field select {
  appearance: none;
  cursor: pointer;
}

.form__note {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.05em;
  color: var(--secondary);
}

.form__status {
  min-height: 18px;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.05em;
  color: var(--accent-ink);
}

.contact-map-side {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 380px;
  padding: 40px var(--margin-mobile);
  overflow: hidden;
  background: var(--surface-container);
}

.contact-map-side::before {
  display: none;
}

.hq {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 420px;
  padding: 0;
  background: transparent;
  border: 0;
  border-top: var(--hairline) solid var(--outline-variant);
  padding-top: 28px;
}

.hq:hover {
  box-shadow: none;
  transform: none;
}

.hq h3 {
  margin-bottom: 20px;
}

.hq p {
  margin-bottom: 28px;
  color: var(--on-surface-variant);
}

.hq__est {
  padding-top: 20px;
  border-top: var(--hairline) solid var(--outline-variant);
  font-family: var(--font-mono);
  font-size: var(--text-data);
  letter-spacing: 0.05em;
  color: var(--accent-ink);
}

/* --- Footer --------------------------------------------------------------
   Solid brand blue, which is where the sample the client approved puts it too.
   It also gives the white logo variant somewhere to live.

   Layout:
     phone     — brand/address/square map → nav → enquire
     tablet    — brand/map | enquire / products | company
     desktop   — brand/map | products | company | enquire
   -------------------------------------------------------------------------- */
.footer {
  margin-top: 0;
  padding-block: 56px 28px;
  background: var(--brand-ink);
  color: var(--on-dark);
  border-top: 0;
}

.footer__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 36px;
  align-items: start;
}

.footer__col {
  min-width: 0;
}

.footer h2 {
  margin-bottom: 16px;
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent);
}

.footer__logo {
  height: 40px;
  width: auto;
  max-width: min(220px, 100%);
  margin-bottom: 20px;
}

.footer__contact {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 20px;
}

.footer__map {
  width: min(100%, 280px);
}

.footer__map iframe {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  border: 0;
  background: var(--surface-container);
}

.footer__map-open {
  display: inline-block;
  margin-top: 10px;
  padding-block: 10px;
  color: var(--on-dark-variant);
  font-size: var(--text-data);
  line-height: 1.45;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 4px;
}

.footer__map-open:hover { color: var(--on-dark); }
.footer__map-open:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

.footer__col--nav ul {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* :not(.btn) keeps its hands off the CTA button — this selector is two
   classes wide and would otherwise out-specify .btn--accent, painting the
   orange button's label 76%-white (2.4:1) and resizing its type. */
.footer__col a:not(.btn),
.footer__col p {
  color: var(--on-dark-variant);
  font-size: var(--text-data);
  line-height: 1.45;
  transition: color 0.1s;
}

.footer__col a:not(.btn):hover {
  color: var(--on-dark);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
}

.footer__col--brand .iso-badge {
  margin-top: 4px;
}

.subscribe {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
  max-width: 360px;
  gap: 0;
}

.subscribe input {
  flex: 1 1 160px;
  min-width: 0;
  padding: 14px 16px;
  background: var(--surface-lowest);
  border: var(--hairline) solid transparent;
  color: var(--on-surface);
  transition: border-color 0.1s;
}

.subscribe input:focus {
  outline: none;
  border-color: var(--accent);
}

.subscribe button {
  padding: 14px 22px;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--font-display);
  font-size: var(--text-ui);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background 0.1s;
}

.subscribe button:hover {
  background: var(--accent-deep);
}

.footer-cta {
  margin-bottom: 24px;
  padding: 0 0 24px;
  border: 0;
  border-bottom: var(--hairline) solid rgba(255, 255, 255, 0.18);
  background: transparent;
}

.footer-cta h2 {
  margin-bottom: 12px;
}

.footer-cta__title {
  margin-bottom: 12px;
  font-family: var(--font-display);
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--on-dark);
}

.footer-cta p {
  margin-bottom: 18px;
  max-width: 34ch;
  color: var(--on-dark-variant);
}

.footer-cta .btn {
  width: auto;
}

.footer__base {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin-top: 40px;
  padding-top: 24px;
  border-top: var(--hairline) solid rgba(255, 255, 255, 0.25);
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.05em;
  color: var(--on-dark-variant);
  text-align: center;
}

/* --- Responsive --------------------------------------------------------- */
@media (min-width: 640px) {
  .products {
    grid-template-columns: repeat(2, 1fr);
  }
  .cards {
    grid-template-columns: repeat(2, 1fr);
  }
  .hero__scroll {
    display: block;
  }
  .step {
    grid-template-columns: 92px 1fr;
    column-gap: 24px;
  }
  .step__num {
    grid-column: 1;
    grid-row: 1 / span 2;
    padding-top: 6px;
  }
  .step__title,
  .step__body {
    grid-column: 2;
  }
  .footer__grid {
    grid-template-columns: 1.15fr 1fr;
    gap: 48px 56px;
  }
  /* Brand | Enquiries on row 1; Products | Company on row 2 — keeps the
     enquire block from crushing the link lists into narrow strips. */
  .footer__col--brand { order: 1; }
  .footer__col--enquire { order: 2; }
  .footer__col--nav:nth-of-type(2) { order: 3; }
  .footer__col--nav:nth-of-type(3) { order: 4; }
  .footer__base {
    flex-direction: row;
    justify-content: space-between;
    text-align: left;
  }
}

@media (min-width: 900px) {
  .wrap {
    padding-inline: var(--margin-desktop);
  }
  :root {
    --topbar-height: 40px;
    --nav-height: 88px;
  }
  .topbar {
    display: block;
  }
  .topbar__inner {
    padding-inline: var(--margin-desktop);
  }
  .nav {
    width: 100%;
    /* Asymmetric on purpose. The left inset is the page margin so the mark
       starts on the same edge as the topbar above it and the page content
       below it. The right stays at the mobile margin while the hamburger is
       still on screen — jumping that side to --margin-desktop left an 80px
       dead strip beside the toggle on every laptop below the 1350px link row. */
    padding: 0 var(--margin-mobile) 0 var(--margin-desktop);
    gap: 32px;
    border: 0;
  }
  /* Right side only. This padding sets mark-to-rule for the ::after divider;
     mirroring it on the left pushed the mark 30px past the page margin, so the
     logo overhung every other first element on the page. */
  .nav__logo {
    padding-inline: 0 30px;
  }
  .nav__logo img {
    height: 46px;
    max-width: 325px;
  }
  .section {
    padding-block: 80px;
  }
  .section--tight {
    padding-block: 64px;
  }
  .hero__slide {
    /* The fixed desktop header is 128px tall (utility bar + navigation).
       Give the first hero label its own 32px breathing band beneath that
       chrome instead of letting it begin almost flush with the nav rule. */
    padding-block: calc(var(--head-height) + 32px) 84px;
  }
  /* The base clamp carries the size — an earlier 24px override here quietly
     shrank the stats on desktop, the exact opposite of the intent. */
  .vision {
    grid-template-columns: 5fr 1fr 5fr 1fr;
  }
  .vision__quote-col {
    grid-column: 1;
  }
  .vision__body {
    grid-column: 3;
  }
  .vision__quote {
    padding-left: 48px;
  }
  .products {
    grid-template-columns: repeat(3, 1fr);
  }
  .capability {
    grid-template-columns: 4fr 7fr;
    gap: 56px;
  }
  .cap-list {
    align-self: start;
  }
  .split {
    grid-template-columns: 4fr 7fr;
    gap: 56px;
  }
  .split__aside {
    position: sticky;
    top: 160px;
    align-self: start;
  }
  .cards--three {
    grid-template-columns: repeat(2, 1fr);
    gap: 0 48px;
    border-top: var(--hairline) solid var(--outline-variant);
  }
  .cards--three .card {
    padding-top: 28px;
  }
  .contact-box {
    grid-template-columns: 1fr 1fr;
  }
  .contact-form-side {
    padding: 64px;
    border-bottom: 0;
    border-right: var(--hairline) solid var(--outline-variant);
  }
  .contact-map-side {
    padding: 64px;
  }
  .footer {
    padding-block: 72px 40px;
  }
  .footer__logo {
    height: 46px;
    margin-bottom: 24px;
  }
  .footer__contact {
    gap: 10px;
    margin-bottom: 24px;
  }
  .footer__col--nav ul {
    gap: 12px;
  }
  .footer-cta {
    margin-bottom: 28px;
    padding-bottom: 28px;
  }
  .footer-cta p {
    margin-bottom: 20px;
  }
  .footer__base {
    margin-top: 56px;
    padding-top: 28px;
  }
}

@media (min-width: 1100px) {
  .footer__grid {
    grid-template-columns:
      minmax(200px, 1.35fr)
      minmax(140px, 0.85fr)
      minmax(140px, 0.85fr)
      minmax(220px, 1.2fr);
    gap: 40px 48px;
  }

  .footer__col--brand,
  .footer__col--enquire,
  .footer__col--nav:nth-of-type(2),
  .footer__col--nav:nth-of-type(3) {
    order: 0;
  }
}

@media (min-width: 1200px) {
  .cards--three {
    grid-template-columns: repeat(2, 1fr);
  }
  .reasons {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* --- Legal / prose pages ------------------------------------------------ */
.legal {
  padding-top: 180px;
}

.prose {
  max-width: 68ch;
}

.prose p,
.prose ul {
  margin-bottom: 24px;
  color: var(--on-surface-variant);
  font-size: var(--text-prose);
  line-height: 1.65;
}

.prose h2 {
  margin-top: 48px;
  margin-bottom: 16px;
  color: var(--on-surface);
}

.prose ul {
  padding-left: 0;
}

.prose li {
  position: relative;
  margin-bottom: 10px;
  padding-left: 24px;
}

.prose li::before {
  content: "";
  position: absolute;
  top: 12px;
  left: 0;
  width: 12px;
  height: var(--hairline);
  background: var(--accent-ink);
}

.prose a {
  border-bottom: var(--hairline) solid var(--outline-variant);
  transition: border-color 0.1s, color 0.1s;
}

.prose a:hover {
  color: var(--accent-ink);
  border-color: var(--accent);
}

.prose .btn-text {
  border-bottom: 0;
}

/* ==========================================================================
   Sub-page components
   ========================================================================== */


/* --- Page hero — Quiet -------------------------------------------------- */
.page-hero {
  padding-top: calc(var(--head-height) + 48px);
  padding-bottom: 48px;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.page-hero h1 {
  margin-bottom: 16px;
  max-width: 18ch;
}

.page-hero__lede {
  max-width: 54ch;
  color: var(--on-surface-variant);
}

.page-hero__meta {
  margin-top: 24px;
  padding-top: 16px;
  border-top: var(--hairline) solid var(--outline-variant);
  font-size: var(--text-micro);
  letter-spacing: 0.1em;
  color: var(--secondary);
}

/* --- Breadcrumbs -------------------------------------------------------- */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding-top: 128px;
  padding-bottom: 8px;
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--secondary);
}

.crumbs a:hover {
  color: var(--accent-ink);
}

.crumbs [aria-current] {
  color: var(--on-surface);
}

/* --- Buttons ------------------------------------------------------------ */
.btn--ghost {
  background: transparent;
  color: var(--brand);
  border: 2px solid var(--brand);
}

.btn--ghost:hover {
  background: var(--brand);
  color: var(--on-primary);
}

/* Outlined on a dark band: white rule, orange on hover. */
.bg-brand .btn--ghost,
.bg-ink .btn--ghost {
  background: transparent;
  color: var(--on-dark);
  border-color: rgba(255, 255, 255, 0.55);
}

.bg-brand .btn--ghost:hover,
.bg-ink .btn--ghost:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}

.btn--block-sm {
  width: 100%;
  padding-block: 18px;
}

/* --- Spec list ---------------------------------------------------------- */
.specs {
  margin: 28px 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.spec {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding: 12px 0;
  border-bottom: var(--hairline) solid var(--outline-variant);
  transition: padding-left 0.125s, background 0.125s;
}

.spec dt {
  font-family: var(--font-mono);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--secondary);
}

.spec dd {
  font-family: var(--font-mono);
  font-size: var(--text-ui);
  text-align: right;
  /* Values here include an email address and a URL, which have no space to
     break at and otherwise push a narrow phone sideways. */
  min-width: 0;
  overflow-wrap: anywhere;
  font-variant-numeric: tabular-nums;
}

.tbc {
  color: var(--secondary);
}

.spec-note {
  margin-top: 16px;
  margin-bottom: 20px;
  font-size: var(--text-micro);
  line-height: 1.6;
}

.spec-note a {
  border-bottom: var(--hairline) solid var(--outline-variant);
}

/* --- Catalog cards ------------------------------------------------------
   Identical tiles, three to a row. This replaced a stack of alternating
   full-bleed rows: those gave every product a different image size and flipped
   the reading order line by line, which is exactly wrong for a page whose job
   is letting a buyer compare product groups against each other.
   ------------------------------------------------------------------------- */
.cat-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
}

/* Hover moves the whole card, not the picture inside it. The previous pass
   scaled the image to 1.06 over 0.6s against a 0.35s card lift — two gestures
   on two clocks, so the eye read the faster, larger one and the card looked
   static while the photo slid around behind a fixed window. Now one gesture:
   the card rises and grows, the photo grows with it on the same clock. */
.cat-card {
  position: relative;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--surface-lowest);
  border: var(--hairline) solid var(--outline-variant);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 1px 0 rgba(16,26,64,0.04);
  transition: transform 0.18s var(--ease-spring), box-shadow 0.18s var(--ease-spring), border-color 0.12s;
}

/* :focus-within so tabbing to the summary or the buttons inside gives the same
   affordance a mouse gets. z-index lifts the raised card's shadow above its
   neighbours; without it the shadow is clipped by the next card in the grid. */
/* Specificity, not decoration. The scroll-reveal owns transform on these
   cards: `.js .fade-up.is-visible` (0,3,0) pins transform:none and beats a
   bare `.cat-card:hover` (0,2,0), and `.js .fade-up` (0,2,0) replaces the
   card's own transition (0,1,0) so box-shadow snapped instead of easing.
   That is why the old translateY(-5px) lift never rendered and the image
   zoom was the only thing anyone saw. These selectors outweigh both.
   The same trap is still set for .svc-card. */
.js .cat-card.fade-up {
  transition: transform 0.18s var(--ease-spring), box-shadow 0.18s var(--ease-spring), border-color 0.12s;
}

.cat-card:hover,
.cat-card:focus-within,
.cat-card.fade-up.is-visible:hover,
.cat-card.fade-up.is-visible:focus-within {
  transform: translateY(-6px) scale(1.015);
  z-index: 1;
  box-shadow: var(--shadow-card);
  border-color: rgba(147,164,188,0.9);
}

/* Fixed ratio plus object-fit is what makes every card render at one size
   whatever the source frame is. */
.cat-card__visual { position: relative; }

.cat-card__media {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--surface-container);
}

.cat-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.18s var(--ease-spring);
}

.cat-card__image-note {
  position: absolute;
  left: 12px;
  bottom: 12px;
  padding: 6px 9px;
  background: rgba(16, 26, 64, 0.92);
  color: #fff;
  font-family: var(--font-body);
  font-size: var(--text-micro);
  font-weight: 600;
  line-height: 1.2;
  pointer-events: none;
}

/* Neutral category artwork for product groups that do not yet have an
   approved Rotec photograph. It uses the registered mark and never presents
   a stock image as the company's own equipment. */
.product-media-placeholder {
  display: grid;
  width: 100%;
  aspect-ratio: 4 / 3;
  place-items: center;
  align-content: center;
  gap: 18px;
  padding: 32px;
  background:
    linear-gradient(135deg, rgba(72, 83, 149, 0.08), rgba(234, 170, 16, 0.12)),
    var(--surface-container);
  color: var(--brand);
  text-align: center;
}

.cat-card__media .product-media-placeholder img,
.prod-hero__media .product-media-placeholder img {
  width: clamp(72px, 18%, 112px);
  height: auto;
  aspect-ratio: auto;
  object-fit: contain;
  opacity: 0.75;
}

.product-media-placeholder .t-label {
  max-width: 28ch;
  color: var(--brand);
}

/* A whisper on top of the card's own 1.015, so the photo reads as sitting
   slightly deeper than its frame. Same duration as the card on purpose —
   the moment these two durations differ the effect splits back into two. */
.cat-card:hover .cat-card__media img,
.cat-card:focus-within .cat-card__media img {
  transform: scale(1.02);
}

.cat-card__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 24px;
}

.cat-card__body h2 {
  margin-bottom: 12px;
}

.cat-card__intro {
  font-size: var(--text-ui);
  line-height: 1.55;
}

/* margin-top:auto drops the disclosure to the foot of the card. Grid rows
   stretch their items, so across a row of three the summaries land on one
   line however long the intros run. */
.cat-card__details {
  margin-top: auto;
  padding-top: 18px;
}

.cat-card__details summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 16px;
  border-top: var(--hairline) solid var(--outline-variant);
  color: var(--accent-ink);
  cursor: pointer;
  list-style: none;
  transition: color 0.1s;
}

/* The default marker is a filled triangle in Safari and a rotating one in
   Chrome; neither matches the rest of the site, so both are suppressed and
   .cat-card__chev draws the mark. */
.cat-card__details summary::-webkit-details-marker {
  display: none;
}

.cat-card__details summary:hover {
  color: var(--brand);
}

/* Plus that becomes a minus — the same mark the home service cards use. */
.cat-card__chev {
  position: relative;
  flex: none;
  width: 12px;
  height: 12px;
}

.cat-card__chev::before,
.cat-card__chev::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 2px;
  background: currentColor;
  transition: transform 0.125s ease;
}

.cat-card__chev::after {
  transform: rotate(90deg);
}

.cat-card__details[open] .cat-card__chev::after {
  transform: rotate(0deg);
}

.cat-card__panel {
  padding-top: 18px;
}

.cat-card__panel ul {
  display: grid;
  gap: 9px;
  margin-bottom: 22px;
}

.cat-card__panel li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-size: var(--text-ui);
  color: var(--on-surface-variant);
  line-height: 1.4;
}

.cat-card__panel li::before {
  content: "";
  width: 12px;
  height: var(--hairline);
  flex: 0 0 12px;
  margin-top: 0.55em;
  background: var(--accent-ink);
}

/* A third-width card has no room for two buttons side by side, so they stack
   and run the full width rather than being given a min-width to overflow. */
.cat-card__actions {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
}

.cat-card__actions .btn {
  width: 100%;
  justify-content: center;
}

/* --- Product page ------------------------------------------------------- */
.prod-hero {
  padding-top: 20px;
  padding-bottom: 64px;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.prod-hero__grid {
  display: grid;
  gap: 40px;
  align-items: center;
}

.prod-hero__text h1 {
  margin-bottom: 24px;
}

.prod-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 36px;
}

.prod-hero__media {
  position: relative;
  border: var(--hairline) solid var(--outline-variant);
  background: var(--surface-container);
}

.prod-hero__media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.prod-hero__media figcaption {
  position: static;
  margin-top: 12px;
  padding: 0;
  background: transparent;
  border: 0;
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--secondary);
}

.prod-body {
  display: grid;
  gap: 56px;
}

.deflists {
  display: grid;
  gap: 40px;
  margin-top: 48px;
}

.deflist h2 {
  padding-bottom: 12px;
  margin-bottom: 16px;
  border-bottom: var(--hairline) solid var(--outline-variant);
  color: var(--secondary);
}

.deflist li {
  position: relative;
  padding: 8px 0 8px 24px;
  color: var(--on-surface-variant);
}

.deflist li::before {
  content: "";
  position: absolute;
  top: 18px;
  left: 0;
  width: 12px;
  height: var(--hairline);
  background: var(--accent-ink);
}

.prod-body__aside {
  align-self: start;
  padding: 28px 0 0;
  background: transparent;
  border: 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.prod-nav {
  display: grid;
  gap: 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.prod-nav__link {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 28px 0;
  background: transparent;
  border: 0;
  border-bottom: var(--hairline) solid var(--outline-variant);
  transition: opacity 0.1s;
}

.prod-nav__link:hover {
  transform: none;
  box-shadow: none;
  opacity: 0.85;
  border-color: transparent;
}

.prod-nav__link--next {
  text-align: right;
}

/* --- Chips -------------------------------------------------------------- */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.chip {
  padding: 10px 14px;
  border: 0;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--on-surface-variant);
  transition: color 0.1s, border-color 0.1s;
}

.chip:hover {
  background: transparent;
  border-color: transparent;
  border-bottom-color: var(--accent);
  color: var(--brand);
}

/* --- Tables ------------------------------------------------------------- */
.table-scroll {
  overflow-x: auto;
  border: var(--hairline) solid var(--outline-variant);
  background: var(--surface-lowest);
}

.data-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  font-size: var(--text-data);
  font-variant-numeric: tabular-nums;
}

.data-table th,
.data-table td {
  padding: 14px 18px;
  text-align: left;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.data-table thead th {
  background: transparent;
  border-bottom: var(--hairline) solid var(--outline);
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--secondary);
}

.data-table tbody tr:last-child th,
.data-table tbody tr:last-child td {
  border-bottom: 0;
}

.data-table tbody tr:hover {
  background: var(--surface);
}

.data-table tbody th {
  font-weight: 600;
}

.data-table a:hover {
  color: var(--accent-ink);
}

.credit-thumb {
  width: 84px;
  height: 56px;
  object-fit: cover;
  border: var(--hairline) solid var(--outline-variant);
}

/* --- Figures ------------------------------------------------------------ */
.figure {
  border: var(--hairline) solid var(--outline-variant);
  background: var(--surface-container);
}

.figure img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.figure--wide img {
  aspect-ratio: 21 / 9;
}

.figure figcaption {
  padding: 12px 16px;
  border-top: var(--hairline) solid var(--outline-variant);
  background: var(--surface-lowest);
  font-size: var(--text-micro);
  letter-spacing: 0.1em;
  color: var(--secondary);
}

.media-split {
  display: grid;
  gap: 32px;
}

/* --- Timeline ----------------------------------------------------------- */
.timeline .wrap {
  position: relative;
}

.epoch {
  display: grid;
  gap: 24px;
  margin-bottom: 88px;
}

.epoch:last-child {
  margin-bottom: 0;
}

.epoch__media {
  position: relative;
  border: var(--hairline) solid var(--outline-variant);
  background: var(--surface-container);
}

.epoch__media img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
}

.epoch__badge {
  position: absolute;
  top: 16px;
  left: 16px;
  z-index: 1;
  padding: 0;
  background: transparent;
  color: var(--on-dark);
  letter-spacing: 0.12em;
  text-shadow: 0 1px 12px rgba(16, 26, 64, 0.55);
}

.epoch:nth-child(3n) .epoch__badge {
  background: transparent;
  color: var(--accent);
}

.epoch__text h2 {
  margin-bottom: 20px;
}

.epoch__body {
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--on-surface-variant);
  max-width: 54ch;
}

.pillars-grid {
  display: grid;
  gap: 0;
}

.pillar {
  padding: 28px 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.pillar h3 {
  margin: 0 0 12px;
}

.pillar p {
  color: var(--on-surface-variant);
  font-size: var(--text-body);
  line-height: 1.6;
}

/* --- CTA band ----------------------------------------------------------- */
.cta-band {
  display: grid;
  gap: 28px;
  align-items: center;
}

.cta-band h2 {
  margin-bottom: 12px;
}

.cta-band p {
  max-width: 56ch;
}

/* Quiet home CTA sits on a light band, not full ink — v2 adds soft card */
.cta-band--quiet {
  padding: 22px 22px;
  background: var(--surface-lowest);
  border: 1px solid var(--outline-variant);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-soft);
}

.cta-band--quiet h2 {
  color: var(--brand);
}

@media (min-width: 900px) {
  .cta-band--quiet {
    grid-template-columns: 1fr auto;
    gap: 48px;
    padding: 28px 28px;
  }
}

/* --- Contact page ------------------------------------------------------- */
.gallery-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(12px, 1.4vw, 20px);
}

.gallery-photo {
  margin: 0;
  overflow: hidden;
  background: var(--surface-container);
}

.gallery-photo a { display: block; }
.gallery-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 0.35s ease;
}
.gallery-photo--wide img { aspect-ratio: 16 / 9; }
.gallery-photo a:hover img { transform: scale(1.025); }
.gallery-photo a:focus-visible { outline: 3px solid var(--primary); outline-offset: -3px; }

@media (min-width: 640px) {
  .gallery-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gallery-photo--wide { grid-column: 1 / -1; }
}

.location-section { border-top: var(--hairline) solid var(--outline-variant); }
.location-grid { display: grid; grid-template-columns: 1fr; gap: 28px; align-items: center; }
.location-map { position: relative; min-width: 0; background: var(--surface-container); }
.location-map iframe {
  display: block;
  width: 100%;
  height: clamp(300px, 31vw, 430px);
  border: 0;
}
.location-map__link {
  position: absolute;
  left: 16px;
  bottom: 16px;
  padding: 12px 16px;
  background: #fff;
  color: var(--primary);
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.025em;
  box-shadow: 0 3px 14px rgba(16, 26, 64, 0.15);
}
.location-map__link:hover { color: var(--accent); }
.location-map__link:focus-visible { outline: 3px solid var(--primary); outline-offset: 2px; }
/* Narrow maps leave no clear corner: the overlay covered Google's own logo
   and attribution strip. Below tablet the link sits under the map instead. */
@media (max-width: 639px) {
  .location-map__link {
    position: static;
    display: inline-block;
    margin-top: 12px;
    padding: 12px 0;
    box-shadow: none;
  }
  .location-map { background: none; }
}
.location-copy address { margin: 20px 0 24px; font-style: normal; line-height: 1.75; }
@media (min-width: 900px) {
  .location-grid { grid-template-columns: minmax(0, 7fr) minmax(260px, 4fr); gap: 48px; }
}

.contact-grid {
  display: grid;
  gap: 48px;
  align-items: start;
}

/* Grid items default to a minimum of their content, which lets one stubborn
   descendant hold a column open wider than the screen. */
.contact-grid > *,
.form-row > * {
  min-width: 0;
}

.form-block {
  padding-bottom: 36px;
  margin-bottom: 36px;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.form-block:last-of-type {
  border-bottom: 0;
}

.form-block legend {
  display: flex;
  gap: 14px;
  margin-bottom: 28px;
  padding: 0;
}

.form-row {
  display: grid;
  gap: 28px;
  margin-bottom: 28px;
}

.form-row:last-child {
  margin-bottom: 0;
}

.form-block > .field + .field {
  margin-top: 28px;
}

.contact-aside .hq {
  max-width: none;
}

/* --- Responsive --------------------------------------------------------- */
@media (min-width: 640px) {
  .prod-hero__actions .btn {
    min-width: 168px;
  }
  .cat-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .form-row {
    grid-template-columns: 1fr 1fr;
  }
  .prod-nav {
    grid-template-columns: 1fr 1fr;
  }
  .media-split {
    grid-template-columns: 1fr 1fr;
  }
  .pillars-grid {
    grid-template-columns: 1fr 1fr;
    gap: 0 40px;
  }
}

@media (min-width: 900px) {
  .page-hero {
    padding-top: calc(var(--head-height) + 40px);
    padding-bottom: 64px;
  }
  .crumbs {
    padding-top: 150px;
  }
  .cat-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 32px;
  }
  .prod-hero__grid {
    grid-template-columns: 1fr 1fr;
    gap: 64px;
  }
  .prod-body {
    grid-template-columns: 7fr 4fr;
    gap: 56px;
  }
  .deflists {
    grid-template-columns: 1fr 1fr;
  }
  /* Two columns here, so the separator is the left rule and the top rule from
     the stacked layout has to go — it drew a hairline across the head of the
     sidebar that lined up with nothing in the main column. The 6px lifts the
     "SPECIFICATION" eyebrow onto the same optical line as the first line of
     the intro paragraph beside it, which sets in a taller line box. */
  .prod-body__aside {
    position: sticky;
    top: 140px;
    padding: 6px 0 0 28px;
    border-top: 0;
    border-left: var(--hairline) solid var(--outline-variant);
  }
  .epoch {
    grid-template-columns: 1fr 1fr;
    gap: 56px;
    align-items: center;
    margin-bottom: 88px;
  }
  .epoch--flip .epoch__media {
    order: 2;
  }
  .epoch--flip .epoch__text {
    text-align: right;
  }
  .pillars-grid {
    grid-template-columns: repeat(4, 1fr);
    gap: 0 32px;
  }
  .cta-band {
    grid-template-columns: 1fr auto;
    gap: 56px;
  }
  .cta-band .btn {
    width: auto;
    min-width: 240px;
  }
  .contact-grid {
    grid-template-columns: 7fr 4fr;
    gap: 56px;
  }
  .contact-aside {
    position: sticky;
    top: 140px;
  }
}

/* ==========================================================================
   Brand sync — a light pass of the logo's blue so the mark belongs here.
   Deliberately restrained: red remains the accent colour of the design.
   ========================================================================== */

::selection {
  background: var(--brand-soft);
  color: var(--on-surface);
}

/* Active nav item gets an underline rather than only a colour shift — the two
   red steps are close enough that colour alone is a weak signal. */
.nav__link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 2px;
  background: var(--nav-link-hover);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
}

.nav__link:hover::after,
.nav__link.is-active::after {
  transform: scaleX(1);
}

/* Section rules read as two-tone: ink, then a short brand tick.
   Scoped to section dividers — the hero stamp sits inline beside text. */
.section .rule {
  position: relative;
  overflow: visible;
}

.section .rule::after {
  content: "";
  position: absolute;
  left: 100%;
  top: 0;
  width: 16px;
  height: 100%;
  margin-left: 4px;
  background: var(--brand);
}

.subscribe button:hover,
.btn--block:hover {
  background: var(--brand);
}

.pillar:hover {
  border-top-color: var(--accent);
}

/* ==========================================================================
   ISO certification badges
   ========================================================================== */

.iso-badge__text strong,
.iso-badge__text span {
  font-family: var(--font-display);
}

.iso-badge {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border: 0;
  border-top: var(--hairline) solid var(--outline-variant);
  background: transparent;
  transition: opacity 0.1s;
}

/* On the blue footer the badge inverts rather than punching a white hole in
   the band. The hero is a light wash now, so it keeps the default treatment. */
.footer .iso-badge {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.24);
  border-left-color: var(--accent);
}

.footer .iso-seal {
  stroke: var(--accent);
}

.footer .iso-badge__text strong {
  color: var(--on-dark);
}

.footer .iso-badge__text span {
  color: var(--on-dark-variant);
}

a.iso-badge:hover {
  border-color: transparent;
  box-shadow: none;
  transform: none;
  opacity: 0.9;
}

.iso-seal {
  flex-shrink: 0;
  fill: none;
  stroke: var(--brand);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.iso-badge__text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-family: var(--font-mono);
  line-height: 1.2;
}

.iso-badge__text strong {
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--on-surface);
}

.iso-badge__text span {
  font-size: var(--text-micro);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--secondary);
}

/* Placements */
.iso-badge--footer {
  margin-top: 28px;
}

.iso-badge--stack {
  display: flex;
  width: 100%;
  margin-top: 24px;
}

.hq .iso-badge--stack {
  margin-top: 20px;
  background: transparent;
}

/* --- Certification panel ------------------------------------------------ */
.cert-split {
  display: grid;
  gap: 48px;
  align-items: start;
}

.cert-panel {
  padding: 0;
  background: transparent;
  border: 0;
  border-top: var(--hairline) solid var(--outline-variant);
  padding-top: 28px;
}

.cert-panel__head {
  display: flex;
  align-items: center;
  gap: 20px;
  padding-bottom: 24px;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.cert-panel__head h3 {
  margin: 4px 0;
}

.cert-panel__scope {
  margin: 24px 0 0;
  color: var(--on-surface-variant);
  font-size: var(--text-body);
  line-height: 1.6;
}

.cert-panel .specs {
  margin-bottom: 24px;
}

@media (min-width: 900px) {
  .cert-split {
    grid-template-columns: 5fr 6fr;
    gap: 56px;
  }
}

@media (min-width: 900px) {
  .hero__cert {
    margin-top: 32px;
  }
}

/* ==========================================================================
   Home page — overview blocks
   ========================================================================== */

.home-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 28px 48px;
  margin-bottom: 40px;
}

.home-head > div {
  flex: 1 1 28rem;
  min-width: 0;
  max-width: 40rem;
}

.home-head .btn-text {
  margin-top: 0;
  margin-bottom: 6px;
  flex-shrink: 0;
}

/* --- Check list — quality claims under manufacturing copy --------------- */
.check-list {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin: 8px 0 36px;
}

.check-list li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  font-size: var(--text-body);
  font-weight: 600;
  line-height: 1.45;
  color: var(--on-surface);
}

.check-list li::before {
  content: "";
  flex: none;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  background-color: var(--accent);
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E") center / contain no-repeat;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 13l4 4L19 7'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* --- Field cards — photo overlay panels (reference: project gallery) ---- */
.field-cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

.field-card {
  position: relative;
  display: block;
  min-height: 300px;
  overflow: hidden;
  color: var(--on-dark);
}

.field-card__media {
  position: absolute;
  inset: 0;
}

.field-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.275s cubic-bezier(0.16, 1, 0.3, 1);
}

.field-card__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(16, 26, 64, 0.15) 0%,
    rgba(16, 26, 64, 0.55) 45%,
    rgba(16, 26, 64, 0.92) 100%
  );
  transition: background 0.15s;
}

.field-card__body {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: 12px;
  min-height: 300px;
  padding: 32px 28px;
}

.field-card__meta {
  color: var(--accent);
}

.field-card__title {
  max-width: 22ch;
  font-family: var(--font-display);
  font-size: var(--text-h3);
  font-weight: 700;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-transform: uppercase;
}

.field-card__arrow {
  display: inline-flex;
  margin-top: 4px;
  color: var(--accent);
  transition: transform 0.125s;
}

.field-card__arrow .icon {
  width: 20px;
  height: 20px;
}

.field-card:hover .field-card__media img {
  transform: scale(1.05);
}

.field-card:hover .field-card__arrow {
  transform: translateX(6px);
}

@media (min-width: 900px) {
  .field-cards {
    grid-template-columns: repeat(3, 1fr);
    gap: 28px;
  }

  .field-card {
    min-height: 380px;
  }

  .field-card__body {
    min-height: 380px;
    padding: 36px 32px;
  }
}


/* --- Sector list -------------------------------------------------------- */
.sectors {
  display: grid;
  gap: 40px;
}

.sector-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  border-top: var(--hairline) solid var(--outline-variant);
  align-self: start;
}

.sector-list li {
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.sector-list a {
  display: block;
  padding: 16px 8px;
  font-family: var(--font-mono);
  font-size: var(--text-ui);
  letter-spacing: 0.05em;
  transition: background 0.11s, padding-left 0.11s, color 0.11s;
}

.sector-list a:hover {
  background: var(--surface-lowest);
  padding-left: 20px;
  color: var(--brand);
}

/* Industries sits on an ink band, so the list inverts. */
.bg-brand .sector-list,
.bg-brand .sector-list li,
.bg-ink .sector-list,
.bg-ink .sector-list li {
  border-color: rgba(255, 255, 255, 0.28);
}

.bg-brand .sector-list a,
.bg-ink .sector-list a {
  color: var(--on-dark);
}

.bg-brand .sector-list a:hover,
.bg-ink .sector-list a:hover {
  background: rgba(255, 255, 255, 0.12);
  color: var(--on-dark);
}

.bg-brand .btn-text:hover,
.bg-ink .btn-text:hover {
  color: var(--accent);
}

@media (min-width: 640px) {
  .sector-list {
    grid-template-columns: 1fr 1fr;
    column-gap: 32px;
  }
}

@media (min-width: 900px) {
  .sectors {
    grid-template-columns: 4fr 7fr;
    gap: 56px;
  }
}

/* Nine links need real width. Below this threshold the hamburger drawer
   carries navigation; above it the row is allowed to breathe across a
   measured grid instead of bunching up immediately after the logo. */
@media (min-width: 1350px) {
  .nav {
    padding: 0 var(--margin-desktop);
  }
  .nav__logo {
    padding-right: 28px;
  }
  .nav__logo img {
    height: 44px;
  }
  .nav__links {
    display: grid;
    grid-template-columns: repeat(9, max-content);
    justify-content: space-between;
    width: 100%;
    max-width: 1280px;
    /* The logo's padding sets mark-to-rule and the bar's gap sets rule-to-link;
       this extra inset would stack on the second of those and push the row off
       balance. Set here rather than beside the divider because the base rule
       below that block would otherwise win on source order at equal weight. */
    padding-left: 0;
    gap: 0;
  }
  .nav__actions {
    margin-left: 0;
  }
  .nav__toggle,
  .nav__drawer {
    display: none;
  }
  .nav__link {
    padding-block: 10px;
    font-size: var(--text-ui);
    letter-spacing: 0.035em;
  }
}

/* Phone stays out of the desktop nav — it crowded the link row.
   Number remains in the drawer, footer and contact page. */

/* ==========================================================================
   Micro-animations
   Every rule here is additive — the page is fully legible with none of it.
   The reduced-motion block at the end switches all of it off.
   ========================================================================== */

/* --- Scroll progress ---------------------------------------------------- */
.scroll-progress {
  pointer-events: none;
  display: none;
}

/* --- Hero entrance ------------------------------------------------------
   Pure CSS animation with `both` fill, so it plays on load with no JS.
   If the script never arrives the hero still ends up fully visible.
   Vertical motion only — a horizontal drift would push past the viewport. */
@keyframes heroIn {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@keyframes ruleDraw {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* Scoped to the first slide. The others are off-canvas at load, so animating
   them just burns their entrance before anyone can see it — their motion is
   the track slide itself. */
.hero__slide:first-child .hero__title  { animation: heroIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.05s both; }
.hero__slide:first-child .hero__lede   { animation: heroIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.16s both; }
.hero__slide:first-child .eyebrow      { animation: heroIn 0.7s cubic-bezier(0.16, 1, 0.3, 1) 0.24s both; }
/* --- Photography ---------------------------------------------------------
   Product and plant images stay natural and immediately visible. */
.figure img,
.cat-card__media img,
.epoch__media img,
.prod-hero__media img,
.product__art img {
  filter: none;
  clip-path: none;
}


/* --- Drawer link stagger ------------------------------------------------ */
.nav__drawer.is-open a {
  opacity: 1;
  transform: none;
}

.nav__drawer.is-open a:nth-child(1) { transition-delay: 0.08s; }
.nav__drawer.is-open a:nth-child(2) { transition-delay: 0.13s; }
.nav__drawer.is-open a:nth-child(3) { transition-delay: 0.18s; }
.nav__drawer.is-open a:nth-child(4) { transition-delay: 0.23s; }
.nav__drawer.is-open a:nth-child(5) { transition-delay: 0.28s; }
.nav__drawer.is-open a:nth-child(6) { transition-delay: 0.33s; }
.nav__drawer.is-open a:nth-child(7) { transition-delay: 0.38s; }

/* The mark used to step down on scroll — 52px to 44px here, 58px to 50px at
   1400 — while the bar's own height stayed put. Removed: a logo that changes
   size as you scroll reads as a rendering fault rather than as an effect,
   and the raster mark resamples at every intermediate height on the way,
   which is what made it look like it was flickering. The bar still condenses;
   it does it with background and shadow, which is where the scroll cue
   belongs. Size is now fixed per breakpoint. */

.spec:hover {
  padding-left: 8px;
  background: var(--brand-tint);
}

/* --- Buttons ------------------------------------------------------------ */
.btn,
.btn--ghost {
  position: relative;
  overflow: hidden;
}

.btn::after {
  content: "";
  position: absolute;
  inset: 0;
  background: currentColor;
  opacity: 0;
  transition: opacity 0.15s;
}

.btn:active::after {
  opacity: 0.12;
  transition: none;
}

/* --- Form validation shake --------------------------------------------- */
.is-invalid {
  animation: nudge 0.2s;
  border-color: var(--accent) !important;
}

@keyframes nudge {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-5px); }
  40% { transform: translateX(5px); }
  60% { transform: translateX(-3px); }
  80% { transform: translateX(3px); }
}

/* --- Card / link polish ------------------------------------------------- */
.card__num,
.step__num {
  transition: letter-spacing 0.15s, color 0.15s;
}

.card:hover .card__num,
.step:hover .step__num {
  letter-spacing: 0.18em;
}

.cap-list li .name {
  transition: transform 0.125s;
  display: inline-block;
}

.cap-list li:hover .name {
  transform: translateX(3px);
}

.iso-seal circle,
.iso-seal path {
  transition: stroke 0.15s;
}

a.iso-badge:hover .iso-seal path {
  stroke: var(--accent);
}

/* ==========================================================================
   Motion off — everything above collapses to a static, fully visible page
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .scroll-progress {
    display: none;
  }
  /* Keep the hover readable — shadow and border still change, so the card
     still answers the cursor. Only the movement goes. */
  .svc-card:hover,
  .svc-card:focus-visible,
  .svc-card.fade-up.is-visible:hover,
  .svc-card.fade-up.is-visible:focus-visible,
  .cat-card:hover,
  .cat-card:focus-within,
  .cat-card.fade-up.is-visible:hover,
  .cat-card.fade-up.is-visible:focus-within,
  .cat-card:hover .cat-card__media img,
  .cat-card:focus-within .cat-card__media img {
    transform: none;
  }
  .hero__title,
  .hero__lede,
  .hero .eyebrow,
  .hero__track,
  .hero__cert,
  .hero__actions,
  .hero__stats,
  .nav__drawer a {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .hero__art img {
    animation: none !important;
    transform: none !important;
  }
  .figure img,
  .cat-card__media img,
  .epoch__media img,
  .product__art img {
    clip-path: none !important;
  }
  .is-invalid {
    animation: none;
  }
}

/* ==========================================================================
   Touch targets — WCAG 2.5.8 wants ~44px on coarse pointers.
   Applied via hit-area padding so nothing moves visually.
   ========================================================================== */
@media (pointer: coarse), (max-width: 900px) {
  .nav__toggle {
    padding: 9px;
    margin: -9px;
  }

  /* Do not add padding-block on .nav__logo. It kept the mark full-height back
     when the accent slab was behind it, and it still should: the link is
     stretched to the bar's height, which is what makes it a comfortable touch
     target on a phone. Insetting it would shrink the hit area for no gain. */

  .footer__col ul {
    gap: 2px;
  }

  .footer__col ul a,
  .footer__contact a {
    display: inline-block;
    padding-block: 11px;
  }

  .btn-text {
    padding-block: 12px;
  }

  .chip {
    padding: 13px 20px;
  }

  .crumbs a,
  .crumbs span {
    padding-block: 8px;
  }

  .prose a:not(.btn-text) {
    padding-block: 8px;
  }

  .spec dd a,
  .hq a,
  .spec-note a,
  .form__note a {
    display: inline-block;
    padding-block: 11px;
  }


  .data-table a {
    display: inline-block;
    padding-block: 8px;
  }
}

/* --- Mobile sticky enquire — conversion after hero folds ---------------- */
.mobile-enquire {
  display: none;
}

@media (max-width: 768px) {
  .mobile-enquire {
    position: fixed;
    z-index: 40;
    left: 16px;
    right: 16px;
    bottom: max(16px, env(safe-area-inset-bottom));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 48px;
    padding: 14px 22px;
    background: var(--accent);
    color: var(--on-accent);
    font-family: var(--font-display);
    font-size: var(--text-ui);
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    box-shadow: 0 12px 28px rgba(16, 26, 64, 0.28);
    transition: transform 0.1s, opacity 0.1s, background 0.1s;
  }

  .mobile-enquire .icon {
    width: 16px;
    height: 16px;
  }

  .mobile-enquire:hover,
  .mobile-enquire:focus-visible {
    background: var(--accent-deep);
  }

  .mobile-enquire:active {
    transform: scale(0.98);
  }

  /* Keep clear of the fixed bar */
  body {
    padding-bottom: calc(72px + env(safe-area-inset-bottom));
  }

  /* Hide while the mobile nav drawer is open */
  body:has(.nav__drawer.is-open) .mobile-enquire {
    opacity: 0;
    pointer-events: none;
    transform: translateY(12px);
  }
}

/* --- Utilities -----------------------------------------------------------
   One-off layout nudge helpers. These live at the end of the cascade so a
   utility always wins over a component rule — the same guarantee an inline
   style used to give, without the attribute. Only add one when a value is
   used more than once; otherwise put it in the component that owns it.
   ----------------------------------------------------------------------- */

.u-self-center { align-self: center; }
.u-rotate-180  { transform: rotate(180deg); }

.u-mb-20 { margin-bottom: 20px; }
.u-mb-24 { margin-bottom: 24px; }
.u-mb-32 { margin-bottom: 32px; }
.u-mb-40 { margin-bottom: 40px; }
.u-mb-48 { margin-bottom: 48px; }

.u-mt-24 { margin-top: 24px; }
.u-mt-40 { margin-top: 40px; }
.u-mt-48 { margin-top: 48px; }

.u-maxw-38 { max-width: 38ch; }
.u-maxw-42 { max-width: 42ch; }
.u-maxw-46 { max-width: 46ch; }
.u-maxw-68 { max-width: 68ch; }
.u-maxw-none { max-width: none; }

/* ==========================================================================
   Reference layout
   The client approved a construction-sector layout built on: a utility strip
   above a nav anchored by a solid colour block, a bordered four-up services
   grid with an accent rule under each card, and a hero whose copy sits on a
   light wash over full-bleed plant photography. The first and last of those
   are handled up in the header and hero sections; the services grid is below.
   ========================================================================== */

/* --- Hero copy ----------------------------------------------------------- */
.hero__copy {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0;
  max-width: 38rem;
}

.hero .eyebrow {
  position: relative;
  z-index: 1;
  margin-bottom: 16px;
  color: var(--accent);
}

.hero .eyebrow::before {
  background: var(--accent);
}

/* --- Services grid — bordered four-up ------------------------------------
   Each card is a whole product line: a standing label, the name, what it is
   for, and a plus that reads as "there is more behind this".
   ------------------------------------------------------------------------- */
.svc-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}

.svc-card {
  position: relative;
  display: flex;
  min-width: 0;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 30px 28px 26px;
  background: var(--surface-lowest);
  border: var(--hairline) solid var(--outline-variant);
  border-bottom: 3px solid var(--accent);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform 0.175s var(--ease-spring), box-shadow 0.175s var(--ease-spring), border-color 0.125s;
}

/* Same trap the catalog cards were in. `.js .fade-up.is-visible` (0,3,0)
   pins transform:none and outweighs a bare `.svc-card:hover` (0,2,0), so this
   lift never rendered. `.js .fade-up` (0,2,0) likewise replaced the card's
   own transition. These selectors outweigh both. The card is an <a>, so :focus-visible (not
   :focus-within) is what a keyboard user trips. */
.js .svc-card.fade-up {
  transition: transform 0.175s var(--ease-spring), box-shadow 0.175s var(--ease-spring), border-color 0.125s;
}

.svc-card:hover,
.svc-card:focus-visible,
.svc-card.fade-up.is-visible:hover,
.svc-card.fade-up.is-visible:focus-visible {
  transform: translateY(-6px);
  box-shadow: var(--shadow-card);
  border-color: rgba(147,164,188,0.9);
  border-bottom-color: var(--accent);
}

.svc-card__eyebrow {
  font-family: var(--font-display);
  font-size: var(--text-micro);
  font-weight: 700;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent-ink);
}

/* Reserve two lines whether the name needs them or not. Four product names
   wrap; without this the taglines beside them no longer align. */
.svc-card__title {
  min-height: 2.5em;
  font-size: var(--text-h3);
  color: var(--brand);
}

.svc-card__tag {
  color: var(--on-surface-variant);
  font-size: var(--text-data);
  line-height: 1.5;
}

/* Pushed to the bottom edge so the plus lines up across a row whatever the
   name wraps to. */
.svc-card__plus {
  display: block;
  margin-top: auto;
  padding-top: 20px;
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 600;
  line-height: 1;
  color: var(--accent-ink);
  transition: transform 0.125s;
}

.svc-card:hover .svc-card__plus {
  transform: rotate(90deg);
}

@media (min-width: 400px) {
  .svc-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 16px;
  }
}

@media (min-width: 560px) {
  .svc-grid {
    gap: 24px;
  }
}

@media (min-width: 1080px) {
  .svc-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  .svc-card,
  .svc-card:hover,
  .svc-card:hover .svc-card__plus {
    transform: none;
  }
}

/* ==========================================================================
   Hero slider controls
   Arrows bottom-left with the next button filled in accent, dots to their
   right — the arrangement the client's reference uses. Everything here is
   additive: with JS off the first slide is already the visible one and the
   controls simply do nothing, which is why they are never the only route to
   any content on the page.
   ========================================================================== */
.hero__controls {
  position: absolute;
  z-index: 3;
  right: 0;
  bottom: 32px;
  left: 0;
  display: flex;
  align-items: center;
  gap: 24px;
}

.hero__arrows {
  display: flex;
  flex: none;
}

.hero__arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  background: var(--surface-lowest);
  color: var(--brand);
  border: var(--hairline) solid var(--outline-variant);
  transition: background 0.1s, color 0.1s, border-color 0.1s;
}

.hero__arrow .icon {
  width: 18px;
  height: 18px;
}

.hero__arrow:hover {
  background: var(--brand);
  color: var(--on-primary);
  border-color: var(--brand);
}

/* The forward action is the one being encouraged, so it carries the accent —
   same rule the rest of the site follows for primary actions. */
.hero__arrow--next {
  background: var(--accent);
  color: var(--on-accent);
  border-color: var(--accent);
}

.hero__arrow--next:hover {
  background: var(--accent-deep);
  color: var(--on-accent);
  border-color: var(--accent-deep);
}

.hero__dots {
  display: flex;
  align-items: center;
  /* Negative gap pulls the 24px hit areas back to a 10px visual rhythm; the
     targets still meet at no less than 24px apart centre to centre. */
  gap: 0;
}

/* The button itself carries the 24x44 hit area — WCAG 2.5.8 measures the
   control, not a pseudo-element drawn over it — and ::before draws the 10px
   dot people actually see. A 10px button with an invisible 44px overlay would
   pass a glance and fail an audit. */
.hero__dot {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 44px;
  background: none;
}

.hero__dot::before {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--outline);
  border-radius: 50%;
  transition: background 0.125s, transform 0.125s;
}

.hero__dot:hover::before {
  background: var(--brand);
}

.hero__dot.is-active::before {
  background: var(--accent-deep);
  transform: scale(1.35);
}

/* Slides that are not on screen must not be reachable by tab and must not be
   read out. The generated HTML ships `inert` on every slide after the first
   and the script moves it; this is the CSS half of the same contract. */
.hero__slide[inert] {
  user-select: none;
}

@media (max-width: 767px) {
  .hero__controls {
    bottom: 20px;
    gap: 16px;
  }
  .hero__arrow {
    width: 44px;
    height: 44px;
  }
}

/* A slider that moves on its own is a motion effect. Under reduced-motion the
   track jumps rather than slides, and main.js never starts the autoplay. */
@media (prefers-reduced-motion: reduce) {
  .hero__track {
    transition: none !important;
  }
  .hero__dot.is-active::before {
    transform: none;
  }
}

/* ==========================================================================
   Enquiry dialog
   The persistent Enquire button opens this on every page. Visually it is the
   existing contact form on a raised white surface — same fields, same rules,
   same accent — so the popup reads as part of the site rather than a widget
   dropped on top of it.
   ========================================================================== */
.enq-modal {
  width: min(560px, calc(100vw - 32px));
  max-height: min(88svh, 760px);
  padding: 0;
  border: 0;
  border-radius: var(--radius-lg);
  background: var(--surface-lowest);
  color: var(--on-surface);
  box-shadow: var(--shadow-card);
  overflow: auto;
  overscroll-behavior: contain;
}

.enq-modal::backdrop {
  background: rgba(16, 26, 64, 0.55);
}

/* The panel is the form itself, so a click anywhere it does not cover is the
   backdrop — that is what main.js tests for when closing on outside click. */
.enq-modal__panel {
  gap: 20px;
  padding: 32px 28px 28px;
}

.enq-modal__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 20px;
  border-bottom: var(--hairline) solid var(--outline-variant);
}

.enq-modal__head h2 {
  margin: 6px 0 0;
}

.enq-modal__close {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: var(--hairline) solid var(--outline-variant);
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--on-surface-variant);
  cursor: pointer;
  transition: border-color 0.2s var(--ease-smooth), color 0.2s var(--ease-smooth);
}

.enq-modal__close:hover {
  border-color: var(--accent);
  color: var(--accent-ink);
}

.enq-modal__lede {
  margin: 0;
  color: var(--on-surface-variant);
  font-size: var(--text-body);
  line-height: 1.6;
}

/* The shared .form-row spacing is tuned for the full-page form; inside the
   dialog the rows are already separated by the panel's own gap. */
.enq-modal .form-row {
  margin-bottom: 0;
  gap: 20px;
}

.enq-modal .form__status:empty {
  display: none;
}

.enq-modal__foot {
  margin: 0;
  padding-top: 4px;
  text-align: center;
  font-size: var(--text-micro);
}

.enq-modal__foot a {
  color: var(--on-surface-variant);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.enq-modal__foot a:hover {
  color: var(--accent-ink);
}

/* Holding the page still behind the dialog. <dialog> already makes the
   background inert; this stops the scroll bleed on iOS. */
body.has-modal {
  overflow: hidden;
}

/* On a phone the enquiry IS the task, so the dialog takes the viewport
   rather than floating as a card over a partially obscured page. */
@media (max-width: 599px) {
  .enq-modal {
    width: 100vw;
    max-width: 100vw;
    height: 100dvh;
    max-height: 100dvh;
    margin: 0;
    border-radius: 0;
  }
  /* Long option names ("Technological Structures") meet the caret and
     overflow the field without room and ellipsis. */
  .enq-modal .field select {
    padding-right: 28px;
    text-overflow: ellipsis;
  }
}

@media (min-width: 600px) {
  .enq-modal__panel {
    padding: 36px 36px 32px;
  }
  .enq-modal .form-row {
    grid-template-columns: 1fr 1fr;
  }
}

/* ==========================================================================
   Enquiry side button
   With the header's ENQUIRE removed this is the only persistent call to
   action, so it carries the accent rather than hiding on the page surface.
   The horizontal pill keeps the word visible without the clipping problem of
   the earlier vertical label.
   ========================================================================== */
.enq-rail {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  align-items: center;
}

.enq-rail__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding-inline: 18px;
  width: auto;
  height: 48px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-card);
  transition:
    background 0.2s var(--ease-smooth),
    transform 0.2s var(--ease-smooth);
  animation: enqRailIn 0.4s var(--ease-spring) 0.5s both;
}

.enq-rail__btn .icon {
  width: 20px;
  height: 20px;
}

.enq-rail__btn:hover {
  background: var(--accent-deep);
  transform: translateY(-2px);
}

.enq-rail__label {
  font-family: var(--font-display);
  font-size: var(--text-ui);
  font-weight: 800;
  letter-spacing: 0.08em;
  line-height: 1;
  text-transform: uppercase;
}

.enq-rail__social {
  position: fixed;
  top: 50%;
  right: 0;
  z-index: 61;
  display: flex;
  flex-direction: column;
  gap: 8px;
  transform: translateY(-50%);
}

.enq-rail__social__link {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 12px 0 0 12px;
  color: var(--on-surface-variant);
  box-shadow: var(--shadow-soft);
  transition:
    color 0.2s var(--ease-smooth),
    background 0.2s var(--ease-smooth),
    transform 0.2s var(--ease-smooth);
}

.enq-rail__social__link svg {
  width: 22px;
  height: 22px;
}

.enq-rail__social__link:hover {
  background: var(--accent-wash);
  color: var(--accent-ink);
  transform: translateY(-2px);
}

/* Instagram's official gradient treatment keeps the social action
   recognisable at the compact rail size. */
.enq-rail__social__link--instagram {
  position: relative;
  overflow: hidden;
  color: #fff;
  background: #5b1bb7;
}

.enq-rail__social__link--instagram::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(circle at 31% 107%, #fdf497 0 5%, #fdf497 6%, #fd5949 45%, #d6249f 60%, #285aeb 90%);
}

.enq-rail__social__link--instagram svg {
  position: relative;
  z-index: 1;
}

.enq-rail__social__link--instagram:hover {
  color: #fff;
  background: #4e159e;
}

.enq-rail__social__link--instagram:hover::before {
  filter: brightness(1.08);
}

@media (max-width: 899px) {
  .enq-rail {
    right: 14px;
    bottom: 14px;
  }
  .enq-rail__social__link {
    width: 44px;
    height: 44px;
  }
  .enq-rail__btn {
    width: auto;
    height: 44px;
    padding-inline: 15px;
  }
}

/* --- Enquiry dialog motion ---------------------------------------------
   The panel lifts and settles rather than appearing instantly, so the popup
   reads as coming from the page instead of being stamped over it. The exit
   is driven by main.js, which holds dialog.close() until the animation ends;
   without that a native <dialog> vanishes on the first frame. */
@keyframes enqPanelIn {
  from {
    opacity: 0;
    transform: translateY(14px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@keyframes enqPanelOut {
  from {
    opacity: 1;
    transform: none;
  }
  to {
    opacity: 0;
    transform: translateY(8px) scale(0.985);
  }
}

@keyframes enqBackdropIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.enq-modal[open] {
  animation: enqPanelIn 0.3s var(--ease-spring) both;
}

.enq-modal[open]::backdrop {
  animation: enqBackdropIn 0.3s var(--ease-smooth) both;
}

.enq-modal.is-closing,
.enq-modal.is-closing[open] {
  animation: enqPanelOut 0.18s var(--ease-smooth) both;
}

.enq-modal.is-closing::backdrop {
  animation: enqBackdropIn 0.18s var(--ease-smooth) reverse both;
}

/* The side button gets the same courtesy on first paint, so it arrives with
   the page rather than popping in after it. */
@keyframes enqRailIn {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Motion is decoration here — the dialog and the button must still work with
   it switched off, so under reduced-motion they simply appear. */
@media (prefers-reduced-motion: reduce) {
  .enq-modal[open],
  .enq-modal[open]::backdrop,
  .enq-modal.is-closing,
  .enq-modal.is-closing[open],
  .enq-modal.is-closing::backdrop,
  .enq-rail__btn {
    animation: none;
  }
  .enq-rail__btn:hover {
    transform: none;
  }
}

/* ==========================================================================
   Vision & mission
   Two statements of equal weight, so they sit side by side rather than one
   above the other. The accent rule at the top of each is the same marker the
   pillars use, which ties the two sections on the story page together.
   ========================================================================== */
.vm-grid {
  display: grid;
  gap: 0;
}

.vm {
  padding: 28px 0;
  border-top: var(--hairline) solid var(--outline-variant);
}

.vm__body {
  margin: 14px 0 0;
  max-width: 46ch;
  color: var(--on-surface-variant);
  font-size: var(--text-prose);
  line-height: 1.65;
}

.vm__cta {
  margin-top: 36px;
}

@media (min-width: 900px) {
  .vm-grid {
    grid-template-columns: 1fr 1fr;
    gap: 0 56px;
  }
}
