/* ==========================================================================
   BLAKEMERE ENGINEERING — SITE STYLESHEET
   Single source of truth for all 15 pages.

   Design language: "General Arrangement"
   The visual system borrows from the drawings, dial gauges and annotated
   photographs that Blakemere actually produces — hexagon geometry from the
   mark, a measured typographic grid, machined chamfers, and technical
   annotation. Every device is meant to carry meaning, not decorate.

   Structure
     01 Tokens
     02 Reset and base
     03 Typography
     04 Layout primitives
     05 Brand geometry (hex, lattice, dial, cut line)
     06 Header, navigation, mobile drawer
     07 Heroes
     08 Section heading device
     09 Components
     10 Page-specific blocks
     11 Footer
     12 Motion and reveal
     13 Reduced motion, print, forced colours
   ========================================================================== */

/* ==========================================================================
   01 TOKENS
   ========================================================================== */

/* Barlow Semi Condensed (body) and Barlow Condensed (headings, labels), SIL
   Open Font License 1.1, see fonts/Barlow-OFL.txt. Latin subset WOFF2 from
   Google Fonts, self-hosted so no visitor request goes to Google. Glyphs
   outside the subset (e.g. U+2192 arrow) fall through to the system font. */
@font-face {
  font-family: 'Barlow Semi Condensed';
  src: url('fonts/barlow-semi-condensed-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow Semi Condensed';
  src: url('fonts/barlow-semi-condensed-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow Semi Condensed';
  src: url('fonts/barlow-semi-condensed-700.woff2') format('woff2');
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow Condensed';
  src: url('fonts/barlow-condensed-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow Condensed';
  src: url('fonts/barlow-condensed-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Barlow Condensed';
  src: url('fonts/barlow-condensed-700.woff2') format('woff2');
  font-weight: 600 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* --- Brand core ------------------------------------------------------- */
  --teal: #00AF86;          /* brand teal. Graphics, rules, fills only     */
  --teal-ink: #00795A;      /* teal for TEXT on light. 5.4:1 on white      */
  --teal-bright: #33D6AC;   /* teal for text on dark. 5.8:1 on anthracite  */
  --teal-dim: #0C6E56;      /* pressed / visited                           */

  --anthracite: #3D4952;
  --anthracite-deep: #333D44;
  --black: #131619;
  --ink: #262C31;           /* body copy. Darkened from #33393D for 13.4:1 */
  --grey: #5E686D;          /* secondary copy. 5.9:1 on white              */
  --grey-light: #A2ABB0;    /* 11px on dark: 4.6:1 on anthracite           */
  --white: #FFFFFF;

  /* --- Surfaces --------------------------------------------------------- */
  --surface: #FFFFFF;
  --surface-alt: #F3F5F5;   /* alternate light band                        */
  --surface-sunk: #ECEFEF;
  --line: #DDE2E3;          /* hairline on light                           */
  --line-dark: rgba(255, 255, 255, 0.14);
  --line-teal: rgba(0, 175, 134, 0.35);

  /* --- Type ------------------------------------------------------------- */
  --font-display: 'Barlow Condensed', 'Roboto Condensed', system-ui,
                  -apple-system, 'Segoe UI', Arial, sans-serif;
  --font-body: 'Barlow Semi Condensed', system-ui, -apple-system, 'Segoe UI',
               Arial, sans-serif;
  --font-mono: var(--font-display); /* eyebrows, chips, spec labels */

  --fs-display: clamp(2.5rem, 6.4vw, 5.5rem);
  --fs-display-sm: clamp(2rem, 4.6vw, 3.6rem);
  --fs-h1: clamp(2rem, 4.2vw, 3.25rem);
  --fs-h2: clamp(1.55rem, 2.7vw, 2.3rem);
  --fs-h3: clamp(1.1rem, 1.5vw, 1.3rem);
  --fs-h4: 1.0625rem;
  --fs-body: 1.0625rem;      /* 17px */
  --fs-body-sm: 0.9375rem;   /* 15px */
  --fs-small: 0.875rem;      /* 14px */
  --fs-tiny: 0.8125rem;      /* 13px */
  --fs-eyebrow: 0.6875rem;   /* 11px */
  --fs-numeral: clamp(2.75rem, 5.2vw, 4.25rem);

  --lh-display: 0.96;
  --lh-head: 1.1;
  --lh-body: 1.65;

  /* Barlow Condensed is tightly fitted and kerns capital pairs hard, so the
     uppercase headings take slight positive tracking rather than the
     negative values DINOT needed. */
  --ls-display: 0.01em;
  --ls-head: 0.012em;
  --ls-eyebrow: 0.2em;

  /* --- Space ------------------------------------------------------------ */
  --gut: 32px;
  --wrap: 1240px;
  --wrap-narrow: 900px;
  --band-y: clamp(64px, 8vw, 116px);
  --band-y-sm: clamp(44px, 5vw, 68px);

  /* --- Form ------------------------------------------------------------- */
  --chamfer: 14px;
  --radius: 3px;
  --shadow-card: 0 1px 2px rgba(19, 22, 25, 0.04),
                 0 12px 32px -12px rgba(19, 22, 25, 0.14);
  --shadow-lift: 0 2px 4px rgba(19, 22, 25, 0.06),
                 0 22px 48px -16px rgba(19, 22, 25, 0.22);

  /* --- Motion ----------------------------------------------------------- */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 0.5s;
  --dur-fast: 0.22s;
}

/* ==========================================================================
   02 RESET AND BASE
   ========================================================================== */

*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: 96px;
  /* clip, not hidden: `overflow: hidden` on an ancestor would break the
     sticky header, and `clip` does not create a scroll container. Needed
     because the mobile drawer is parked off-screen with a transform. */
  overflow-x: clip;
}

body {
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-variant-numeric: tabular-nums;
  overflow-x: clip;
}
@supports not (overflow: clip) {
  body { overflow-x: hidden; }
}

a { color: inherit; text-decoration: none; }
/* height:auto matters. Without it the width and height attributes on an <img>
   apply as a real CSS height, aspect-ratio is ignored because neither axis is
   auto, and every case study figure rendered 1100px tall at any width instead
   of 16:11. */
img, svg, video, canvas { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
ul, ol { list-style: none; }

::selection { background: var(--teal); color: #fff; }

:focus-visible {
  outline: 2px solid var(--teal);
  outline-offset: 3px;
  border-radius: 1px;
}
header :focus-visible,
.on-dark :focus-visible,
.dark-band :focus-visible { outline-color: var(--teal-bright); }

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

.skip-link {
  position: fixed; top: -60px; left: 16px; z-index: 200;
  background: var(--teal); color: var(--black); padding: 10px 18px;
  font-size: var(--fs-small); font-weight: 500;
  transition: top var(--dur-fast) var(--ease);
}
.skip-link:focus { top: 12px; }

/* ==========================================================================
   03 TYPOGRAPHY
   ========================================================================== */

h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: var(--lh-head);
  letter-spacing: var(--ls-head);
  text-wrap: balance;
}

/* Display type. Uppercase, tight, set large. Because the brand has only
   Regular and Medium, hierarchy is carried by size, case and tracking
   rather than weight. */
.display {
  font-size: var(--fs-display);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
}
.display-sm {
  font-size: var(--fs-display-sm);
  line-height: 1.02;
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
}

/* Outlined second line — echoes the outline hexagons in the capability deck
   and lets a two-line statement carry emphasis without a Bold weight. */
.stroke {
  color: transparent;
  -webkit-text-stroke: 1.25px currentColor;
  text-stroke: 1.25px currentColor;
  paint-order: stroke fill;
  /* The stroke grows each glyph outwards; open the fit so outlines do not touch. */
  letter-spacing: 0.035em;
}
.on-dark .stroke, .hero .stroke { -webkit-text-stroke-width: 1.5px; -webkit-text-stroke-color: rgba(255,255,255,0.8); }
@supports not (-webkit-text-stroke: 1px black) {
  .stroke { color: inherit; opacity: 0.55; }
}

/* Technical annotation. Reads as a drawing label. */
.eyebrow, .tag, .sec-eyebrow, .cap-eyebrow, .tf-eyebrow, .tr-eyebrow,
.ind-eyebrow, .sub-eyebrow, .home-tag, .scope-tag, .contract-label,
.iso-code, .s-abbr {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey);
}
.on-dark .eyebrow, .dark-band .eyebrow, .capabilities .eyebrow,
.on-dark .tag, .dark-band .tag { color: var(--grey-light); }
.eyebrow--teal { color: var(--teal-ink); }
.on-dark .eyebrow--teal, .dark-band .eyebrow--teal { color: var(--teal-bright); }

/* Prose */
p { max-width: 68ch; }
.lede {
  font-size: clamp(1.0625rem, 1.5vw, 1.3125rem);
  line-height: 1.55;
  color: var(--grey);
  max-width: 60ch;
}
.on-dark .lede, .dark-band .lede { color: #C3CACE; }

.prose > * + * { margin-top: 1.1em; }
.prose h3 { margin-top: 2em; font-size: var(--fs-h3); }
.prose ul { margin-top: 1.1em; }
.prose li {
  position: relative;
  padding-left: 26px;
  margin-top: 0.6em;
  max-width: 66ch;
}
/* Hexagon bullet, lifted from the mark */
.prose li::before {
  content: '';
  position: absolute;
  left: 2px; top: 0.62em;
  width: 9px; height: 10px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.on-dark .prose li::before, .dark-band .prose li::before { background: var(--teal-bright); }

.accent { color: var(--teal-ink); }
.on-dark .accent, .dark-band .accent, .hero .accent, .capabilities .accent { color: var(--teal-bright); }
.accent-white { color: var(--white); }

strong, b { font-weight: 500; color: var(--ink); }
.on-dark strong, .dark-band strong { color: #fff; }

/* Numerals — DIN's figures are the strongest thing in the family, so proof
   points are set as numerals first and words second. */
.numeral {
  font-family: var(--font-display);
  font-size: var(--fs-numeral);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--teal-ink);
}
.on-dark .numeral, .dark-band .numeral { color: var(--teal-bright); }
.numeral sup, .numeral .unit {
  font-size: 0.36em;
  letter-spacing: 0.06em;
  vertical-align: super;
  margin-left: 2px;
}

/* ==========================================================================
   04 LAYOUT PRIMITIVES
   ========================================================================== */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 0 var(--gut);
}
.wrap--narrow { max-width: var(--wrap-narrow); }
@media (max-width: 640px) { :root { --gut: 20px; } }

section { position: relative; }

/* Bands. The old site alternated light/dark on a fixed cadence, which read
   as a template. Bands are now chosen per section and the dark ones carry
   the hex lattice so they feel built rather than filled.
   Note: the padding utility is .sect, not .band — track-record.html already
   uses .band for a row of figures. */
.sect { padding: var(--band-y) 0; }
.sect--sm { padding: var(--band-y-sm) 0; }
.band--alt { background: var(--surface-alt); }
.band--dark, .dark-band, .capabilities {
  background: var(--anthracite-deep);
  color: #D7DCDF;
}
.band--black { background: var(--black); color: #D7DCDF; }
.band--dark h1, .band--dark h2, .band--dark h3, .band--dark h4,
.dark-band h1, .dark-band h2, .dark-band h3, .dark-band h4,
.capabilities h1, .capabilities h2, .capabilities h3, .capabilities h4,
.band--black h1, .band--black h2, .band--black h3 { color: #fff; }

/* Grids */
.grid { display: grid; gap: 24px; }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }
/* Asymmetric editorial split — deliberately not 50/50 */
.grid--split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(28px, 4vw, 64px); align-items: center; }
.grid--split-rev { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: clamp(28px, 4vw, 64px); align-items: center; }
.grid--aside { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: clamp(28px, 4vw, 64px); }

@media (max-width: 1000px) {
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .grid--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 860px) {
  .grid--2, .grid--3, .grid--split, .grid--split-rev, .grid--aside { grid-template-columns: 1fr; }
}
@media (max-width: 560px) { .grid--4 { grid-template-columns: 1fr; } }

/* Machined chamfer. A cut corner instead of a rounded one — the whole
   business is cutting steel accurately, so the card shape says so. */
.chamfer {
  clip-path: polygon(
    0 0,
    calc(100% - var(--chamfer)) 0,
    100% var(--chamfer),
    100% 100%,
    0 100%
  );
}
.chamfer--bl {
  clip-path: polygon(
    0 0, 100% 0, 100% 100%,
    var(--chamfer) 100%, 0 calc(100% - var(--chamfer))
  );
}

/* ==========================================================================
   05 BRAND GEOMETRY
   The mark is a hexagon. The old site never used that geometry anywhere,
   which is the main reason it read as generic. These are the primitives.
   ========================================================================== */

/* --- Hexagon ------------------------------------------------------------- */
.hex {
  --hex-clip: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  clip-path: var(--hex-clip);
  aspect-ratio: 1 / 1.1547;   /* true regular hexagon, pointy top */
}

/* Outlined hex, drawn rather than filled — matches the deck's capability
   wheel. Uses a masked pseudo-element so the stroke stays crisp. */
.hex-outline {
  position: relative;
  aspect-ratio: 1 / 1.1547;
  display: grid;
  place-items: center;
  text-align: center;
}
.hex-outline::before {
  content: '';
  position: absolute; inset: 0;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  padding: 1.5px;
  transition: background var(--dur-fast) var(--ease);
}
.hex-outline:hover::before { background: var(--teal-bright); }

/* --- Hex lattice --------------------------------------------------------- */
/* Faint tessellated hexagons for dark bands. Encoded inline so the site
   stays a self-contained folder with no extra asset requests. */
.lattice { position: relative; isolation: isolate; }
.lattice::before {
  content: '';
  position: absolute; inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='97' viewBox='0 0 56 97'%3E%3Cg fill='none' stroke='%2300AF86' stroke-width='1'%3E%3Cpath d='M28 0 56 16v32L28 64 0 48V16z'/%3E%3Cpath d='M28 64 56 80v32M28 64 0 80v32M56 16 84 0M0 16-28 0'/%3E%3C/g%3E%3C/svg%3E");
  background-size: 56px 97px;
  opacity: 0.13;
}
.lattice--soft::before { opacity: 0.07; background-size: 84px 145px; }

/* --- Instrument dial ----------------------------------------------------- */
/* Radial tick motif from the deck's cover and contact slides. Reads as a
   pressure gauge or a bearing plate. Sits behind dark hero content. */
/* The dial was removed in rev 3.5. The rotating hexagon read as a
   distraction behind every page heading. */

/* --- Cut line ------------------------------------------------------------ */
/* A diamond wire makes a cut. Section transitions draw a teal line across
   rather than fading content up, so the motion means something. */
.cut {
  position: relative;
  height: 1px;
  background: var(--line);
  overflow: visible;
}
.cut::after {
  content: '';
  position: absolute;
  left: 0; top: 0; height: 100%;
  width: 100%;
  background: var(--teal);
  transition: width 1.1s var(--ease-out);
}
.js .cut::after { width: 0; }
.cut.is-in::after { width: 100%; }
.dark-band .cut, .band--dark .cut { background: var(--line-dark); }

/* Rule under a heading — the deck's teal bar, reduced to a measured rule */
.rule {
  width: 56px; height: 3px;
  background: var(--teal);
  margin-top: 20px;
  transform-origin: left center;
  transition: transform 0.7s var(--ease-out) 0.1s;
}
/* Default is drawn. Only a rule inside a section still waiting to reveal is
   held back, so a rule can never be stranded at zero width. */
.js [data-reveal]:not(.is-in) .rule { transform: scaleX(0); }

/* ==========================================================================
   06 HEADER, NAVIGATION, MOBILE DRAWER
   ========================================================================== */

header {
  position: sticky;
  top: 0;
  z-index: 120;
  background: rgba(51, 61, 68, 0.92);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  transition: background var(--dur-fast) var(--ease);
}
@supports not (backdrop-filter: blur(1px)) {
  header { background: var(--anthracite-deep); }
}

/* Scroll progress. Doubles as a depth read-out on a subsea site. */
.scroll-progress {
  position: absolute;
  left: 0; bottom: -1px;
  height: 2px;
  width: var(--progress, 0%);
  background: linear-gradient(90deg, var(--teal-dim), var(--teal));
  z-index: 2;
}

header nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 10px 0;
}
.logo-lockup { height: 52px; width: auto; }

.nav-links { display: flex; align-items: center; gap: 4px; }
.nav-links > a, .nav-item > a {
  display: block;
  padding: 10px 13px;
  color: #E6EAEC;
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.01em;
  white-space: nowrap;
  position: relative;
}
/* Underline grows from the left, like a dimension line being set out */
.nav-links > a::after, .nav-item > a::after {
  content: '';
  position: absolute;
  left: 13px; right: 13px; bottom: 4px;
  height: 2px;
  background: var(--teal);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur-fast) var(--ease);
}
.nav-links > a:hover::after,
.nav-item:hover > a::after,
.nav-item:focus-within > a::after,
.nav-links > a.active::after,
.nav-item > a.active::after { transform: scaleX(1); }
.nav-links > a:hover, .nav-item > a:hover { color: #fff; }
.nav-links a.active { color: #fff; }

.nav-item { position: relative; }
/* Dropdown affordance. Drawn as a background chevron on the right of the
   label so it cannot be mistaken for punctuation in the text flow. */
.nav-item.has-dropdown > a { padding-right: 24px; }
.nav-item.has-dropdown > a {
  background-image:
    linear-gradient(45deg, transparent 46%, currentColor 46%, currentColor 60%, transparent 60%),
    linear-gradient(-45deg, transparent 46%, currentColor 46%, currentColor 60%, transparent 60%);
  background-size: 5px 5px, 5px 5px;
  background-position: right 14px top calc(50% + 1px), right 10px top calc(50% + 1px);
  background-repeat: no-repeat;
}

.dropdown {
  display: none;
  position: absolute;
  top: 100%; left: 0;
  padding-top: 10px;
  z-index: 20;
}
.nav-item:hover .dropdown, .nav-item:focus-within .dropdown { display: block; }
.dropdown-inner {
  background: var(--anthracite-deep);
  min-width: 210px;
  padding: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 20px 44px rgba(0, 0, 0, 0.45);
  animation: dd-in 0.2s var(--ease-out);
}
@keyframes dd-in { from { opacity: 0; transform: translateY(-5px); } }
.dropdown-inner a {
  display: block;
  padding: 9px 12px;
  font-size: var(--fs-tiny);
  font-weight: 500;
  color: #D7DCDF;
  border-left: 2px solid transparent;
  white-space: nowrap;
}
.dropdown-inner a:hover { color: #fff; background: rgba(255,255,255,0.05); border-left-color: var(--teal); }
.dropdown-inner a.active { color: var(--teal-bright); border-left-color: var(--teal); }

header nav a.contact, .nav-cta {
  border: 1px solid var(--teal);
  color: #fff;
  padding: 9px 18px;
  font-size: var(--fs-small);
  font-weight: 500;
  transition: background var(--dur-fast) var(--ease);
}
header nav a.contact::after, .nav-cta::after { content: none; }
header nav a.contact:hover, .nav-cta:hover { background: var(--teal); }

/* --- Mobile drawer ------------------------------------------------------- */
.nav-toggle {
  display: none;
  width: 44px; height: 44px;
  position: relative;
  flex: 0 0 auto;
}
.nav-toggle span {
  position: absolute;
  left: 11px; right: 11px;
  height: 2px;
  background: #fff;
  transition: transform var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.nav-toggle span:nth-child(1) { top: 15px; }
.nav-toggle span:nth-child(2) { top: 21px; }
.nav-toggle span:nth-child(3) { top: 27px; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

@media (max-width: 960px) {
  .nav-toggle { display: block; }
  .logo-lockup { height: 44px; }
  .nav-links {
    position: fixed;
    inset: 0 0 0 auto;
    width: min(88vw, 380px);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--anthracite-deep);
    padding: 88px 24px 40px;
    overflow-y: auto;
    transform: translateX(100%);
    transition: transform 0.34s var(--ease-out);
    box-shadow: -24px 0 60px rgba(0, 0, 0, 0.4);
    z-index: 110;
  }
  .nav-links[data-open="true"] { transform: translateX(0); }
  .nav-links > a, .nav-item > a {
    padding: 15px 4px;
    font-size: 1.0625rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
  }
  .nav-links > a::after, .nav-item > a::after { content: none; }
  .nav-item > a::before { float: right; margin-top: 8px; transform: rotate(45deg); }
  .nav-item { border: 0; }
  .dropdown { display: block; position: static; padding: 0 0 10px; }
  .dropdown-inner {
    background: none; border: 0; box-shadow: none; padding: 4px 0 0 14px;
    border-left: 1px solid var(--line-teal); animation: none; min-width: 0;
  }
  .dropdown-inner a { padding: 10px 8px; font-size: var(--fs-body-sm); }
  header nav a.contact { margin-top: 18px; text-align: center; }
  .nav-scrim {
    position: fixed; inset: 0;
    background: rgba(10, 13, 15, 0.6);
    opacity: 0; pointer-events: none;
    transition: opacity var(--dur-fast) var(--ease);
    z-index: 105;
  }
  .nav-scrim[data-open="true"] { opacity: 1; pointer-events: auto; }
  body[data-nav-open="true"] { overflow: hidden; }
}

/* ==========================================================================
   07 HEROES
   ========================================================================== */

.hero {
  position: relative;
  overflow: hidden;
  background: var(--black);
  color: #fff;
  isolation: isolate;
}
.hero-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -2;
  transform: scale(1.04);
}
.hero-overlay {
  position: absolute; inset: 0;
  z-index: -1;
  background:
    linear-gradient(96deg,
      rgba(11, 14, 16, 0.94) 0%,
      rgba(11, 14, 16, 0.78) 38%,
      rgba(11, 14, 16, 0.22) 76%,
      rgba(11, 14, 16, 0.32) 100%);
}
/* Fine scanline grain. Keeps large flat photo areas from banding and reads
   as an ROV camera feed rather than a stock overlay. */
.hero-overlay::after {
  content: '';
  position: absolute; inset: 0;
  background: repeating-linear-gradient(
    180deg, rgba(255,255,255,0.028) 0 1px, transparent 1px 3px);
  mix-blend-mode: overlay;
}

.hero-content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: flex-end;
  min-height: min(78vh, 700px);
  padding: 140px 0 clamp(44px, 6vw, 76px);
}
.hero-content .wrap { width: 100%; }
.hero h1 {
  font-size: clamp(2.1rem, 5vw, 4.3rem);
  line-height: 1.0;
  letter-spacing: var(--ls-display);
  text-transform: uppercase;
  color: #fff;
  max-width: 100%;
}
/* The photographic plate carries a graded black panel across its left side.
   Hero copy is held inside that panel so the stroked line keeps its contrast
   against a dark ground rather than open water. */
.hero-content .wrap > * { max-width: min(620px, 52%); }
@media (max-width: 1100px) { .hero-content .wrap > * { max-width: min(620px, 68%); } }
@media (max-width: 899px)  { .hero-content .wrap > * { max-width: 100%; } }
.hero .lede { margin-top: 22px; max-width: 46ch; color: #C9D0D4; }
.hero .eyebrow { margin-bottom: 22px; color: var(--teal-bright); }

/* Measured hero foot — a dimension strip carrying the primary proof points */
.hero-foot {
  position: relative;
  z-index: 1;
  background: var(--black);
  border-bottom: 1px solid rgba(255, 255, 255, 0.09);
}
.hero-foot .wrap {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
/* Scoped to the direct children of .wrap: a bare `.hero-foot div` selector
   also matches the .wrap container and strips its gutter. */
.hero-foot .wrap > div {
  padding: 20px 24px 20px 22px;
  border-left: 1px solid rgba(255, 255, 255, 0.13);
}
.hero-foot .wrap > div:first-child { border-left: 0; padding-left: 0; }
.hero-foot b {
  display: block;
  font-size: clamp(1.35rem, 2.1vw, 1.85rem);
  font-weight: 500;
  color: #fff;
  line-height: 1;
  letter-spacing: -0.02em;
}
.hero-foot span {
  display: block;
  margin-top: 8px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey-light);
  line-height: 1.4;
}
@media (max-width: 860px) {
  .hero-foot .wrap { grid-template-columns: 1fr 1fr; }
  .hero-foot .wrap > div:nth-child(3) { border-left: 0; padding-left: 0; }
  .hero-foot .wrap > div { padding-top: 16px; padding-bottom: 16px; }
}
@media (max-width: 460px) {
  .hero-foot .wrap { grid-template-columns: 1fr; }
  .hero-foot .wrap > div { border-left: 0; padding-left: 0; border-top: 1px solid rgba(255,255,255,0.12); }
  .hero-foot .wrap > div:first-child { border-top: 0; }
}

/* Scroll cue */
.scroll-cue {
  position: absolute;
  right: var(--gut); bottom: 22px;
  z-index: 2;
  display: flex; align-items: center; gap: 10px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}
.scroll-cue i {
  display: block; width: 1px; height: 34px;
  background: linear-gradient(180deg, var(--teal), transparent);
  animation: cue 2.4s var(--ease) infinite;
}
@keyframes cue { 0%, 100% { transform: scaleY(0.4); opacity: 0.4; } 50% { transform: scaleY(1); opacity: 1; } }
@media (max-width: 860px) { .scroll-cue { display: none; } }

/* --- Interior page hero -------------------------------------------------- */
/* Sub-pages get a compact banded hero rather than a full photo stage, so the
   homepage keeps its impact and interior pages get to the content faster. */
.page-hero {
  position: relative;
  background: var(--anthracite-deep);
  color: #fff;
  padding: clamp(56px, 8vw, 104px) 0 clamp(40px, 5vw, 64px);
  overflow: hidden;
}
.page-hero h1 {
  font-size: var(--fs-h1);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  max-width: 26ch;
  color: #fff;
}
.page-hero .lede { margin-top: 20px; max-width: 62ch; }
.page-hero .eyebrow { color: var(--teal-bright); }

/* Breadcrumb. One pattern on every page:
   <nav class="crumb" aria-label="Breadcrumb"><ol><li><a>…</a></li>…
   <li aria-current="page">…</li></ol></nav>
   The separator is drawn here, so the markup never carries a slash. Keep the
   trail in step with the page's BreadcrumbList structured data. */
.crumb {
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.68);
  margin-bottom: 20px;
}
.crumb ol {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  list-style: none; margin: 0; padding: 0;
}
.crumb a:hover { color: var(--teal-bright); }
.crumb li + li::before { content: '/'; margin-right: 9px; opacity: 0.5; }

/* ==========================================================================
   08 SECTION HEADING DEVICE
   The deck's signature is a grey letterspaced eyebrow over a teal bar. On the
   web that becomes eyebrow + large heading + a measured rule that draws in.
   Every section on every page uses it, which is what makes the site cohere.
   ========================================================================== */

.rule-head { margin-bottom: clamp(32px, 4vw, 56px); max-width: 46ch; }
.rule-head h2, .rule-head h1 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-top: 12px;
}
.rule-head p { margin-top: 16px; color: var(--grey); }
.dark-band .rule-head p, .band--dark .rule-head p, .capabilities .rule-head p { color: #B9C1C6; }
.rule-head--wide { max-width: 62ch; }
.rule-head--center { margin-left: auto; margin-right: auto; text-align: center; }
.rule-head--center .rule { margin-left: auto; margin-right: auto; transform-origin: center; }

/* ==========================================================================
   09 COMPONENTS
   ========================================================================== */

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  background: var(--teal);
  /* Near-black on brand teal is 6.5:1. White on brand teal is 2.81:1 and
     fails WCAG AA at button text sizes, which the first pass did site-wide. */
  color: var(--black);
  padding: 14px 26px;
  font-size: var(--fs-small);
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  position: relative;
  overflow: hidden;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
  transition: background var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn::after {
  content: '';
  width: 16px; height: 1px;
  background: currentColor;
  transition: width var(--dur-fast) var(--ease);
}
.btn:hover { background: var(--teal-bright); transform: translateY(-2px); }
.btn:hover::after { width: 26px; }
.btn:active { transform: translateY(0); }

.btn--ghost {
  background: none;
  border: 1px solid var(--teal);
  color: var(--teal-ink);
}
.btn--ghost:hover { background: var(--teal); color: #fff; }
.on-dark .btn--ghost, .dark-band .btn--ghost, .capabilities .btn--ghost,
.cap-band .btn--ghost, .hero .btn--ghost {
  color: #fff; border-color: rgba(255, 255, 255, 0.42);
}
.on-dark .btn--ghost:hover, .dark-band .btn--ghost:hover,
.cap-band .btn--ghost:hover, .hero .btn--ghost:hover { border-color: var(--teal); background: var(--teal); color: #fff; }

/* Inline forward link. Replaces the old teal 13px links, which failed
   contrast at that size. */
.arrow, a.arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--teal-ink);
  letter-spacing: 0.01em;
}
.arrow::after {
  content: '';
  width: 14px; height: 1px;
  background: currentColor;
  transition: width var(--dur-fast) var(--ease);
}
.arrow:hover::after { width: 24px; }
.on-dark .arrow, .dark-band .arrow, .capabilities .arrow { color: var(--teal-bright); }

/* --- Card base ----------------------------------------------------------- */
.card, .cap-card, .tw-card, .hiring-card, .stat-card, .iso-item, .faq-item {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  transition: border-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.dark-band .card, .band--dark .card, .capabilities .card {
  background: rgba(255, 255, 255, 0.035);
  border-color: var(--line-dark);
}

/* --- Lifecycle hex tiles -------------------------------------------------- */
/* The four asset-lifecycle stages are the organising idea of the whole
   business, so they get the brand's own geometry rather than a generic card.
   Mirrors the capability wheel on slide 3 of the deck. */
.hexrow {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(12px, 1.6vw, 26px);
  align-items: start;
}
.hexrow > * { min-width: 0; }
@media (max-width: 1000px) { .hexrow { grid-template-columns: repeat(2, 1fr); row-gap: 34px; } }
@media (max-width: 520px) { .hexrow { grid-template-columns: 1fr; } }

.hextile { position: relative; padding-top: 8px; }
.hextile-mark {
  position: relative;
  width: 84px;
  margin-bottom: 22px;
}
.hextile-mark .hx {
  aspect-ratio: 1 / 1.1547;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: rgba(0, 175, 134, 0.13);
  display: grid;
  place-items: center;
  transition: background var(--dur) var(--ease);
}
.hextile-mark .hx-num {
  font-size: 1.5rem;
  font-weight: 500;
  color: var(--teal-ink);
  letter-spacing: -0.02em;
  line-height: 1;
}
.dark-band .hextile-mark .hx { background: rgba(0, 175, 134, 0.2); }
.dark-band .hextile-mark .hx-num, .capabilities .hextile-mark .hx-num { color: var(--teal-bright); }
.hextile:hover .hextile-mark .hx { background: var(--teal); }
.hextile:hover .hextile-mark .hx-num { color: var(--black); }

.hextile h3 {
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: -0.005em;
}
.hextile p { margin-top: 12px; font-size: var(--fs-body-sm); color: var(--grey); }
.dark-band .hextile p, .capabilities .hextile p { color: #AEB7BC; }
.hextile .arrow { margin-top: 18px; }
/* Connector rule between tiles, like a process flow on a drawing */
.hextile::before {
  content: '';
  position: absolute;
  top: 46px; left: 96px; right: calc(-1 * clamp(12px, 1.6vw, 26px));
  height: 1px;
  background: var(--line-teal);
}
.hextile:last-child::before { display: none; }
@media (max-width: 1000px) { .hextile::before { display: none; } }

/* --- Proof band ---------------------------------------------------------- */
/* Real figures, set as numerals. Replaces the four teal rectangles that
   carried the same information with none of the weight. */
.proof {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--line-dark);
  border: 1px solid var(--line-dark);
}
.proof > div {
  background: var(--anthracite-deep);
  padding: clamp(24px, 3vw, 40px) clamp(18px, 2vw, 30px);
}
.proof .numeral { display: block; }
.proof h3 {
  margin-top: 14px;
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #fff;
}
.proof p { margin-top: 8px; font-size: var(--fs-tiny); color: #A6AFB4; line-height: 1.55; }
@media (max-width: 900px) { .proof { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .proof { grid-template-columns: 1fr; } }

/* --- Dimension scale ----------------------------------------------------- */
/* Slide 8 of the deck plots the diamond wire saw fleet by cut size. That is
   the single most useful thing an operator can see on the rentals page, so it
   becomes a measured scale rather than a row of identical cards. */
.scale {
  position: relative;
  margin: 48px 0 8px;
  padding: 0 0 74px;
}
.scale-rule {
  position: relative;
  height: 2px;
  background: linear-gradient(90deg, var(--teal) 0%, var(--teal-dim) 100%);
}
.scale-tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  text-align: center;
}
.scale-tick i {
  display: block;
  width: 1px; height: 13px;
  margin: 0 auto;
  background: var(--teal);
  opacity: 0.6;
}
.scale-tick b {
  display: block;
  margin-top: 7px;
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--grey);
}
.scale-item {
  position: absolute;
  bottom: 0;
  transform: translateX(-50%);
  width: 116px;
  text-align: center;
}
.scale-item i {
  display: block;
  width: 1px;
  height: 20px;
  margin: 0 auto 8px;
  background: var(--line-teal);
}
.scale-item b {
  display: block;
  font-size: var(--fs-tiny);
  font-weight: 500;
  color: var(--ink);
}
.scale-item span {
  display: block;
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.08em;
  color: var(--grey);
  margin-top: 3px;
}
@media (max-width: 860px) { .scale { display: none; } }

/* --- Annotated figure ---------------------------------------------------- */
/* Leader lines to boxed labels, as on the AX machining tool slides. Applied
   to real tooling photography where naming the parts is the point. */
.figure { position: relative; }
.figure img { width: 100%; }
.figure-note {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 0;
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  pointer-events: none;
}
.figure-note b {
  background: rgba(19, 22, 25, 0.86);
  color: #fff;
  border-left: 2px solid var(--teal);
  padding: 6px 10px;
  font-weight: 500;
  white-space: nowrap;
}
.figure-note i {
  height: 1px;
  width: 42px;
  background: var(--teal);
  flex: 0 0 auto;
}
.figure-note--left { flex-direction: row-reverse; }
.figure-note--left b { border-left: 0; border-right: 2px solid var(--teal); }
@media (max-width: 760px) { .figure-note { display: none; } }

/* Figure caption — drawing-sheet style */
.figure figcaption, .fig-cap {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-tiny);
  color: var(--grey);
  display: flex;
  gap: 14px;
}
.fig-cap b {
  font-weight: 500;
  color: var(--teal-ink);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: var(--fs-eyebrow);
  flex: 0 0 auto;
  padding-top: 2px;
}

/* --- Imagery ------------------------------------------------------------- */
.photo-real, .sec-photo img, .lf-photo img, .ind-photo img, .cap-photo img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
}
.photo-real.contain { object-fit: contain; }

.media { position: relative; overflow: hidden; background: var(--surface-sunk); }
.media img { width: 100%; height: 100%; object-fit: cover; }
.media--16-9 { aspect-ratio: 16 / 9; }
.media--16-11 { aspect-ratio: 16 / 11; }
.media--4-3 { aspect-ratio: 4 / 3; }
.media--square { aspect-ratio: 1; }
.media--tall { aspect-ratio: 3 / 4; }

/* Duotone. Section-divider photography is knocked back into the brand pair so
   it supports the type instead of competing with it. Equipment shots stay in
   full colour, because the yellow and orange of the tooling is information. */
.duotone { position: relative; }
.duotone img { filter: grayscale(1) contrast(1.08) brightness(0.92); }
.duotone::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(150deg, rgba(0, 175, 134, 0.5), rgba(19, 22, 25, 0.72));
  mix-blend-mode: multiply;
}
.duotone--soft::after { opacity: 0.6; }

/* Placeholders. Deliberately obvious — an unsupplied asset should read as an
   open item, not as a design choice. */
.photo-ph, .ph {
  position: relative;
  background:
    repeating-linear-gradient(45deg,
      rgba(0, 175, 134, 0.05) 0 8px,
      rgba(0, 175, 134, 0.11) 8px 16px);
  border: 1px dashed var(--line-teal);
  display: grid;
  place-items: center;
  min-height: 200px;
  aspect-ratio: 16 / 11;
  color: var(--grey);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  text-align: center;
  padding: 20px;
}
.photo-ph.square, .ph.square { aspect-ratio: 1; }
.photo-ph.tall, .ph.tall { aspect-ratio: 3 / 4; }
.photo-ph.wide, .ph.wide { aspect-ratio: 21 / 9; }
.photo-ph.dark, .ind-photo.dark {
  background:
    repeating-linear-gradient(45deg,
      rgba(255, 255, 255, 0.04) 0 8px,
      rgba(255, 255, 255, 0.08) 8px 16px);
  border-color: rgba(255, 255, 255, 0.2);
  color: var(--grey-light);
}

/* --- Notes and flags ----------------------------------------------------- */
/* Amber callout component. Retained for future use; no page currently uses it. */
.insert-note, .cap-note, .flag {
  display: block;
  border-left: 3px solid #E0A32E;
  background: rgba(224, 163, 46, 0.09);
  padding: 14px 18px;
  font-size: var(--fs-tiny);
  line-height: 1.55;
  color: #6B4C08;
  margin: 20px 0;
}
.flag { display: inline-block; margin: 0; padding: 3px 9px; font-size: var(--fs-eyebrow); letter-spacing: 0.08em; text-transform: uppercase; }
.dark-band .insert-note, .dark-band .cap-note,
.capabilities .insert-note, .capabilities .cap-note,
.on-dark .insert-note, .on-dark .cap-note {
  color: #F2DCA6;
  background: rgba(224, 163, 46, 0.14);
}
.dark-band .insert-note strong, .capabilities .insert-note strong,
.on-dark .insert-note strong { color: #F7E9C4; }

.callout {
  border-left: 3px solid var(--teal);
  background: var(--surface-alt);
  padding: clamp(20px, 2.4vw, 30px);
  margin: 32px 0;
}
.callout p { max-width: 62ch; }
.callout p + p { margin-top: 0.9em; }

/* --- Accordions ---------------------------------------------------------- */
.acc {
  border-bottom: 1px solid var(--line);
  background: none;
}
.acc > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: 22px 0;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: var(--ls-head);
  color: var(--ink);
  transition: color var(--dur-fast) var(--ease);
}
.acc > summary::-webkit-details-marker { display: none; }
.acc > summary:hover { color: var(--teal-ink); }
.acc-body { padding: 0 0 28px; max-width: 72ch; }
.acc-body > * + * { margin-top: 1em; }
.chev {
  flex: 0 0 auto;
  width: 30px; height: 30px;
  border: 1px solid var(--line-teal);
  position: relative;
  transition: background var(--dur-fast) var(--ease), transform var(--dur) var(--ease);
}
.chev::before, .chev::after {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  background: var(--teal-ink);
  transition: opacity var(--dur-fast) var(--ease);
}
.chev::before { width: 11px; height: 1.5px; transform: translate(-50%, -50%); }
.chev::after { width: 1.5px; height: 11px; transform: translate(-50%, -50%); }
.acc[open] > summary .chev::after { opacity: 0; }
.acc[open] > summary .chev { background: rgba(0, 175, 134, 0.1); }
.acc[open] > summary { color: var(--teal-ink); }

/* .on-dark belongs in this list. The plugs section on bespoke engineering is
   an .on-dark band, and without it the accordion summaries inherited the
   light-background colour and rendered near-black on anthracite. */
.dark-band .acc, .capabilities .acc, .on-dark .acc { border-color: var(--line-dark); }
.dark-band .acc > summary, .capabilities .acc > summary, .on-dark .acc > summary { color: #fff; }
.dark-band .acc > summary:hover, .capabilities .acc > summary:hover, .on-dark .acc > summary:hover { color: var(--teal-bright); }
.dark-band .acc[open] > summary, .capabilities .acc[open] > summary, .on-dark .acc[open] > summary { color: var(--teal-bright); }
.dark-band .chev, .capabilities .chev, .on-dark .chev { border-color: rgba(255, 255, 255, 0.3); }
.dark-band .chev::before, .dark-band .chev::after,
.capabilities .chev::before, .capabilities .chev::after,
.on-dark .chev::before, .on-dark .chev::after { background: var(--teal-bright); }
.dark-band .acc[open] > summary .chev,
.capabilities .acc[open] > summary .chev,
.on-dark .acc[open] > summary .chev { background: rgba(0, 175, 134, 0.18); }
.dark-band .acc-body, .capabilities .acc-body, .on-dark .acc-body { color: #B9C1C6; }

/* --- Logo carousel ------------------------------------------------------- */
.logos-section { padding: var(--band-y-sm) 0; border-bottom: 1px solid var(--line); }
.logos-section .rule-head h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
}
.logo-carousel-outer {
  overflow: hidden;
  width: 100%;
  margin-top: 28px;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 7%, #000 93%, transparent);
}
.logo-track {
  display: flex;
  align-items: center;
  gap: 46px;
  width: max-content;
  animation: logo-scroll 62s linear infinite;
}
.logo-track:hover { animation-play-state: paused; }
@keyframes logo-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.logo-chip {
  flex: 0 0 auto;
  width: 140px; height: 72px;
  display: flex; align-items: center; justify-content: center;
  padding: 10px 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  filter: grayscale(1);
  opacity: 0.78;
  transition: filter var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.logo-chip:hover { border-color: var(--line-teal); }
.logo-chip:hover { filter: none; opacity: 1; }
.logos-section { background: var(--surface-alt); border-top: 1px solid var(--line); }
.logo-chip img { max-width: 100%; max-height: 100%; object-fit: contain; }
.logo-chip.invert img { filter: invert(1) brightness(0.35); }

/* --- CTA band ------------------------------------------------------------ */
.cta-band {
  position: relative;
  background: var(--anthracite-deep);
  color: #fff;
  padding: clamp(56px, 6.5vw, 92px) 0;
  overflow: hidden;
  text-align: center;
}
.cta-band h2 {
  position: relative;
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  color: #fff;
  margin: 0 auto;
  max-width: 30ch;
}
.cta-band p { position: relative; margin: 18px auto 0; color: #B9C1C6; max-width: 56ch; }
.cta-band .btn { position: relative; margin-top: 30px; }

/* --- Onward navigation --------------------------------------------------- */
.onward {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.onward > a {
  background: var(--surface);
  padding: clamp(24px, 3vw, 38px) clamp(20px, 3vw, 40px);
  transition: background var(--dur-fast) var(--ease);
}
.onward > a:hover { background: var(--surface-alt); }
.onward .eyebrow { color: var(--teal-ink); }
.onward strong {
  display: block;
  margin-top: 10px;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
}
@media (max-width: 700px) { .onward { grid-template-columns: 1fr; } }

/* --- Tables -------------------------------------------------------------- */
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 28px 0; min-width: 0; }
table { width: 100%; border-collapse: collapse; font-size: var(--fs-body-sm); }
th, td { text-align: left; padding: 13px 16px; border-bottom: 1px solid var(--line); vertical-align: top; }
th {
  font-weight: 500;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey);
  background: var(--surface-alt);
  white-space: nowrap;
}
tbody tr:hover { background: var(--surface-alt); }

/* --- Small utilities ---------------------------------------------------- */
.spec {
  font-family: var(--font-mono);
  font-size: var(--fs-tiny);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--teal-ink);
}
.dark-band .spec, .capabilities .spec { color: var(--teal-bright); }
.k { font-weight: 500; color: var(--ink); }
.t { color: var(--grey); }
.n {
  font-family: var(--font-display);
  font-weight: 500;
  color: var(--teal-ink);
  font-variant-numeric: tabular-nums;
}
.subhead {
  font-size: var(--fs-h4);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--ink);
}

/* ==========================================================================
   10 PAGE BLOCKS
   Legacy class names are kept so existing markup keeps working, but every
   one is restyled onto the new system.
   ========================================================================== */

/* --- Two-column feature (used across sectors, subsea, rentals, industry) -- */
.sec-block, .rental-feature, .lifecycle-feature, .ind-feature, .intro, .qa-block {
  padding: var(--band-y) 0;
}
.sec-block .wrap, .rental-feature .wrap, .lifecycle-feature .wrap,
.ind-feature .wrap, .intro .wrap {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(28px, 4.5vw, 72px);
  align-items: center;
}
.sec-block.flip .wrap, .rental-feature.img-right .wrap,
.lifecycle-feature.img-right .wrap, .ind-feature.img-right .wrap { direction: rtl; }
.sec-block.flip .wrap > *, .rental-feature.img-right .wrap > *,
.lifecycle-feature.img-right .wrap > *, .ind-feature.img-right .wrap > * { direction: ltr; }
@media (max-width: 860px) {
  .sec-block .wrap, .rental-feature .wrap, .lifecycle-feature .wrap,
  .ind-feature .wrap, .intro .wrap { grid-template-columns: 1fr; direction: ltr; }
}
.on-light { background: var(--surface); }
.on-light:nth-of-type(even) { background: var(--surface-alt); }
.on-dark { background: var(--anthracite-deep); color: #D7DCDF; }
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4 { color: #fff; }

.sec-copy h2, .rf-copy h2, .ind-feature h2, .lifecycle-feature h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
}
.sec-copy > p, .rf-copy > p { margin-top: 16px; color: var(--grey); }
.on-dark .sec-copy > p, .on-dark .rf-copy > p { color: #B9C1C6; }
.sec-copy .btn, .rf-copy .btn, .sec-copy .arrow, .rf-copy .arrow { margin-top: 24px; }
.sec-lead { font-size: clamp(1.0625rem, 1.4vw, 1.25rem); line-height: 1.55; color: var(--grey); }

.sec-photo, .lf-photo, .ind-photo, .cap-photo, .asked-img,
.tf-hero-img, .sub-hero-img, .product-photo {
  position: relative;
  overflow: hidden;
  background: var(--surface-sunk);
}
.sec-photo, .lf-photo { aspect-ratio: 16 / 11; }
.cap-photo, .tf-hero-img { aspect-ratio: 16 / 9; }
.sec-eyebrow-link:hover { color: var(--teal-ink); }

/* Corner registration marks on photography — a drawing-sheet convention that
   frames the image without a heavy border. */
.sec-photo::before, .lf-photo::before, .cap-photo::before {
  content: '';
  position: absolute;
  z-index: 2;
  top: 12px; left: 12px;
  width: 22px; height: 22px;
  border-top: 2px solid var(--teal);
  border-left: 2px solid var(--teal);
  opacity: 0.85;
}
.sec-photo::after, .lf-photo::after, .cap-photo::after {
  content: '';
  position: absolute;
  z-index: 2;
  bottom: 12px; right: 12px;
  width: 22px; height: 22px;
  border-bottom: 2px solid var(--teal);
  border-right: 2px solid var(--teal);
  opacity: 0.85;
}

/* --- Homepage capability band -------------------------------------------- */
.capabilities { padding: var(--band-y) 0; }
.cap-layout {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
@media (max-width: 1000px) { .cap-layout { grid-template-columns: 1fr; } }
.cap-copy h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  color: #fff;
}
.cap-copy p { margin-top: 16px; color: #B9C1C6; font-size: var(--fs-body-sm); }
.cap-copy .btn { margin-top: 26px; }

.cap-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 14px; }
@media (max-width: 1000px) { .cap-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .cap-grid { grid-template-columns: 1fr; } }
.cap-card {
  padding: 24px 20px 22px;
  display: flex;
  flex-direction: column;
  min-height: 232px;
  border-color: var(--line);
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
}
.cap-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); border-color: var(--teal); }
.cap-card.outline { border-color: var(--teal); }
.cap-card h3 { font-size: var(--fs-h4); text-transform: uppercase; letter-spacing: 0; margin-bottom: 10px; }
.cap-card p { font-size: var(--fs-tiny); color: var(--grey); line-height: 1.6; flex-grow: 1; }
.cap-card .arrow, .cap-card a { margin-top: 16px; font-size: var(--fs-tiny); }
/* The generic line icons were the most off-brand element on the site. They
   are replaced by a numbered hexagon from the mark's own geometry. */
.cap-icon {
  width: 34px; height: 39px;
  margin-bottom: 14px;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: rgba(0, 175, 134, 0.14);
  color: var(--teal-ink);
  display: grid;
  place-items: center;
  font-size: var(--fs-tiny);
  font-weight: 500;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.cap-card:hover .cap-icon { background: var(--teal); color: var(--black); }
.cap-icon svg { width: 18px; height: 18px; }

/* --- Sectors ------------------------------------------------------------- */
.sectors { padding: var(--band-y) 0; }
.sectors-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px; background: var(--line); border: 1px solid var(--line); }
@media (max-width: 860px) { .sectors-row { grid-template-columns: 1fr; } }
.sector-tile {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
  padding: clamp(26px, 3vw, 38px) clamp(22px, 2.4vw, 32px);
  background: var(--surface);
  position: relative;
  overflow: hidden;
  transition: background var(--dur-fast) var(--ease);
}
.sector-tile::before {
  content: '';
  position: absolute;
  left: 0; bottom: 0; right: 0;
  height: 3px;
  background: var(--teal);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--dur) var(--ease);
}
.sector-tile:hover { background: var(--surface-alt); }
.sector-tile:hover::before { transform: scaleX(1); }
.sector-left { display: flex; align-items: center; gap: 16px; }
.sector-num {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 500;
  color: var(--teal);
  opacity: 0.4;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
  transition: opacity var(--dur-fast) var(--ease);
}
.sector-tile:hover .sector-num { opacity: 1; }
.sector-name {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  text-transform: uppercase;
  color: var(--ink);
}
.sector-arrow { color: var(--teal-ink); opacity: 0; transform: translateX(-8px); transition: all var(--dur-fast) var(--ease); }
.sector-tile:hover .sector-arrow { opacity: 1; transform: translateX(0); }

/* --- Two ways ------------------------------------------------------------ */
.two-ways { padding: var(--band-y) 0; }
.tw-grid { display: grid; gap: clamp(20px, 2.4vw, 30px); }
.tw-card {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  overflow: hidden;
  min-height: 300px;
  border-color: var(--line);
}
.tw-card:hover { border-color: var(--teal); box-shadow: var(--shadow-lift); }
.tw-text { padding: clamp(26px, 3.2vw, 44px); display: flex; flex-direction: column; justify-content: center; }
.tw-text h3 { font-size: var(--fs-h3); text-transform: uppercase; }
.tw-text p { margin-top: 14px; font-size: var(--fs-body-sm); color: var(--grey); }
.tw-text .btn, .tw-text .arrow { margin-top: 24px; align-self: flex-start; }
/* The image is absolutely positioned so it fills the grid cell exactly. With
   height:100% in an auto-height grid cell it under-filled and left a strip of
   the container showing beneath. */
.tw-img { position: relative; overflow: hidden; min-height: 240px; }
.tw-img img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.9s var(--ease);
}
.tw-card:hover .tw-img img { transform: scale(1.04); }
@media (max-width: 860px) {
  .tw-card { grid-template-columns: 1fr; min-height: 0; }
  .tw-img { min-height: 220px; order: -1; }
}

/* --- Story / stats ------------------------------------------------------- */
.story { padding: var(--band-y) 0; }
.story-grid {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 72px);
  align-items: start;
}
@media (max-width: 860px) { .story-grid { grid-template-columns: 1fr; } }
.story-grid > div > p + p { margin-top: 1.1em; }
.stat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 480px) { .stat-grid { grid-template-columns: 1fr; } }
.stat-card {
  padding: 26px 22px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 3px solid var(--teal);
}
.stat-card h3, .stat-card h4 {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 2.4vw, 2.1rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.025em;
  color: var(--teal-ink);
  font-variant-numeric: tabular-nums;
}
.stat-card p {
  display: block;
  margin-top: 12px;
  font-size: var(--fs-tiny);
  color: var(--grey);
  line-height: 1.55;
}
.dark-band .stat-card, .on-dark .stat-card {
  background: rgba(255, 255, 255, 0.04);
  border-color: var(--line-dark);
  border-top-color: var(--teal);
}
.dark-band .stat-card h3, .dark-band .stat-card h4,
.on-dark .stat-card h3, .on-dark .stat-card h4 { color: var(--teal-bright); }
.dark-band .stat-card p, .on-dark .stat-card p { color: #AEB7BC; }
.story-logo { max-height: 90px; width: auto; }

/* --- About page blocks --------------------------------------------------- */
.intro-grid, .work-grid, .proven-grid, .award-grid, .assurance-grid {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 68px);
  align-items: center;
}
@media (max-width: 860px) {
  .intro-grid, .work-grid, .proven-grid, .award-grid, .assurance-grid { grid-template-columns: 1fr; }
}
.work-copy > p + p, .proven-copy > p + p { margin-top: 1.1em; }
.award-col > * + * { margin-top: 20px; }
.iso-item {
  padding: 20px 22px;
  border-left: 3px solid var(--teal);
  background: var(--surface-alt);
  border-top: 0; border-right: 0; border-bottom: 0;
}
.iso-item strong { display: block; margin-top: 6px; font-weight: 500; }
.cert-badge { max-width: 260px; }
.cert-badges { display: flex; gap: 16px; flex-wrap: wrap; align-items: center; margin-top: 26px; }
.cert-badges img {
  width: 29%; max-width: 112px; min-width: 74px;
  aspect-ratio: 1 / 1;
  background: #fff;
  border-radius: 50%;
  padding: 12px;
  object-fit: contain;
}

/* --- Capabilities page --------------------------------------------------- */
.cap-hero, .sec-hero, .tf-hero, .ind-hero, .sub-hero, .tr-head {
  position: relative;
  background: var(--anthracite-deep);
  color: #fff;
  padding: clamp(56px, 8vw, 104px) 0 clamp(40px, 5vw, 64px);
  overflow: hidden;
}
.cap-hero h1, .sec-hero h1, .tf-hero h1, .ind-hero h1, .sub-hero h1, .tr-head h1 {
  font-size: var(--fs-h1);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  color: #fff;
  max-width: 26ch;
}
.cap-lede, .tr-lede, .tf-hero-copy p:not(.tf-eyebrow) {
  margin-top: 20px;
  font-size: clamp(1.0625rem, 1.5vw, 1.25rem);
  line-height: 1.55;
  color: #C3CACE;
  max-width: 60ch;
}
.cap-head { padding-bottom: 0; }
.cap-body, .prose-section, .doc-body, .contract-section, .stages, .tf-problem, .tf-streams, .tf-handover, .faq, .vessel, .asked, .map-block {
  padding: var(--band-y) 0;
}
.cap-band { padding: var(--band-y) 0; background: var(--anthracite-deep); color: #D7DCDF; }
.cap-band h2, .cap-band h3 { color: #fff; }
.cut-layout {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
@media (max-width: 860px) { .cut-layout { grid-template-columns: 1fr; } }

/* --- Testing centre --------------------------------------------------- */
.tf-hero .wrap, .sub-hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
@media (max-width: 860px) { .tf-hero .wrap, .sub-hero .wrap { grid-template-columns: 1fr; } }
.tf-problem { background: var(--surface-alt); }
.s-head { display: block; font-size: var(--fs-h3); text-transform: uppercase; font-weight: 500; }
.s-abbr { color: var(--teal-ink); margin-bottom: 4px; }
.who {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 12px;
}
.full { display: block; }

/* --- Track record ------------------------------------------------------- */
.doc { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: clamp(32px, 4vw, 64px); }
/* minmax(0, 1fr), not 1fr. A bare 1fr track floors at the item's
   min-content width, and the widest table in .doc-body has a
   min-content width of 713px because its headers are nowrap. That made
   the single mobile column 713px wide inside a 350px container, so the
   whole document overflowed the viewport. */
@media (max-width: 900px) { .doc { grid-template-columns: minmax(0, 1fr); } }
.doc-nav { position: sticky; top: 104px; align-self: start; }
.doc-nav a {
  display: block;
  padding: 9px 0 9px 16px;
  border-left: 2px solid var(--line);
  font-size: var(--fs-tiny);
  color: var(--grey);
  transition: all var(--dur-fast) var(--ease);
}
.doc-nav a:hover, .doc-nav a.active { border-left-color: var(--teal); color: var(--teal-ink); }
@media (max-width: 900px) { .doc-nav { position: static; display: flex; flex-wrap: wrap; gap: 4px; }
  .doc-nav a { border-left: 0; border-bottom: 2px solid var(--line); padding: 8px 12px; } }
.doc-body > section + section { margin-top: var(--band-y-sm); padding-top: var(--band-y-sm); border-top: 1px solid var(--line); }
.contract-section { padding-top: 0; }
.contract-row { display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 20px; padding: 18px 0; border-bottom: 1px solid var(--line); }
@media (max-width: 640px) { .contract-row { grid-template-columns: 1fr; gap: 6px; } }
.contract-label { color: var(--teal-ink); }
.contract-desc { font-size: var(--fs-body-sm); color: var(--grey); }

/* --- Industry pages ----------------------------------------------------- */
.asked ul { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 32px; }
@media (max-width: 720px) { .asked ul { grid-template-columns: 1fr; } }

/* --- Map ---------------------------------------------------------------- */
.map-block { background: var(--anthracite-deep); color: #D7DCDF; }
.worked-map { width: 100%; }
.worked-map .base { fill: rgba(255, 255, 255, 0.09); }
.map-legend { display: flex; gap: 26px; flex-wrap: wrap; margin-top: 26px; font-size: var(--fs-tiny); color: #AEB7BC; }
.map-legend span { display: flex; align-items: center; gap: 9px; }
.map-legend i {
  width: 10px; height: 11px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* --- Hiring / FAQ ------------------------------------------------------- */
.hiring-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(18px, 2.4vw, 28px); }
@media (max-width: 860px) { .hiring-grid { grid-template-columns: 1fr; } }
.hiring-card { padding: clamp(24px, 3vw, 36px); border-top: 3px solid var(--teal); }
.hiring-card h3 { font-size: var(--fs-h3); text-transform: uppercase; margin-bottom: 14px; }
.hiring-card p { font-size: var(--fs-body-sm); color: var(--grey); }
.hiring-card p + p { margin-top: 0.9em; }
.faq-item { border: 0; border-bottom: 1px solid var(--line); }

/* ==========================================================================
   11 FOOTER
   ========================================================================== */

footer {
  background: var(--black);
  color: #8A9398;
  padding: clamp(44px, 5vw, 68px) 0 32px;
  position: relative;
  overflow: hidden;
}
.foot-grid {
  display: grid;
  grid-template-columns: minmax(0, 3fr) minmax(0, 5fr) minmax(0, 4fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
  padding-bottom: 34px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
@media (max-width: 860px) { .foot-grid { grid-template-columns: 1fr; } }
.foot-logo { height: 58px; width: auto; }
.foot-links { display: flex; flex-wrap: wrap; gap: 10px 28px; }
.foot-links a { font-size: var(--fs-small); color: #C3CACE; }
.foot-links a:hover { color: var(--teal-bright); }
.foot-addr { font-size: var(--fs-tiny); line-height: 1.7; color: #A2ABB0; }
footer .eyebrow { color: #98A1A6; margin-bottom: 14px; display: block; }
.foot-base {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding-top: 22px;
  font-size: var(--fs-tiny);
  color: #98A1A6;
}

/* ==========================================================================
   12 MOTION AND REVEAL
   Reveals are directional and content-linked: text rises, images are wiped
   open like a cut being made, rules draw out from the left. Uniform fade-up
   on everything is what made the first pass feel templated.
   ========================================================================== */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.62s var(--ease-out), transform 0.62s var(--ease-out);
}
[data-reveal].is-in { opacity: 1; transform: none; }

.js [data-reveal="wipe"] {
  opacity: 1;
  transform: none;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.95s var(--ease-out);
}
[data-reveal="wipe"].is-in { clip-path: inset(0 0 0 0); }

.js [data-reveal="stagger"] > * {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.55s var(--ease-out), transform 0.55s var(--ease-out);
}
[data-reveal="stagger"].is-in > * { opacity: 1; transform: none; }
[data-reveal="stagger"].is-in > *:nth-child(1) { transition-delay: 0.02s; }
[data-reveal="stagger"].is-in > *:nth-child(2) { transition-delay: 0.09s; }
[data-reveal="stagger"].is-in > *:nth-child(3) { transition-delay: 0.16s; }
[data-reveal="stagger"].is-in > *:nth-child(4) { transition-delay: 0.23s; }
[data-reveal="stagger"].is-in > *:nth-child(5) { transition-delay: 0.30s; }
[data-reveal="stagger"].is-in > *:nth-child(6) { transition-delay: 0.37s; }

/* Counter roll-up target */
.count { font-variant-numeric: tabular-nums; }

/* ==========================================================================
   13 REDUCED MOTION, PRINT, FORCED COLOURS
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
  }
  [data-reveal], [data-reveal="stagger"] > * { opacity: 1 !important; transform: none !important; }
  [data-reveal="wipe"] { clip-path: none !important; }
  .rule { transform: scaleX(1) !important; }
  .cut::after { width: 100% !important; }
  .logo-track { animation: none !important; }
  /* The ticker tracks are duplicated for the loop; stopping the animation
     without resetting the transform would park them mid-shift. */
  .spec-tape-track { animation: none !important; transform: none !important; }
  .ct-track { transform: none !important; }
  .scroll-cue i { animation: none !important; }
}

@media print {
  header, footer, .scroll-cue, .nav-toggle, .nav-scrim { display: none !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  [data-reveal="wipe"] { clip-path: none !important; }
  body { color: #000; background: #fff; font-size: 11pt; }
  .band--dark, .dark-band, .capabilities, .on-dark, .cta-band, .page-hero {
    background: #fff !important; color: #000 !important;
  }
  .band--dark h1, .band--dark h2, .dark-band h2, .on-dark h2, .capabilities h2 { color: #000 !important; }
  a[href^="http"]::after { content: ' (' attr(href) ')'; font-size: 9pt; color: #555; }
  section { break-inside: avoid; }
}

@media (forced-colors: active) {
  .cap-card, .card, .tw-card, .stat-card, .hiring-card { border: 1px solid CanvasText; }
  .btn { border: 1px solid CanvasText; }
  .lattice::before { display: none; }
}

/* ==========================================================================
   14 LATE ADDITIONS — blocks whose existing markup needed a bespoke fit
   ========================================================================== */

/* Track record: a row of project figures. Note .band here is a figure row,
   not a section band — the existing markup got there first. */
.band {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin: 32px 0;
}
.band--2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px) { .band { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .band, .band--2 { grid-template-columns: 1fr; } }
.band figure figcaption {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--grey);
}

/* Track record: campaign figures as a measured key/value list. */
.metrics {
  display: grid;
  gap: 0;
  margin: 28px 0;
  border-top: 1px solid var(--line);
}
.metrics li {
  display: grid;
  grid-template-columns: 170px minmax(0, 1fr);
  gap: 20px;
  align-items: baseline;
  padding: 14px 0;
  border-bottom: 1px solid var(--line);
}
.metrics .n {
  font-size: clamp(1.1rem, 1.8vw, 1.45rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.metrics .k { font-weight: 400; color: var(--grey); font-size: var(--fs-body-sm); }
@media (max-width: 560px) {
  .metrics li { grid-template-columns: 1fr; gap: 4px; }
}

/* World map: home base and worked territories. */
.worked-map .home { fill: var(--teal); }
.worked-map .scope { fill: rgba(0, 175, 134, 0.55); }

/* Light photo placeholder on a light band. */
.ind-photo.light, .photo-ph.light {
  background:
    repeating-linear-gradient(45deg,
      rgba(19, 22, 25, 0.035) 0 8px,
      rgba(19, 22, 25, 0.07) 8px 16px);
  border-color: var(--line);
  color: var(--grey);
}

/* Header compaction once the hero is behind you. */
header[data-scrolled="true"] { background: rgba(19, 22, 25, 0.94); }
header[data-scrolled="true"] nav { padding: 5px 0; }
header[data-scrolled="true"] .logo-lockup { height: 42px; }
header nav, header .logo-lockup { transition: padding var(--dur-fast) var(--ease), height var(--dur-fast) var(--ease); }

/* --- Sector pictograms ---------------------------------------------------- */
/* The three marks on the deck's cover slide: offshore structure, mine
   headframe, transmission tower. They give the sector row a reason to exist
   as a graphic rather than three identical text rows. */
.sector-ico {
  width: 42px; height: 42px;
  flex: 0 0 auto;
  color: var(--teal);
  opacity: 0.55;
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur) var(--ease);
}
.sector-tile:hover .sector-ico { opacity: 1; transform: translateY(-2px); }
.sector-left > span:last-child { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }

/* --- Hex tiles as links -------------------------------------------------- */
a.hextile { display: block; color: inherit; }
a.hextile h3 { color: #fff; transition: color var(--dur-fast) var(--ease); }
a.hextile:hover h3 { color: var(--teal-bright); }
a.hextile .arrow { pointer-events: none; }

/* Section heading inside a dark capability band */
.capabilities .rule-head h2 { color: #fff; }
.capabilities .cap-copy .btn { margin-top: 26px; }
.cap-copy.rule-head { margin-bottom: 0; }

/* Generic section headings that have no rule-head wrapper yet */
.two-ways > .wrap > h2, .sectors > .wrap > h2, .story h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
}

/* --- Sector tile layout -------------------------------------------------- */
/* Number as a label above the sector name, pictogram on the right, so the
   three tiles stay on one line each at every width. */
.sector-tile { align-items: center; }
.sector-left { align-items: center; gap: 18px; flex: 1 1 auto; min-width: 0; }
.sector-left > span:last-child { flex-direction: column; align-items: flex-start; gap: 4px; }
.sector-num {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  opacity: 1;
  color: var(--grey);
}
.sector-tile:hover .sector-num { color: var(--teal-ink); }
.sector-name { font-size: 1.15rem; line-height: 1.15; }
.sector-ico { order: 2; width: 38px; height: 38px; }
.sector-tile > .sector-arrow { display: none; }

/* --- Fleet capability chart ---------------------------------------------- */
/* Slide 8 of the capability deck plots the diamond wire saw fleet by cut
   size. On the web that becomes a real size chart on a logarithmic axis:
   an operator with a 36 inch tubular can see which saws cover it without
   reading seven cards. The axis is logarithmic because the fleet spans
   8 inches to nine metres and a linear axis would bunch six of the seven
   saws into the first fifth of the scale. */
.range-chart {
  margin: 8px 0 0;
  border-top: 1px solid var(--line-dark);
}
.range-axis {
  position: relative;
  height: 30px;
  grid-column: 2;
  border-bottom: 1px solid var(--line-dark);
}
.range-head {
  display: grid;
  grid-template-columns: var(--rc-label, 132px) minmax(0, 1fr) var(--rc-val, 96px);
}
.range-axis span {
  position: absolute;
  top: 9px;
  transform: translateX(-50%);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.09em;
  color: var(--grey-light);
  white-space: nowrap;
}
.range-axis span::after {
  content: '';
  position: absolute;
  left: 50%; bottom: -9px;
  width: 1px; height: 7px;
  background: rgba(255, 255, 255, 0.28);
}
.range-row {
  display: grid;
  grid-template-columns: var(--rc-label, 132px) minmax(0, 1fr) var(--rc-val, 96px);
  align-items: center;
  gap: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  transition: background var(--dur-fast) var(--ease);
}
.range-row:hover { background: rgba(255, 255, 255, 0.04); }
.range-name {
  padding: 13px 16px 13px 0;
  font-size: var(--fs-tiny);
  font-weight: 500;
  color: #fff;
  letter-spacing: 0.04em;
}
.range-track { position: relative; height: 46px; }
/* Faint vertical grid, aligned to the axis ticks. One gradient per tick so
   the image and position lists stay in step. */
.range-track::before {
  content: '';
  position: absolute; inset: 0;
  pointer-events: none;
  --gl: linear-gradient(90deg, rgba(255,255,255,0.08) 0 1px, transparent 1px);
  background-image: var(--gl), var(--gl), var(--gl), var(--gl), var(--gl), var(--gl), var(--gl);
  background-size: 1px 100%;
  background-repeat: no-repeat;
  background-position:
    3.34% 0, 17.35% 0, 36.43% 0, 52.06% 0, 60.99% 0, 77.55% 0, 98.23% 0;
}
.range-bar {
  position: absolute;
  top: 50%;
  transform: translateY(-50%) scaleX(0);
  transform-origin: left center;
  height: 12px;
  background: linear-gradient(90deg, var(--teal), rgba(0, 175, 134, 0.45));
  clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 50%, calc(100% - 5px) 100%, 0 100%);
  transition: transform 0.85s var(--ease-out);
}
.is-in .range-bar { transform: translateY(-50%) scaleX(1); }
.range-row:nth-child(2) .range-bar { transition-delay: 0.05s; }
.range-row:nth-child(3) .range-bar { transition-delay: 0.10s; }
.range-row:nth-child(4) .range-bar { transition-delay: 0.15s; }
.range-row:nth-child(5) .range-bar { transition-delay: 0.20s; }
.range-row:nth-child(6) .range-bar { transition-delay: 0.25s; }
.range-row:nth-child(7) .range-bar { transition-delay: 0.30s; }
.range-row:nth-child(8) .range-bar { transition-delay: 0.35s; }
/* Values live in their own grid column so a bar reaching the top of the
   scale can never push a label outside the viewport. */
.range-val {
  padding-left: 14px;
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.08em;
  color: var(--teal-bright);
  white-space: nowrap;
  text-align: left;
}
/* The last axis label sits on the boundary, so pull it inside. */
.range-axis span:last-child { transform: translateX(-70%); }
.range-note {
  margin-top: 18px;
  font-size: var(--fs-tiny);
  color: #A6AFB4;
  display: flex;
  gap: 12px;
}
.range-note b { color: var(--teal-bright); font-weight: 500; letter-spacing: 0.09em;
  text-transform: uppercase; font-size: var(--fs-eyebrow); flex: 0 0 auto; padding-top: 2px; }
@media (max-width: 760px) {
  .range-chart { --rc-label: 92px; --rc-val: 0px; }
  .range-val { display: none; }
  .range-name { font-size: var(--fs-eyebrow); padding-right: 10px; }
  .range-axis span { font-size: 9px; letter-spacing: 0.04em; }
}

/* --- Dark-band inheritance guards ---------------------------------------- */
/* A white card sitting on a dark band must not inherit the band's white
   heading colour, or its title disappears. This bit the DWS product cards. */
.capabilities .cap-card h1, .capabilities .cap-card h2, .capabilities .cap-card h3,
.capabilities .cap-card h4,
.dark-band .cap-card h3, .dark-band .cap-card h4,
.band--dark .card h3, .band--dark .card h4,
.on-dark .cap-card h3, .on-dark .cap-card h4,
.capabilities .hiring-card h3, .dark-band .hiring-card h3,
.capabilities .faq-item h3, .dark-band .faq-item h3 { color: var(--ink); }
.capabilities .cap-card p, .dark-band .cap-card p { color: var(--grey); }
.capabilities .cap-card .spec, .dark-band .cap-card .spec { color: var(--teal-ink); }

/* Interior hero ledes sit on dark grounds and need the light treatment even
   though those sections predate the .on-dark convention. */
.sub-hero .lede, .cap-hero .lede, .sec-hero .lede, .tf-hero .lede,
.ind-hero .lede, .tr-head .lede, .page-hero .lede,
.sub-hero p, .cap-hero p:not(.eyebrow):not(.cap-eyebrow),
.sec-hero p:not(.eyebrow):not(.sec-eyebrow), .tr-head p:not(.eyebrow):not(.tr-eyebrow) { color: #C3CACE; }
.sub-hero .eyebrow, .cap-hero .eyebrow, .sec-hero .eyebrow,
.tf-hero .eyebrow, .ind-hero .eyebrow, .tr-head .eyebrow { color: var(--teal-bright); }
.sub-hero h1, .sub-hero h2 { color: #fff; }
.sub-hero { padding-bottom: clamp(48px, 6vw, 80px); }

/* --- Numbered process accordions ----------------------------------------- */
/* The six delivery stages are the deck's capability wheel read as a sequence.
   Each carries its stage number in the brand hexagon. */
.acc > summary { gap: 18px; align-items: center; }
.acc-num {
  flex: 0 0 auto;
  width: 38px; height: 44px;
  display: grid;
  place-items: center;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: rgba(0, 175, 134, 0.14);
  color: var(--teal-ink);
  font-size: var(--fs-tiny);
  font-weight: 500;
  letter-spacing: 0.02em;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.acc-title { flex: 1 1 auto; }
.acc > summary:hover .acc-num,
.acc[open] > summary .acc-num { background: var(--teal); color: var(--black); }
.dark-band .acc-num, .capabilities .acc-num, .on-dark .acc-num {
  background: rgba(0, 175, 134, 0.24); color: var(--teal-bright);
}
.acc-body { padding-left: 56px; }
@media (max-width: 640px) {
  .acc-num { width: 30px; height: 35px; }
  .acc-body { padding-left: 0; }
}

/* --- Section headings without a rule-head wrapper ------------------------ */
/* Interior pages carry plain <h2> straight inside .wrap. Rather than rewrite
   every one, they inherit the display scale and a measured rule. */
.prose-section > .wrap > h2, .stages > .wrap > h2, .cap-body > .wrap > h2,
.tf-problem > .wrap > h2, .tf-streams > .wrap > h2, .tf-handover > .wrap > h2, .faq > .wrap > h2,
.vessel > .wrap > h2, .asked > .wrap > h2, .map-block > .wrap > h2,
.qa-block > .wrap > h2, .contract-section > .wrap > h2, .doc-body > section > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 20px;
  position: relative;
  max-width: 44ch;
}
.prose-section > .wrap > h2::after, .stages > .wrap > h2::after,
.cap-body > .wrap > h2::after, .tf-problem > .wrap > h2::after,
.tf-streams > .wrap > h2::after, .tf-handover > .wrap > h2::after, .faq > .wrap > h2::after,
.vessel > .wrap > h2::after, .asked > .wrap > h2::after,
.map-block > .wrap > h2::after, .qa-block > .wrap > h2::after,
.contract-section > .wrap > h2::after, .doc-body > section > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.prose-section > .wrap > p { max-width: 72ch; }
.prose-section > .wrap > p + p { margin-top: 1.1em; }

/* --- Blanket section heading scale --------------------------------------- */
/* Interior pages carry bare <h2> in a variety of wrappers. A single blanket
   rule guarantees no heading anywhere on the site is left at browser default,
   which is what made the first pass read as unfinished in places. */
main section h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
}
main section h4 {
  font-size: var(--fs-h4);
  font-weight: 500;
  letter-spacing: 0.01em;
}

/* Capability page hero: two columns, copy left, plate right */
.cap-hero .wrap, .ind-hero .wrap, .tr-head .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.tr-head .wrap, .ind-hero .wrap { grid-template-columns: 1fr; }
@media (max-width: 860px) { .cap-hero .wrap { grid-template-columns: 1fr; } }

/* About: story Q&A */
.qa-block { padding: 22px 0; border-bottom: 1px solid var(--line); }
.qa-block h4 { margin-bottom: 10px; }
.qa-block:first-of-type { border-top: 1px solid var(--line); }
.story-logo { display: grid; place-items: center; padding: 32px; background: var(--surface-alt); }
.story-logo img { max-height: 120px; width: auto; filter: invert(1) brightness(0.35) saturate(0); }

/* --- Capability sub-page hero -------------------------------------------- */
.cap-head {
  position: relative;
  overflow: hidden;
  background: var(--anthracite-deep);
  color: #fff;
  padding: clamp(52px, 7vw, 92px) 0 clamp(40px, 5vw, 62px);
}
.cap-head h1 {
  font-size: var(--fs-h1);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  color: #fff;
  max-width: 26ch;
  margin-top: 14px;
}
.cap-head .cap-eyebrow { color: var(--teal-bright); }
.cap-head .cap-lede { color: #C3CACE; }

/* Hex bullets for prose lists on interior pages */
.cap-body ul:not(.metrics):not(.benefits) li, .prose-section ul:not(.metrics):not(.benefits) li,
.asked ul:not(.metrics):not(.benefits) li, .vessel ul:not(.metrics):not(.benefits) li,
.doc-body ul:not(.metrics):not(.benefits) li, .rf-copy ul:not(.metrics):not(.benefits) li,
.sec-copy ul:not(.metrics):not(.benefits) li, .hiring-card ul:not(.metrics):not(.benefits) li,
.acc-body ul:not(.metrics):not(.benefits) li, .ind-feature ul:not(.metrics):not(.benefits) li {
  position: relative;
  padding-left: 26px;
  margin-top: 0.6em;
  max-width: 66ch;
}
.cap-body ul:not(.metrics):not(.benefits) li::before, .prose-section ul:not(.metrics):not(.benefits) li::before,
.asked ul:not(.metrics):not(.benefits) li::before, .vessel ul:not(.metrics):not(.benefits) li::before,
.doc-body ul:not(.metrics):not(.benefits) li::before, .rf-copy ul:not(.metrics):not(.benefits) li::before,
.sec-copy ul:not(.metrics):not(.benefits) li::before, .hiring-card ul:not(.metrics):not(.benefits) li::before,
.acc-body ul:not(.metrics):not(.benefits) li::before, .ind-feature ul:not(.metrics):not(.benefits) li::before {
  content: '';
  position: absolute;
  left: 2px; top: 0.62em;
  width: 9px; height: 10px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.on-dark ul:not(.metrics):not(.benefits) li::before, .dark-band ul:not(.metrics):not(.benefits) li::before, .capabilities ul:not(.metrics):not(.benefits) li::before {
  background: var(--teal-bright);
}
.cap-body ul, .prose-section ul { margin: 18px 0 26px; }
.cap-body > .wrap > p + p, .cap-body > .wrap > p { max-width: 72ch; }
.cap-body > .wrap > p + p { margin-top: 1.1em; }
.cap-body > .wrap > h2 { margin-top: 2.4em; }
.cap-body > .wrap > h2:first-of-type { margin-top: 0; }

/* Photo placeholders that live on sector and industry blocks */
.sec-photo.light, .sec-photo.dark, .ind-photo.light, .ind-photo.dark,
.cap-photo.light, .cap-photo.dark {
  display: grid;
  place-items: center;
  text-align: center;
  padding: 24px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  line-height: 1.7;
  background:
    repeating-linear-gradient(45deg,
      rgba(0, 175, 134, 0.05) 0 8px,
      rgba(0, 175, 134, 0.11) 8px 16px);
  border: 1px dashed var(--line-teal);
  color: var(--grey);
}
.sec-photo.dark, .ind-photo.dark, .cap-photo.dark {
  background:
    repeating-linear-gradient(45deg,
      rgba(255, 255, 255, 0.04) 0 8px,
      rgba(255, 255, 255, 0.085) 8px 16px);
  border-color: rgba(255, 255, 255, 0.22);
  color: var(--grey-light);
}
/* A placeholder must not draw the drawing-sheet registration marks — those
   belong to real photography only. */
.sec-photo.light::before, .sec-photo.light::after,
.sec-photo.dark::before, .sec-photo.dark::after,
.cap-photo.light::before, .cap-photo.light::after,
.cap-photo.dark::before, .cap-photo.dark::after { content: none; }

.media--21-9 { aspect-ratio: 21 / 9; }

/* Capability sub-pages are documents, so their body column takes a reading
   measure rather than the full grid, which left the right half of the page
   empty and made a finished page look unfinished. */
.cap-body > .wrap, .prose-section > .wrap { max-width: 880px; }
.cap-body > .wrap > h2, .prose-section > .wrap > h2 { max-width: 100%; }

/* Annotated figures sit on light bands too */
.figure { position: relative; }
.rental-feature .figure, .sec-block .figure { margin: 0; }
.on-light .figure-note b { background: rgba(19, 22, 25, 0.9); }

/* ==========================================================================
   15 CONTRAST GUARDS ON DARK GROUNDS
   The legacy eyebrow classes are page-specific names rather than variants of
   .eyebrow, so they did not pick up the on-dark colour and rendered mid-grey
   on anthracite. Named explicitly here rather than relying on inheritance.
   ========================================================================== */

.ind-hero .ind-eyebrow, .tr-head .tr-eyebrow, .sub-hero .sub-eyebrow,
.cap-head .cap-eyebrow, .sec-hero .sec-eyebrow, .tf-hero .tf-eyebrow,
.cap-hero .cap-eyebrow, .page-hero .eyebrow,
.map-block .home-tag, .map-block .scope-tag,
.on-dark .home-tag, .on-dark .scope-tag,
.capabilities .eyebrow, .capabilities .eyebrow--teal,
.sub-hero .eyebrow--teal, .cap-band .eyebrow, .cap-band .eyebrow--teal {
  color: var(--teal-bright);
}
.ind-hero .crumb, .tr-head .crumb, .sub-hero .crumb, .cap-head .crumb,
.cap-hero .crumb, .page-hero .crumb {
  color: rgba(255, 255, 255, 0.68);
}
.map-legend { color: #C3CACE; }

/* The amber editorial flag has a light-ground and a dark-ground variant. The
   dark variant needs to cover .cap-band too, which is a dark section on the
   capability sub-pages. */
.cap-band .insert-note, .cap-band .cap-note, .cap-band .flag,
.map-block .insert-note, .map-block .cap-note {
  color: #F2DCA6;
  background: rgba(224, 163, 46, 0.14);
}
.cap-band .insert-note strong, .cap-band .cap-note strong { color: #F7E9C4; }

/* Deliberately-blank sections on the industry pages read as an open item, not
   as low-contrast body copy. */
.ind-feature h2:has(+ .insert-note),
h2.to-come {
  color: #E0A32E;
}
/* `.ind-feature.on-dark h2` had no `.to-come` qualifier, so every heading on a
   dark industry band rendered in the amber editorial-flag colour, real copy
   included. Scoped to placeholder headings only. */
.on-dark h2.to-come,
.ind-feature.on-dark h2.to-come,
.ind-feature.on-dark h2:has(+ .insert-note) { color: #E8BC63; }

/* Skip link inherits the button treatment */
.skip-link { color: var(--black); }

/* --- Tiles on dark bands ------------------------------------------------- */
/* A light tile dropped onto a dark band inherits the band's light text and
   disappears. Tiles that live on dark grounds become translucent white with
   light text instead of solid light with dark text. */
.dark-band .iso-item, .on-dark .iso-item, .capabilities .iso-item,
.cap-band .iso-item, .proven-grid .iso-item {
  background: rgba(255, 255, 255, 0.06);
  border-left-color: var(--teal);
  color: #C3CACE;
}
.dark-band .iso-item p, .on-dark .iso-item p, .capabilities .iso-item p,
.cap-band .iso-item p, .proven-grid .iso-item p { color: #C3CACE; }
.dark-band .iso-item .iso-code, .on-dark .iso-item .iso-code,
.capabilities .iso-item .iso-code, .cap-band .iso-item .iso-code,
.proven-grid .iso-item .iso-code { color: var(--teal-bright); }

/* --- Deliberately-blank sections ---------------------------------------- */
/* mining.html and energy.html carry sections the client left empty on
   purpose. They now read as an open item rather than as faint body copy. */
h2.to-come {
  color: #E8BC63 !important;
  position: relative;
  padding-left: 22px;
}
h2.to-come::before {
  content: '';
  position: absolute;
  left: 0; top: 0.34em;
  width: 11px; height: 12px;
  background: #E0A32E;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* Placeholder captions inside photo placeholders */
.photo-ph span, .ph span, .sec-photo span, .ind-photo span, .cap-photo span {
  display: block;
  margin-top: 6px;
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.09em;
  color: var(--grey);
}
.sec-photo.dark span, .ind-photo.dark span, .cap-photo.dark span,
.photo-ph.dark span { color: var(--grey-light); }

/* ==========================================================================
   16 PLACEHOLDERS — CONTEXT INDEPENDENT
   The .light / .dark placeholder modifiers described the intended tile, not
   the band it sits on, so a "light" tile could land on a dark section and
   inherit unreadable text. Placeholders now carry their own opaque ground and
   fixed text colour, so they read the same wherever they are dropped.
   ========================================================================== */

.photo-ph, .ph,
.sec-photo.light, .sec-photo.dark,
.ind-photo.light, .ind-photo.dark,
.cap-photo.light, .cap-photo.dark {
  background-color: #EFF2F2;
  background-image:
    repeating-linear-gradient(45deg,
      rgba(0, 121, 90, 0.045) 0 10px,
      rgba(0, 121, 90, 0.095) 10px 20px);
  border: 1px dashed rgba(0, 121, 90, 0.32);
  color: #4A5459;
}
.photo-ph span, .ph span,
.sec-photo.light span, .sec-photo.dark span,
.ind-photo.light span, .ind-photo.dark span,
.cap-photo.light span, .cap-photo.dark span,
.photo-ph br + span, .ph br + span {
  color: #4A5459;
}
/* A real photograph wrapped in a placeholder container keeps no placeholder
   styling — those wrappers carry an inline background reset already. */
.photo-ph:has(img), .ph:has(img), .sec-photo:has(img), .cap-photo:has(img) {
  background: none;
  border: 0;
  color: inherit;
}

/* The deliberately-blank industry sections: amber that works on light grounds */
h2.to-come { color: #8A5D00 !important; }
.on-dark h2.to-come, .dark-band h2.to-come, .capabilities h2.to-come,
.cap-band h2.to-come { color: #E8BC63 !important; }

/* ==========================================================================
   17 EQUIPMENT CATALOGUE — THE DRIFTING WALL
   Blakemere's differentiator is the volume and variety of bespoke tooling, so
   the catalogue itself becomes the visual. Three rows of drawing title-block
   tiles drift at different speeds on a plane tilted in 3D, which reads as
   depth and breadth before a word is read.

   Deliberately CSS-only: no WebGL, no library. Only the three .ct-track
   elements are animated, so the browser composites three layers rather than
   132 tiles, and the whole thing stays hand-editable.
   ========================================================================== */

.catalogue {
  position: relative;
  overflow: hidden;
  background: var(--black);
  color: #D7DCDF;
  padding: var(--band-y) 0 0;
}
.catalogue .rule-head h2 { color: #fff; }
.catalogue .rule-head p { color: #B9C1C6; }

/* --- Filter chips -------------------------------------------------------- */
.ct-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 26px 0 8px;
}
.ct-chip {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #C3CACE;
  padding: 9px 15px;
  border: 1px solid rgba(255, 255, 255, 0.18);
  background: rgba(255, 255, 255, 0.03);
  clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
  transition: border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.ct-chip:hover { color: #fff; border-color: var(--line-teal); }
.ct-chip[aria-pressed="true"] {
  background: var(--teal);
  border-color: var(--teal);
  color: var(--black);
}
.ct-count {
  margin-left: auto;
  align-self: center;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--grey-light);
}
@media (max-width: 700px) { .ct-count { margin-left: 0; width: 100%; } }

/* --- The stage ----------------------------------------------------------- */
.ct-stage {
  position: relative;
  margin-top: 34px;
  padding-bottom: clamp(48px, 6vw, 84px);
  perspective: none;
  /* Fade at all four edges so the wall reads as a fragment of something
     larger rather than a component that stops. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent),
    linear-gradient(180deg, transparent, #000 18%, #000 84%, transparent);
          mask-image:
    linear-gradient(90deg, transparent, #000 11%, #000 89%, transparent),
    linear-gradient(180deg, transparent, #000 18%, #000 84%, transparent);
  -webkit-mask-composite: source-in;
          mask-composite: intersect;
}
.ct-plane {
  /* Rev 3.5: the tilted plane and the opposing drifts read as chaotic.
     Flat, one direction, one speed family. */
  transform: none;
  display: grid;
  gap: clamp(12px, 1.4vw, 20px);
}

/* --- Rows: different speeds and depths give the parallax ----------------- */
.ct-row { overflow: hidden; }
/* Depth reads as a size difference between the rows rather than as dimming,
   because the tiles hold real text and must stay legible.

   That used to be done with translateZ inside the perspective. It looked
   right and could not be clicked: a row pushed back in Z paints where you
   see it but hit-tests against its unprojected position, so a click landed
   on the plane behind the tile. Only row three, the one at zero depth,
   responded. These are the same sizes expressed as a plain scale, worked out
   against the 1500px perspective: 1500 / (1500 + depth). */
.ct-row[data-row="1"] { opacity: 0.88; }
.ct-row[data-row="2"] { opacity: 0.94; }
.ct-row[data-row="3"] { opacity: 1; }
.ct-row[data-row="4"] { opacity: 0.94; }
.ct-row[data-row="5"] { opacity: 0.88; }

.ct-track {
  display: flex;
  gap: clamp(12px, 1.4vw, 20px);
  width: max-content;
  will-change: transform;
}
.ct-dup { display: flex; gap: inherit; }
.ct-row[data-row="1"] .ct-track { animation: ct-drift-l 132s linear infinite; }
.ct-row[data-row="2"] .ct-track { animation: ct-drift-l 144s linear infinite; }
.ct-row[data-row="3"] .ct-track { animation: ct-drift-l 122s linear infinite; }
.ct-row[data-row="4"] .ct-track { animation: ct-drift-l 154s linear infinite; }
.ct-row[data-row="5"] .ct-track { animation: ct-drift-l 166s linear infinite; }
.ct-stage:hover .ct-track { animation-play-state: paused; }

@keyframes ct-drift-l { from { transform: translateX(0); }      to { transform: translateX(-50%); } }
@keyframes ct-drift-r { from { transform: translateX(-50%); }   to { transform: translateX(0); } }

/* --- The tile: a drawing title block ------------------------------------- */
.ct-tile {
  flex: 0 0 auto;
  width: clamp(176px, 15vw, 214px);
  padding: 15px 16px 13px;
  display: grid;
  grid-template-rows: auto 1fr auto auto;
  gap: 6px;
  background: rgba(255, 255, 255, 0.045);
  border: 1px solid rgba(255, 255, 255, 0.13);
  clip-path: polygon(0 0, calc(100% - 11px) 0, 100% 11px, 100% 100%, 0 100%);
  transition: background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              opacity var(--dur) var(--ease);
}
.ct-tile:hover { background: rgba(0, 175, 134, 0.16); border-color: var(--teal); }
.ct-ref {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.13em;
  color: var(--teal-bright);
  line-height: 1.2;
}
.ct-name {
  font-size: var(--fs-tiny);
  font-weight: 500;
  line-height: 1.28;
  color: #fff;
}
.ct-spec { font-size: 11px; line-height: 1.4; color: #A2ABB0; }
.ct-spec--none { color: #7F888D; font-style: normal; }
.ct-cat {
  margin-top: 2px;
  padding-top: 7px;
  border-top: 1px solid rgba(255, 255, 255, 0.11);
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #8F989D;
}

/* --- Search ---------------------------------------------------------------- */
.ct-search { margin-left: auto; align-self: center; }
.ct-search + .ct-count { margin-left: 14px; }
.ct-search input {
  width: clamp(200px, 22vw, 280px);
  padding: 9px 14px;
  font: inherit;
  font-size: var(--fs-tiny);
  color: #fff;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: 0;
  transition: border-color var(--dur-fast) var(--ease);
}
.ct-search input::placeholder { color: #8F989D; }
.ct-search input:hover { border-color: var(--line-teal); }
.ct-search input:focus-visible { outline: 2px solid var(--teal-bright); outline-offset: 2px; border-color: var(--teal); }
@media (max-width: 700px) {
  .ct-search { margin-left: 0; width: 100%; }
  .ct-search input { width: 100%; }
  .ct-search + .ct-count { margin-left: 0; }
}

/* --- Filtered or searched: a static grid of matches ------------------------
   The rows and tracks dissolve with display: contents so every match, from
   whichever row, flows into one grid aligned to the page wrap. The loop
   copies go, and so does the edge fade, which would otherwise swallow the
   outer columns. */
.ct-stage[data-mode="static"] {
  -webkit-mask-image: none; mask-image: none;
  max-width: var(--wrap);
  margin-left: auto; margin-right: auto;
  padding-left: var(--gut); padding-right: var(--gut);
}
.ct-stage[data-mode="static"] .ct-plane {
  grid-template-columns: repeat(auto-fill, minmax(176px, 1fr));
}
/* site.js swaps the layout while the plane is faded out. */
.ct-plane { transition: opacity 180ms var(--ease); }
.ct-plane.is-fading { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .ct-plane { transition: none; } }
@media (max-width: 640px) {
  .ct-stage[data-mode="static"] .ct-plane { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ct-stage[data-mode="static"] .ct-row,
.ct-stage[data-mode="static"] .ct-track { display: contents; }
.ct-stage[data-mode="static"] .ct-dup,
.ct-stage[data-mode="static"] .ct-tile.is-out { display: none; }
.ct-stage[data-mode="static"] .ct-tile { width: auto; opacity: 1; }
.ct-empty {
  max-width: 60ch;
  font-size: var(--fs-body-sm);
  color: #B6BEC2;
}

/* --- Narrow screens: drop the 3D tilt, keep the drift -------------------- */
@media (max-width: 900px) {
  .ct-plane { transform: none; }
  .ct-row { transform: none !important; opacity: 0.94 !important; }
  .ct-row[data-row="3"] { opacity: 1 !important; }
  .ct-stage { perspective: none; }
  /* Four rows is plenty on a phone; the fifth is redundant weight. */
  .ct-row[data-row="5"] { display: none; }
}

/* --- Reduced motion: a static, honest grid ------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .ct-stage {
    perspective: none;
    -webkit-mask-image: none; mask-image: none;
    overflow: visible;
  }
  .ct-plane { transform: none; }
  .ct-row { overflow: visible; transform: none !important; opacity: 1 !important; }
  .ct-track {
    animation: none !important;
    flex-wrap: wrap;
    width: 100%;
  }
  .ct-dup { display: none; }
  .ct-tile { width: clamp(150px, 22vw, 210px); }
}

/* Catalogue closing line — ties the wall to an action rather than stopping */
.ct-foot {
  display: flex;
  align-items: baseline;
  gap: 18px 28px;
  flex-wrap: wrap;
  padding-bottom: var(--band-y-sm);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-top: 26px;
}
.ct-foot p { color: #C3CACE; font-size: var(--fs-body); margin: 0; }

/* ==========================================================================
   18 BLUEPRINT WIREFRAME
   From the technical-brutalism reference: explicit hairlines and corner ticks
   so a block reads as a drawing sheet rather than a card. Chamfers are kept
   instead of the reference's rounded corners, because the cut corner is
   already this site's own language.
   ========================================================================== */

.blueprint {
  position: relative;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background:
    linear-gradient(90deg, rgba(255,255,255,0.022) 1px, transparent 1px) 0 0 / 48px 48px,
    linear-gradient(180deg, rgba(255,255,255,0.022) 1px, transparent 1px) 0 0 / 48px 48px,
    rgba(255, 255, 255, 0.02);
  padding: clamp(22px, 3vw, 40px);
}
/* Corner registration ticks, all four */
.blueprint::before, .blueprint::after {
  content: '';
  position: absolute;
  width: 14px; height: 14px;
  pointer-events: none;
}
.blueprint::before {
  top: -1px; left: -1px;
  border-top: 2px solid var(--teal);
  border-left: 2px solid var(--teal);
}
.blueprint::after {
  bottom: -1px; right: -1px;
  border-bottom: 2px solid var(--teal);
  border-right: 2px solid var(--teal);
}
.blueprint--light {
  border-color: var(--line);
  background:
    linear-gradient(90deg, rgba(19,22,25,0.03) 1px, transparent 1px) 0 0 / 48px 48px,
    linear-gradient(180deg, rgba(19,22,25,0.03) 1px, transparent 1px) 0 0 / 48px 48px,
    var(--surface);
}

/* ==========================================================================
   19 CURSOR-TRACKED GLOW
   From the modern dev-tool reference. A radial highlight follows the pointer
   across a card surface. Pointer position arrives as --mx / --my from
   site.js; everything else is CSS, and it is inert on touch devices.
   ========================================================================== */

.cap-card, .tw-card, .stat-card, .hextile, .ct-tile, .hiring-card,
.sector-tile, .bento-cell, .onward > a { position: relative; }

.cap-card::after, .tw-card::after, .stat-card::after, .hextile::after,
.ct-tile::after, .hiring-card::after, .sector-tile::after,
.bento-cell::after, .onward > a::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--dur) var(--ease);
  background: radial-gradient(
    360px circle at var(--mx, 50%) var(--my, 50%),
    rgba(0, 175, 134, 0.16),
    transparent 62%);
}
.cap-card:hover::after, .tw-card:hover::after, .stat-card:hover::after,
.hextile:hover::after, .ct-tile:hover::after, .hiring-card:hover::after,
.sector-tile:hover::after, .bento-cell:hover::after, .onward > a:hover::after {
  opacity: 1;
}
@media (hover: none) {
  .cap-card::after, .tw-card::after, .stat-card::after, .hextile::after,
  .ct-tile::after, .hiring-card::after, .sector-tile::after,
  .bento-cell::after, .onward > a::after { display: none; }
}
/* The sector tile already uses ::before for its underline, so keep the two
   from fighting over stacking order. */
.sector-tile > * { position: relative; z-index: 1; }

/* ==========================================================================
   20 SPEC TAPE
   An infinite ticker of hard figures. Same technique as the logo carousel,
   applied to specifications — it bridges the dark catalogue into the light
   band below and gives the numbers a second, more casual appearance.
   ========================================================================== */

.spec-tape {
  background: var(--teal);
  color: var(--black);
  overflow: hidden;
  border-top: 1px solid rgba(0, 0, 0, 0.14);
  border-bottom: 1px solid rgba(0, 0, 0, 0.14);
}
.spec-tape-track {
  display: flex;
  width: max-content;
  align-items: center;
  animation: tape 58s linear infinite;
}
.spec-tape:hover .spec-tape-track { animation-play-state: paused; }
@keyframes tape { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.spec-tape span {
  flex: 0 0 auto;
  padding: 11px 0;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Hexagon separator between items, from the mark */
.spec-tape span::after {
  content: '';
  display: inline-block;
  width: 8px; height: 9px;
  margin: 0 26px;
  vertical-align: middle;
  background: rgba(0, 0, 0, 0.42);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* ==========================================================================
   21 HARDWARE GLOW PLATE
   From the immersive-3D reference, reduced to its cheapest and most useful
   part: a localised radial glow behind hardware on a dark ground, so the
   equipment reads as lit rather than pasted on.
   ========================================================================== */

.glow-plate { position: relative; isolation: isolate; }
.glow-plate::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: -18%;
  background: radial-gradient(circle at 50% 46%,
    rgba(0, 175, 134, 0.30) 0%,
    rgba(0, 175, 134, 0.10) 38%,
    transparent 68%);
  pointer-events: none;
}
.capabilities .product-photo, .dark-band .product-photo { position: relative; }
.capabilities .cap-card .product-photo::before,
.dark-band .cap-card .product-photo::before { content: none; }

/* ==========================================================================
   22 BENTO GRID
   Asymmetric cells rather than a row of equal boxes. Chamfered, hairlined and
   glow-reactive, so the layout technique is borrowed but the styling stays in
   this site's language.
   ========================================================================== */

.bento {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}
.bento-cell {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: clamp(22px, 2.6vw, 34px);
  overflow: hidden;
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
  transition: border-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
  display: flex;
  flex-direction: column;
}
.bento-cell:hover { border-color: var(--teal); transform: translateY(-3px); }
.bento-cell--wide { grid-column: span 2; }
.bento-cell--tall { grid-row: span 2; }
.bento-cell--hero { grid-column: span 2; grid-row: span 2; }
/* Base first, then modifiers. Declaring .bento-cell p after the --teal and
   --dark modifiers at equal specificity made the modifier colours lose the
   cascade, which put mid-grey body copy on a teal ground at 2:1. */
.bento-cell h3 { font-size: var(--fs-h3); text-transform: uppercase; }
.bento-cell h4 { font-size: var(--fs-h4); text-transform: uppercase; letter-spacing: 0.02em; }
.bento-cell p { margin-top: 12px; font-size: var(--fs-body-sm); color: var(--grey); }

.bento-cell--dark { background: var(--anthracite-deep); border-color: var(--line-dark); color: #C3CACE; }
.bento-cell--dark h3, .bento-cell--dark h4 { color: #fff; }
.bento-cell--dark p { color: #AEB7BC; }
.bento-cell--dark .arrow { color: var(--teal-bright); }

.bento-cell--teal { background: var(--teal); border-color: var(--teal); color: var(--black); }
.bento-cell--teal h3, .bento-cell--teal h4, .bento-cell--teal .numeral { color: var(--black); }
.bento-cell--teal p { color: rgba(19, 22, 25, 0.86); }
.bento-cell--teal .arrow { color: var(--black); }
.bento-cell .numeral { display: block; }
.bento-cell .arrow, .bento-cell .btn { margin-top: auto; padding-top: 22px; align-self: flex-start; }
.bento-media { margin: -1px -1px 0; position: relative; overflow: hidden; }
.bento-media img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 1000px) {
  .bento { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .bento-cell--hero, .bento-cell--wide { grid-column: span 2; }
  .bento-cell--hero, .bento-cell--tall { grid-row: auto; }
}
@media (max-width: 620px) {
  .bento { grid-template-columns: 1fr; }
  .bento-cell--hero, .bento-cell--wide { grid-column: span 1; }
}

/* ==========================================================================
   23 STICKY SCROLLYTELLING
   From the cinematic reference, using position: sticky rather than a
   scroll-jacking library. The media pins while the copy cards move past it.
   Scroll behaviour stays native, so the scrollbar, keyboard, trackpad and
   screen readers all behave normally.
   ========================================================================== */

.scrolly { position: relative; }
.scrolly-grid {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 68px);
  align-items: start;
}
.scrolly-media {
  position: sticky;
  top: 108px;
  align-self: start;
}
/* Every frame is absolutely positioned inside a fixed-ratio figure, so
   swapping the active one cross-fades without reflowing the column. */
.scrolly-media figure {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line-dark);
}
.scrolly-media img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.65s var(--ease), transform 1.4s var(--ease);
  transform: scale(1.03);
}
.scrolly-media img[data-active="true"] { opacity: 1; transform: scale(1); }
/* Frame counter, drawing-sheet style */
.scrolly-media figcaption {
  position: absolute;
  z-index: 2;
  left: 14px; bottom: 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #fff;
  background: rgba(19, 22, 25, 0.7);
  padding: 5px 10px;
  border-left: 2px solid var(--teal);
}
/* Corner ticks on the pinned plate */
.scrolly-media figure::before, .scrolly-media figure::after {
  content: '';
  position: absolute;
  z-index: 2;
  width: 20px; height: 20px;
  pointer-events: none;
}
.scrolly-media figure::before { top: 12px; left: 12px; border-top: 2px solid var(--teal); border-left: 2px solid var(--teal); }
.scrolly-media figure::after { bottom: 12px; right: 12px; border-bottom: 2px solid var(--teal); border-right: 2px solid var(--teal); }
.scrolly-steps > * + * { margin-top: clamp(56px, 12vh, 130px); }
.scrolly-step { scroll-margin-top: 120px; }
.scrolly-step h3 { font-size: var(--fs-h2); text-transform: uppercase; letter-spacing: var(--ls-display); }
.scrolly-step .eyebrow { margin-bottom: 12px; }
.scrolly-step > p { margin-top: 16px; }
@media (max-width: 900px) {
  .scrolly-grid { grid-template-columns: 1fr; }
  .scrolly-media { position: static; order: -1; }
  .scrolly-steps > * + * { margin-top: 48px; }
}
/* No JS and no sticky support: show the frames stacked so nothing is lost. */
@media (prefers-reduced-motion: reduce) {
  .scrolly-media { position: static; }
  .scrolly-media figure { aspect-ratio: auto; }
  .scrolly-media img { position: static; opacity: 1; transform: none; }
}

/* ==========================================================================
   24 CUT SELECTOR
   ========================================================================== */

.selector { margin: 44px 0 8px; }
.sel-head h3 {
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  color: #fff;
  margin-top: 10px;
}
.sel-controls {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(18px, 2.4vw, 34px);
  margin: 28px 0 4px;
  padding-bottom: 28px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
@media (max-width: 820px) { .sel-controls { grid-template-columns: 1fr; } }

.sel-field label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-bright);
  margin-bottom: 12px;
}
.sel-dia { display: flex; align-items: baseline; gap: 10px; }
.selector input[type="number"], .selector select {
  background: rgba(0, 0, 0, 0.34);
  border: 1px solid rgba(255, 255, 255, 0.24);
  color: #fff;
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 500;
  letter-spacing: -0.01em;
  padding: 11px 14px;
  width: 100%;
  font-variant-numeric: tabular-nums;
}
.selector input[type="number"] { max-width: 130px; }
.selector select {
  font-size: var(--fs-body-sm);
  appearance: none;
  background-image:
    linear-gradient(45deg, transparent 46%, #fff 46%, #fff 60%, transparent 60%),
    linear-gradient(-45deg, transparent 46%, #fff 46%, #fff 60%, transparent 60%);
  background-size: 6px 6px, 6px 6px;
  background-position: right 20px center, right 14px center;
  background-repeat: no-repeat;
}
.selector input:focus-visible, .selector select:focus-visible {
  outline: 2px solid var(--teal-bright); outline-offset: 2px;
}
.sel-unit {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: #B6BEC2;
}
.selector input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 2px; margin-top: 20px;
  background: linear-gradient(90deg, var(--teal), rgba(0,175,134,0.3));
  cursor: pointer;
}
.selector input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 16px; height: 18px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  cursor: grab;
}
.selector input[type="range"]::-moz-range-thumb {
  width: 16px; height: 18px; border: 0;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.sel-scale {
  display: flex; justify-content: space-between;
  margin-top: 9px;
  font-family: var(--font-mono);
  font-size: 10px; letter-spacing: 0.14em;
  color: #B6BEC2;
}

.sel-out { margin-top: 26px; }
.sel-result-head {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: #B6BEC2;
  display: flex; align-items: baseline; gap: 12px;
}
.sel-result-head b {
  font-family: var(--font-display);
  font-size: 1.9rem; line-height: 1;
  color: var(--teal-bright);
  letter-spacing: -0.02em;
}
.sel-list { margin-top: 16px; }
.sel-list li {
  display: grid;
  grid-template-columns: 104px 108px minmax(0, 1fr) auto;
  gap: 18px;
  align-items: baseline;
  padding: 15px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.sel-list li.sel-best {
  background: linear-gradient(90deg, rgba(0,175,134,0.12), transparent 70%);
  box-shadow: inset 3px 0 0 var(--teal);
  padding-left: 16px;
}
.sel-ref {
  font-family: var(--font-mono);
  font-size: var(--fs-tiny); font-weight: 500;
  letter-spacing: 0.08em;
  color: #fff;
}
.sel-range {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow); letter-spacing: 0.1em;
  color: var(--teal-bright);
}
.sel-note { font-size: var(--fs-tiny); color: #B9C1C6; line-height: 1.55; }
.sel-note em {
  display: block; margin-top: 6px;
  font-style: normal;
  color: #F2DCA6;
}
/* Deployment, installation and power under every saw, on one line with
   dimmed separators. */
.sel-facts .sel-sep { color: rgba(242, 220, 166, 0.45); }
.sel-tag {
  font-family: var(--font-mono);
  font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--black); background: var(--teal);
  padding: 4px 9px; white-space: nowrap;
}
@media (max-width: 760px) {
  .sel-list li { grid-template-columns: 1fr auto; gap: 6px 14px; }
  .sel-note { grid-column: 1 / -1; }
  .sel-list li.sel-best { padding-left: 12px; }
}
.sel-none b { display: block; font-size: var(--fs-h3); color: #fff; text-transform: uppercase; }
.sel-none span { display: block; margin: 12px 0 18px; color: #B9C1C6; font-size: var(--fs-body-sm); max-width: 60ch; }
.sel-trades { margin-top: 30px; padding-top: 24px; border-top: 1px solid rgba(255,255,255,0.14); }
.sel-trades ul { margin-top: 14px; }
.sel-trades li {
  position: relative; padding-left: 26px; margin-top: 0.7em;
  font-size: var(--fs-tiny); color: #B9C1C6; line-height: 1.6; max-width: 78ch;
}
.sel-trades li::before {
  content: ''; position: absolute; left: 2px; top: 0.55em;
  width: 9px; height: 10px; background: var(--teal-bright);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.sel-noscript { color: #C3CACE; font-size: var(--fs-body-sm); }

/* Dim the copy steps that are not current, so the pinned frame and the copy
   read as a pair rather than as two independent columns. */
.scrolly-step { transition: opacity var(--dur) var(--ease); }
.scrolly-step[data-current="false"] { opacity: 0.42; }
.scrolly-step[data-current="true"]  { opacity: 1; }
@media (max-width: 900px) { .scrolly-step[data-current="false"] { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .scrolly-step { opacity: 1 !important; } }

/* --- Forward-link colour on the newer dark grounds ----------------------- */
/* .arrow defaults to the dark teal for light backgrounds. Every dark surface
   has to be named, or the link renders dark-on-dark. Collected here so a new
   dark section only needs adding to this one list. */
.catalogue .arrow, .scrolly .arrow, .cap-band .arrow, .selector .arrow,
.ct-foot .arrow, .band--black .arrow, footer .arrow, .spec-tape .arrow,
.sel-none .arrow {
  color: var(--teal-bright);
}
.catalogue .ct-count, .catalogue .rule-head p { color: #B6BEC2; }

/* ===================================================================== */
/* Contact enquiry form (two-step)                                       */
/* ===================================================================== */
.contact-band { background: var(--anthracite); padding: 70px 0; }
.contact-band .wrap { max-width: 860px; position: relative; z-index: 1; }
.contact-eyebrow {
  font-family: var(--font-mono); font-size: 12px; color: var(--teal-bright);
  letter-spacing: 1.5px; text-transform: uppercase; margin-bottom: 14px;
  display: block; text-align: center;
}
.contact-band h2 {
  font-family: var(--font-display); font-weight: 700; font-size: 26px;
  color: var(--teal-bright); text-transform: uppercase; text-align: center;
  margin: 0 auto 12px; line-height: 1.1; letter-spacing: 1px;
}
.contact-band .lead {
  color: var(--grey-light); text-align: center; max-width: 560px;
  margin: 0 auto 40px; font-size: 15px; line-height: 1.6;
}

/* Step 1: practical details */
.contact-details { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-bottom: 36px; }
@media (max-width: 640px) { .contact-details { grid-template-columns: 1fr; } }
.detail-card {
  background: var(--anthracite-deep); border: 1.5px solid var(--line-teal);
  border-radius: 4px; padding: 20px 22px;
}
/* Rev 4.1: these were <h4> with no h2 or h3 above them, which skipped two
   levels in the document outline. The tag moved, the styling did not. */
.detail-card h2 {
  font-family: var(--font-mono); font-weight: 500; font-size: 11.5px;
  color: var(--teal-bright); letter-spacing: 1.2px; text-transform: uppercase; margin-bottom: 10px;
}
.detail-card p { color: #DDE1E3; font-size: 14px; line-height: 1.55; margin: 0; }
.detail-card a { color: #DDE1E3; }
.detail-card a:hover { color: var(--teal-bright); }

/* Step reveal */
.contact-step-2 { display: none; }
.contact-step-2.is-open { display: block; animation: formfade 0.4s ease; }
@keyframes formfade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.reveal-btn-wrap { text-align: center; }

/* Enquiry chooser */
.enq-legend {
  font-family: var(--font-display); font-weight: 700; font-size: 18px;
  color: var(--white); text-align: center; margin: 8px 0 22px; letter-spacing: 0.4px;
}
.enq-options { display: grid; grid-template-columns: repeat(2, 1fr); gap: 14px; margin-bottom: 8px; }
@media (max-width: 640px) { .enq-options { grid-template-columns: 1fr; } }
.enq-option { position: relative; }
.enq-option input { position: absolute; opacity: 0; pointer-events: none; }
.enq-option label {
  display: block; cursor: pointer; background: var(--anthracite-deep);
  border: 1.5px solid var(--line-dark); border-radius: 4px; padding: 16px 18px;
  transition: border-color 0.18s, background 0.18s;
}
.enq-option label:hover { border-color: var(--line-teal); }
.enq-option input:checked + label { border-color: var(--teal); background: #2F3941; }
.enq-option input:focus-visible + label { outline: 2px solid var(--teal-bright); outline-offset: 2px; }
.enq-option .eo-title { display: block; font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--white); margin-bottom: 4px; }
.enq-option .eo-sub { display: block; font-size: 12.5px; color: var(--grey-light); line-height: 1.45; }

/* Tailored proof panel */
.enq-proof {
  display: none; margin: 22px 0 8px; padding: 20px 22px;
  background: rgba(0, 175, 134, 0.08); border-left: 3px solid var(--teal);
  border-radius: 0 4px 4px 0;
}
.enq-proof.is-shown { display: block; animation: formfade 0.35s ease; }
/* Rev 4.1: were <h5> directly under an <h2>, skipping two outline levels.
   The tag moved, the styling did not: the size is set here rather than
   inherited from the heading level. */
.enq-proof h3 { font-family: var(--font-display); font-weight: 700; font-size: 15px; color: var(--teal-bright); margin-bottom: 8px; }
.enq-proof p { color: #DDE1E3; font-size: 13.5px; line-height: 1.6; margin: 0 0 8px; }
.enq-proof p:last-child { margin-bottom: 0; }
.enq-proof .todo { color: #D98A4A; font-style: italic; font-size: 12.5px; }

/* Message fields */
.contact-fields { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 26px; }
@media (max-width: 640px) { .contact-fields { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; }
.field.full { grid-column: 1 / -1; }
.field label { font-family: var(--font-mono); font-size: 11px; color: var(--grey-light); letter-spacing: 1px; text-transform: uppercase; margin-bottom: 7px; }
.field input, .field textarea {
  background: var(--white); border: 1.5px solid transparent; border-radius: 3px;
  padding: 12px 14px; font-family: var(--font-body); font-size: 14.5px; color: var(--ink); width: 100%;
}
.field input:focus, .field textarea:focus { outline: none; border-color: var(--teal); }
.field textarea { resize: vertical; min-height: 120px; }
.contact-submit { text-align: center; margin-top: 26px; }
.contact-submit .btn { border: none; cursor: pointer; font-family: var(--font-body); padding: 14px 40px; font-size: 15px; }
/* Turnstile. Height reserved so the button does not jump when the check loads. */
.cf-turnstile { margin-top: 26px; min-height: 65px; }
.ask-form .cf-turnstile { margin-top: 12px; }
.form-note { text-align: center; color: var(--grey-light); font-size: 12px; margin-top: 16px; }
.hp-field { position: absolute; left: -9999px; top: -9999px; height: 0; overflow: hidden; }

/* ===================================================================== */
/* Hero carousel (E9) — cross-fading slides                              */
/* ===================================================================== */
.hero-slides { position: absolute; inset: 0; z-index: -2; }
.hero-slide {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.4s ease-in-out;
}
.hero-slide.is-active { opacity: 1; }
.hero-slide .hero-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: auto;
  transform: scale(1.04);
}
/* Award photo: the trophy plaque sits low in frame, so anchor the crop
   towards the bottom on wide banners where cover trims top and bottom. */
@media (min-width: 900px) {
  .hero-slide .hero-bg--awards { object-position: 50% 85%; transform-origin: 50% 85%; }
}
/* slow ken-burns drift on the active slide */
.hero-slide.is-active .hero-bg {
  animation: heroDrift 9s ease-out forwards;
}
@keyframes heroDrift {
  from { transform: scale(1.04); }
  to   { transform: scale(1.10); }
}

/* Headline/lede cross-fade when slide changes */
[data-hero-headline], [data-hero-lede] {
  transition: opacity 0.5s ease;
}
.hero--carousel.is-swapping [data-hero-headline],
.hero--carousel.is-swapping [data-hero-lede] {
  opacity: 0;
}

/* Slide dots */
.hero-dots {
  position: absolute; left: 0; right: 0; bottom: 26px;
  display: flex; gap: 10px; justify-content: center;
  z-index: 2;
}
.hero-dot {
  width: 9px; height: 9px; border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,0.6);
  background: transparent; cursor: pointer; padding: 0;
  transition: background 0.25s, border-color 0.25s, transform 0.25s;
}
.hero-dot:hover { border-color: #fff; }
.hero-dot.is-active { background: var(--teal); border-color: var(--teal); transform: scale(1.15); }

/* Reduced motion: no fades, no drift, first slide only */
@media (prefers-reduced-motion: reduce) {
  .hero-slide { transition: none; }
  .hero-slide.is-active .hero-bg { animation: none; }
  [data-hero-headline], [data-hero-lede] { transition: none; }
  .hero-dots { display: none; }
}

/* ==========================================================================
   25 SUB-PAGE HERO PLATES
   Full-bleed photographic heroes are a homepage device. Interior pages use the
   two-column plate: copy left, photograph right inside a registration-marked
   frame. The supplied banners are 16:11, so the plate takes that ratio instead
   of the 16:9 default and nothing is cropped.
   ========================================================================== */

.cap-hero .cap-photo, .sub-hero .cap-photo { aspect-ratio: 16 / 11; }

/* Stat band reflow. The strip carries four items comfortably at 1440, but the
   rentals labels run longer than the homepage set, so it drops to two columns
   below 1080 and one below 700 rather than crushing to four. Applies to every
   page using .hero-foot, the homepage included. */
@media (max-width: 1080px) and (min-width: 700px) {
  .hero-foot .wrap { grid-template-columns: repeat(2, 1fr); }
  .hero-foot .wrap > div:nth-child(3) { border-left: 0; padding-left: 0; }
  .hero-foot .wrap > div:nth-child(n + 3) { border-top: 1px solid rgba(255, 255, 255, 0.13); }
}
@media (max-width: 699px) {
  .hero-foot .wrap { grid-template-columns: 1fr; }
  .hero-foot .wrap > div { border-left: 0; padding-left: 0; }
  .hero-foot .wrap > div + div { border-top: 1px solid rgba(255, 255, 255, 0.13); }
}

/* Centred closing CTA on Rentals. The heading previously stood alone; the
   supporting line needs the same measure and centring as the heading. */
.rentals-cta .lede {
  max-width: 62ch;
  margin: 18px auto 30px;
}
.rentals-cta h2 + .lede { margin-top: 20px; }

/* Fleet cards. The CAD renders supplied 17 August 2026 have seven different
   aspect ratios, so the image plate is fixed and the render is contained
   inside it. Without this each card's heading sits at a different height and
   the row reads as ragged. */
.cap-card .product-photo {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: contain;
  padding: 10px;
  margin-bottom: 14px;
}

/* The cutting-and-severance intro now carries two paragraphs. Nothing in the
   cut layout set the gap between them, so they ran together. */
.cut-layout > div > p + p { margin-top: 1.1em; }

/* Standfirst above the two hire routes. Carries the engineering claim that the
   two cards then split, so it needs the heading's measure rather than the body
   column's. */
.hiring-lede {
  max-width: 78ch;
  margin: 18px 0 34px;
  font-size: var(--fs-body);
}

/* ==========================================================================
   26 HEXROW TILE HEADINGS
   "Decommissioning" is fifteen characters with no break opportunity. At the
   inherited --fs-h3 it measured 183px inside a 169px column at 1440 and ran
   into the Rentals tile. These are tile labels rather than section headings,
   so they take a step down, sized so the longest single word clears the
   narrowest four-column measure with margin.

   The tiles also stretch to a common height with the arrow pinned to the
   bottom, so the row aligns whether a heading runs to one line or two. That
   was ragged before, because two of the four headings wrap and two do not.
   ========================================================================== */

.hexrow h3 {
  font-size: clamp(0.92rem, 1.25vw, 1.15rem);
  text-wrap: balance;
  /* Last resort only. If Barlow Condensed fails to load and a fallback with wider metrics
     is substituted, the word breaks rather than colliding with the next tile. */
  overflow-wrap: break-word;
}
.hexrow { align-items: stretch; }
/* Matches the a.hextile specificity at section 14, which sets display: block. */
a.hextile, .hextile { display: flex; flex-direction: column; }
.hextile .arrow { margin-top: auto; padding-top: 18px; }

/* ==========================================================================
   27 CAPABILITY PILLARS AND HELD STOCK
   The capabilities hub carries the three lifecycle pillars in the same hexrow
   language as the homepage, at three columns rather than four. Rentals sits
   below them in its own band, because it is bought on a different axis.
   ========================================================================== */

.hexrow--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1000px) { .hexrow--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 640px)  { .hexrow--3 { grid-template-columns: 1fr; } }
/* The pillar tiles carry more copy than the homepage tiles, so the heading
   returns to its full size. Nothing here is a fifteen-character single word
   at a four-column measure. */
.hexrow--3 h3 { font-size: var(--fs-h3); }
.hexrow--3 .hextile p + p { margin-top: 10px; }
.hexrow--3 .hextile .pillar-for {
  display: block;
  margin-top: 12px;
  color: var(--teal-bright);
  font-size: var(--fs-body-sm);
}

/* Held-stock list on Rentals */
/* Six equipment families. Multi-column with no markers read as loose lines of
   text rather than a list, so each item takes a rule in the accent and enough
   leading to separate from its neighbour. */
.stock-list { margin-top: 18px; column-gap: 56px; }
@media (min-width: 860px) { .stock-list { columns: 2; } }
.stock-list li {
  break-inside: avoid;
  position: relative;
  padding: 0 0 0 22px;
  margin-bottom: 13px;
  font-size: var(--fs-body-sm);
  line-height: 1.5;
}
.stock-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.66em;
  width: 11px;
  height: 1px;
  background: var(--teal-bright);
}
/* The note and the testing cross-reference under it sit at the same size, so
   the block does not read as two mismatched paragraphs. */
.stock-note { margin-top: 26px; font-size: var(--fs-body-sm); max-width: 62ch; }
.stock-list + .stock-note { margin-top: 20px; }

/* Rentals hand-off band at the foot of the capabilities hub. The wrap is left
   at the page default so the band aligns with its siblings, and only the
   reading measure is constrained. */
.rentals-handoff .btn, .testing-handoff .btn { margin-top: 30px; }

/* Inline pointer from a capability page to the testing stream that underwrites
   it. Reads as a note rather than a banner, because it is a cross-reference. */
.test-link {
  margin-top: 26px;
  padding: 16px 20px;
  border-left: 2px solid var(--teal);
  background: rgba(0, 175, 134, 0.06);
  font-size: var(--fs-body-sm);
  max-width: 74ch;
}
.cap-band .test-link, .dark-band .test-link, .capabilities .test-link {
  background: rgba(0, 175, 134, 0.12);
}
.test-link b { font-weight: 500; }
.test-link a { color: var(--teal-ink); border-bottom: 1px solid var(--line-teal); }
.cap-band .test-link a, .dark-band .test-link a, .capabilities .test-link a { color: var(--teal-bright); }

/* ==========================================================================
   28 BAND RHYTHM — .dark-band AND .cap-band
   Both carried colour rules but no vertical padding, and neither was in the
   heading or paragraph rhythm the light bands share. On the capabilities hub
   that showed as a heading flush to the band edge, paragraphs running together
   with no gap, and text set to the full wrap width instead of a reading
   measure. They now use the same rhythm as .prose-section and .cap-body, so a
   dark band reads the same as a light one everywhere on the site.
   ========================================================================== */

.dark-band { padding: var(--band-y) 0; }

.dark-band > .wrap > h2, .cap-band > .wrap > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 20px;
  position: relative;
  max-width: 44ch;
}
.dark-band > .wrap > h2::after, .cap-band > .wrap > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
/* An eyebrow above the heading owns the gap, so the heading loses its own. */
.dark-band > .wrap > .eyebrow, .cap-band > .wrap > .eyebrow { margin-bottom: 14px; }

.dark-band > .wrap > p, .cap-band > .wrap > p,
.contract-section > .wrap > p { max-width: 72ch; }
.dark-band > .wrap > p + p, .cap-band > .wrap > p + p,
.contract-section > .wrap > p + p { margin-top: 1.1em; }

.dark-band > .wrap > ul, .cap-band > .wrap > ul { max-width: 72ch; margin-top: 20px; }
.dark-band > .wrap > ul > li + li, .cap-band > .wrap > ul > li + li { margin-top: 12px; }

/* The contract table follows an intro paragraph, so it needs air above it. */
.contract-section .contract-row:first-of-type { margin-top: 30px; }

/* The two hand-off bands on the hub now run as image-and-copy features, so the
   heading rhythm comes from .rf-copy rather than the band-level rule above. */
.rentals-handoff .rf-copy p { margin-top: 14px; }

/* Paragraph rhythm inside the two-column blocks on the hub. The band-level
   rule only reaches direct children of .wrap, so paragraphs nested one level
   deeper ran together. */
.assurance-grid > div > p + p,
.rf-copy > p + p { margin-top: 1.1em; }
.assurance-grid > div > ul { margin-top: 16px; }

/* .cap-body and .prose-section take a narrow 880px wrap for long-form reading.
   That is right on the capability pages, where every band uses it, but on the
   capabilities hub it left one heading indented 180px from every other heading
   on the page. This modifier restores the page gutter for a band that has to
   line up with its neighbours, keeping the reading measure on the paragraphs. */
.cap-body--wide > .wrap { max-width: var(--wrap); }

/* Hero copy on the plate pages ran the paragraph hard against the heading. */
.cap-hero h1 + p, .sub-hero h1 + .lede, .cap-head h1 + .cap-lede { margin-top: 18px; }

/* The FEED band on the hub runs as an image-and-copy feature, so its heading
   takes the same treatment as the rentals hand-off rather than the band rule. */

/* ==========================================================================
   29 FEATURE IMAGE SIZING
   A .photo-ph holding a real photograph was still carrying the placeholder's
   20px inset, so a photo in a placeholder frame rendered 465x320 while the
   same photo in a bare .figure rendered 505x347. On a page mixing both, the
   feature images came out at two different sizes. The inset is dropped when
   the frame holds an image, and every feature photo is pinned to the same
   16:11 frame, so all non-hero photography on a page renders identically.
   ========================================================================== */

.photo-ph:has(img), .ph:has(img) { padding: 0; }
.rental-feature .photo-ph, .sec-block .photo-ph { aspect-ratio: 16 / 11; }
.rental-feature .photo-ph > img,
.rental-feature .figure > img,
.sec-block .photo-ph > img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Global rule at section 03 sets `strong, b` to --ink, which is a dark body
   colour. On a dark band that renders as near-invisible. The existing guard
   covered .on-dark and .dark-band but not .cap-band or .capabilities, and it
   only covered strong, not b. */
.on-dark b, .dark-band b, .cap-band b, .cap-band strong,
.capabilities b, .capabilities strong { color: #fff; }

/* ==========================================================================
   30 DECOMMISSIONING PAGE
   Campaign records collapse into the site's existing accordion so the page
   stays scannable, each carrying a placeholder for its project-record PDF.
   The FEED band splits into copy plus a testing note in a second column.
   ========================================================================== */

.record-acc { margin-top: 30px; }
.record-acc .acc { border-color: rgba(255, 255, 255, 0.16); }
.record-acc .acc-title { text-transform: none; letter-spacing: 0; }
.record-acc .acc-body { max-width: 74ch; }
.record-acc .acc-body .btn { margin-top: 18px; }

/* A button that is deliberately not wired up yet. Dashed and muted so it does
   not read as a live download, with the pending state spelled out rather than
   implied. */
.btn--pending {
  background: transparent;
  border: 1px dashed rgba(255, 255, 255, 0.42);
  color: #D7DCDF;
  clip-path: none;
  cursor: default;
  pointer-events: none;
}
.btn--pending span {
  opacity: 0.62;
  text-transform: none;
  letter-spacing: 0;
  margin-left: 6px;
}
.btn--pending::after { content: none; }

/* FEED band, copy left and the testing cross-reference beside it */
.feed-split .wrap {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 60px);
  align-items: start;
}
.feed-split .test-link { margin-top: 0; }
@media (max-width: 900px) {
  .feed-split .wrap { grid-template-columns: 1fr; }
  .feed-split .test-link { margin-top: 8px; }
}

/* The accordion was built for light bands. On the dark record band its title,
   number and chevron all inherited light-ground colours and disappeared. */
.cap-band .acc > summary { color: #fff; }
.cap-band .acc > summary:hover { color: var(--teal-bright); }
.cap-band .acc .acc-num { color: var(--teal-bright); }
.cap-band .acc .acc-body { color: #D7DCDF; }
.cap-band .chev { border-color: rgba(255, 255, 255, 0.3); }
.cap-band .chev::before, .cap-band .chev::after { background: var(--teal-bright); }
.cap-band .acc[open] > summary .chev { background: rgba(0, 175, 134, 0.18); }

/* The FEED band's heading is now nested one level inside the split grid, so it
   falls outside the direct-child band rules and lost its rule and spacing. */
.feed-split .wrap > div > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 20px;
  position: relative;
  max-width: 44ch;
}
.feed-split .wrap > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.feed-split .wrap > div > p + p { margin-top: 1.1em; }


/* Feature-block headings sit inside .rf-copy, so they fell outside the
   direct-child rule that gives every other section heading on the site its
   measure and teal underline. One rule rather than a per-section override. */
.rental-feature .rf-copy > h2, .sec-block .sec-copy > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 26px;
  padding-bottom: 18px;
  position: relative;
  max-width: 24ch;
}
.rental-feature .rf-copy > h2::after, .sec-block .sec-copy > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}

/* Three-buyer fork on the Decommissioning page. Drops to two columns before
   the cards get too narrow to read, then to one. */
.hiring-grid--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 1100px) { .hiring-grid--3 { grid-template-columns: 1fr 1fr; } }
@media (max-width: 760px)  { .hiring-grid--3 { grid-template-columns: 1fr; } }

/* Contact and Thank You had no h1, which breaks the document outline for
   assistive technology. The heading is promoted and keeps its visual weight. */
.contact-band h1 { font-size: var(--fs-h2); text-transform: uppercase; letter-spacing: var(--ls-display); }

/* ==========================================================================
   31 BODY TEXT COLOUR CONSISTENCY
   Feature blocks set their body copy to --grey while the prose bands next to
   them inherited --ink, so the same page carried mid-grey and near-black body
   text in alternating sections. Dark bands had the same split across two
   different light greys. One value per ground.
   ========================================================================== */

.rf-copy p, .rf-copy li, .sec-copy p, .sec-copy li { color: var(--ink); }
.on-dark .rf-copy p, .on-dark .rf-copy li,
.dark-band .rf-copy p, .capabilities .rf-copy p { color: #D7DCDF; }
.dark-band > .wrap > p, .dark-band > .wrap > li,
.cap-band > .wrap > p, .cap-band > .wrap > li,
.cap-band .hiring-lede, .capabilities .hiring-lede { color: #D7DCDF; }
.feed-split .wrap > div > p { color: #D7DCDF; }

/* Hero plate on the capability pages sits in a different grid to the feature
   blocks, so it rendered three pixels wider. Same column ratio, same size. */
.cap-hero .wrap { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }

/* Body copy resolves to one value per ground. Light grounds take --ink,
   including white cards sitting on a dark band, which were rendering --grey and
   reading washed next to the same copy elsewhere on the page. Dark grounds take
   #D7DCDF. Ledes, eyebrows and compact tile copy keep their own values, because
   that is typographic hierarchy rather than drift. */
.hiring-card p, .hiring-card li, .contract-desc, .contract-desc p { color: var(--ink); }
.dark-band .rule-head p, .band--dark .rule-head p,
.capabilities .rule-head p, .cap-band .rule-head p { color: #D7DCDF; }

/* ==========================================================================
   32 TWO-COLUMN PROSE
   Pairs two related sections side by side. Used where the sections are short
   enough to read as a pair and long enough that stacking them wastes the page.
   ========================================================================== */

.col-split { padding: var(--band-y) 0; }
.col-split .wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(32px, 4.5vw, 76px);
  align-items: start;
}
@media (max-width: 900px) { .col-split .wrap { grid-template-columns: 1fr; row-gap: 48px; } }
.col-split .wrap > div > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 26px;
  padding-bottom: 18px;
  position: relative;
}
.col-split .wrap > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.col-split p + p, .col-split ul + p { margin-top: 1.1em; }
.col-split ul { margin-top: 16px; }
.col-split ul li + li { margin-top: 10px; }
.col-split .test-link { margin-top: 0; }

/* Where one photograph serves a pair of stacked sections, the copy column runs
   much taller than the image. Centring left the photo floating in white space,
   so the image pins to the top of the pair instead. */
.rf-top .wrap { align-items: start; }

/* Two-column prose on a dark band. The colour rules at section 31 reach direct
   children of the band, and these sit one level deeper inside the grid. */
.col-split.cap-band .wrap > div > h2, .col-split.dark-band .wrap > div > h2 { color: #fff; }
.col-split.cap-band .wrap > div > p, .col-split.cap-band .wrap > div > li,
.col-split.dark-band .wrap > div > p { color: #D7DCDF; }

/* Two-column prose lists take the same hex bullet as every other prose list. */
.col-split ul li {
  position: relative;
  padding-left: 26px;
  margin-top: 0.6em;
}
.col-split ul li::before {
  content: '';
  position: absolute;
  left: 2px; top: 0.62em;
  width: 9px; height: 10px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.col-split.cap-band ul li::before, .col-split.dark-band ul li::before { background: var(--teal-bright); }

/* ==========================================================================
   33 SECTORS PAGE
   List items inside a sector block inherited the light-ground body colour, so
   on the anthracite bands they rendered dark grey on dark grey. The sector
   headings are also unified: three blocks carried a link where the fourth
   carried an h2, so the four now share one heading treatment and the page has
   a real heading outline.
   ========================================================================== */

.sec-block.on-dark .sec-copy li,
.sec-block.on-dark .sec-copy p,
.sec-block.on-dark .sec-copy .subhead { color: #D7DCDF; }
.sec-block.on-dark .sec-copy li::before { background: var(--teal-bright); }

.sec-block .sec-copy > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 22px;
  padding-bottom: 18px;
  position: relative;
}
.sec-block .sec-copy > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.sec-block .sec-copy > h2 > .sec-eyebrow-link {
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: inherit;
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
}
.sec-block.on-dark .sec-copy > h2,
.sec-block.on-dark .sec-copy > h2 > .sec-eyebrow-link { color: #fff; }
.sec-block .sec-copy > h2 > .sec-eyebrow-link:hover { color: var(--teal-ink); }
.sec-block.on-dark .sec-copy > h2 > .sec-eyebrow-link:hover { color: var(--teal-bright); }
.sec-block .sec-copy > h2 .arrow { font-size: var(--fs-body); }

/* Every sector photograph renders at one size, like the other pages. */
.sec-block .sec-photo { aspect-ratio: 16 / 11; padding: 0; }
.sec-block .sec-photo > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Sectors hero takes the same two-column plate as the other top-level pages. */
.sec-hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
@media (max-width: 900px) { .sec-hero .wrap { grid-template-columns: 1fr; } }
.sec-hero .cap-photo { aspect-ratio: 16 / 11; }

/* Sector blocks put the copy first in the DOM, so the photograph landed in the
   wider column and rendered 604px against the 505px used by every other
   feature image on the site. Ratio reversed so the photo column matches.

   Guarded by a min-width. Unguarded it sat after the 860px stack rule and beat
   it at every size, so all four sector blocks stayed two columns on a phone:
   176px of text beside a 146px photograph. */
@media (min-width: 861px) {
  .sec-block .wrap { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
}
.sec-hero .cap-photo { aspect-ratio: 16 / 11; }

/* The wipe reveal clipped its element to zero width before the observer ran,
   so a fully clipped element never reported as intersecting and never
   un-clipped. Kept for reference but no longer used in any page. */

/* ==========================================================================
   34 HEADER AT REST
   The logo already shrank on scroll, but the resting size was only 10px
   larger, so the mark never read as part of the banner. At the top of the
   page the bar now goes clear and the lockup steps up, so the logo sits in
   the banner. On scroll it condenses to the compact sticky bar it was.
   The bar sits above the hero copy, so nothing is cut off or covered.
   ========================================================================== */

/* The bar keeps its ground at rest. Going transparent exposed the page
   background above the hero and the nav links stopped being legible. */
header:not([data-scrolled="true"]) {
  background: rgba(45, 55, 62, 0.96);
  border-bottom-color: rgba(255, 255, 255, 0.10);
}
header:not([data-scrolled="true"]) nav { padding: 16px 0; }
header:not([data-scrolled="true"]) .logo-lockup { height: 76px; }

/* Interior pages open on a lighter plate than the homepage carousel, so the
   resting bar keeps a little more weight to hold the nav legible. */
@media (max-width: 899px) {
  header:not([data-scrolled="true"]) .logo-lockup { height: 56px; }
  header:not([data-scrolled="true"]) nav { padding: 10px 0; }
}

/* Hint line under the message field, shown once an enquiry type is chosen. */
.field-hint {
  margin-top: 8px;
  font-size: var(--fs-tiny);
  color: var(--teal-ink);
  opacity: 0;
  max-height: 0;
  overflow: hidden;
  transition: opacity var(--dur-fast) var(--ease), max-height var(--dur-fast) var(--ease);
}
.field-hint.is-shown { opacity: 1; max-height: 4em; }
.on-dark .field-hint, .contact-band .field-hint { color: var(--teal-bright); }

/* "What we are usually asked for" runs the list beside the photograph. The
   list drops to a single column inside the narrower measure, and the whole
   block stacks on small screens. */
.asked--split .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.asked--split ul { grid-template-columns: 1fr; }
.asked--split .asked-img { width: 100%; aspect-ratio: 16 / 11; object-fit: cover; display: block; }
.asked--split .insert-note { margin-top: 16px; }
@media (max-width: 900px) { .asked--split .wrap { grid-template-columns: 1fr; } }

/* ==========================================================================
   35 SUBSEA & OFFSHORE — SPLIT SECTIONS, CERT MARK, FAQ ACCORDION
   ========================================================================== */

/* The vessel argument shares the two-column treatment used by the
   "usually asked for" block, so both photographs land at one size. */
.vessel--split .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.vessel--split .asked-img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
/* The h2 underline rule is bound to `.vessel > .wrap > h2`; in the split
   layout the heading sits one level deeper. */
.vessel--split > .wrap > div > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 20px;
  position: relative;
  max-width: 44ch;
}
.vessel--split > .wrap > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.vessel--split > .wrap > div > p + p { margin-top: 1.1em; }
@media (max-width: 900px) {
  .vessel--split .wrap { grid-template-columns: 1fr; }
}

/* Certification mark beside the assurance copy. Sized as a mark, not
   cropped to the 16:11 photographic ratio. */
.cert-split {
  display: grid;
  grid-template-columns: minmax(0, 58ch) auto;
  justify-content: start;
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.cert-split > div > p + p { margin-top: 1.1em; }
.cert-mark {
  width: clamp(200px, 26vw, 340px);
  height: auto;
  display: block;
  mix-blend-mode: multiply;
}
@media (max-width: 760px) {
  .cert-split { grid-template-columns: 1fr; }
  .cert-mark { width: 220px; }
}

/* FAQ items now carry `.acc`, so they pick up the flex summary layout and
   the chevron sits in its own 30px box on the right instead of collapsing
   to zero width over the question text. No number column here, so the
   body indent that serves the numbered record accordion is reset. */
.faq-item > summary { padding: 20px 0; }
.faq-item .acc-body { padding-left: 0; padding-bottom: 24px; }
.faq-item > summary { text-transform: none; letter-spacing: 0; }

/* Two-line headline lockup. The default h1 scale left "and Bespoke" and
   "Solutions" on separate lines once the hero column narrowed, so the type
   is scaled to the column and the second line is held together with a
   non-breaking space. */
.sub-hero h1.h1-lock {
  font-size: clamp(1.7rem, 3.2vw, 2.85rem);
  max-width: none;
  text-wrap: balance;
}
@media (max-width: 860px) {
  .sub-hero h1.h1-lock { font-size: clamp(1.6rem, 7vw, 2.4rem); }
}

/* The hero intro ran two paragraphs together with no gap. */
.sub-hero > .wrap > div > p + p { margin-top: 1em; }
.sub-hero > .wrap > div > h1 + p { margin-top: 18px; }

/* ==========================================================================
   36 BESPOKE ENGINEERING — ROUTE BOXES, COPY SPLIT, CAROUSEL
   ========================================================================== */

/* Three buying routes as three boxes on the alternate band. */
.route-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 24px);
  margin-top: 32px;
}
.route-grid .hiring-card { display: flex; flex-direction: column; }
.route-grid .hiring-card p:first-of-type { flex: 1 1 auto; }
.route-need {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.route-need b { color: var(--ink); }
@media (max-width: 980px) { .route-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .route-grid { grid-template-columns: 1fr; } }

/* Generic copy-and-image split, so every feature image on a capability page
   lands at the same size as the rest. */
.copy-split > .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.copy-split .split-img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
/* The h2 underline rule targets a direct child of .wrap; in the split layout
   the heading sits one level deeper. */
.copy-split > .wrap > div > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 20px;
  position: relative;
  max-width: 44ch;
}
.copy-split > .wrap > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.copy-split > .wrap > div > * + h2 { margin-top: 2em; }
/* minmax(0, 1fr), not 1fr: the carousel's min-content width is four slides
   wide, and a bare 1fr track floors at min-content, so the section
   overflowed the viewport once the grid collapsed. */
@media (max-width: 900px) { .copy-split > .wrap { grid-template-columns: minmax(0, 1fr); } }

/* --- Carousel ------------------------------------------------------------ */
/* Scroll-snap does the paging. The buttons and dots drive the same scroll,
   so touch, trackpad, keyboard and the controls all agree, and the track
   stays usable with JavaScript off. */
.carousel { margin: 40px 0 8px; max-width: 820px; }
.carousel-viewport { position: relative; overflow: hidden; background: var(--surface-sunk); }
.carousel-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.carousel-track::-webkit-scrollbar { display: none; }
.carousel-track:focus-visible { outline: 2px solid var(--teal); outline-offset: 3px; }
.carousel-slide {
  flex: 0 0 100%;
  margin: 0;
  scroll-snap-align: start;
}
.carousel-slide img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
.carousel-slide figcaption {
  padding: 16px 20px 18px;
  background: var(--anthracite-deep);
  color: #C3CACE;
  font-size: var(--fs-body-sm);
  line-height: 1.55;
  min-height: 5.6em;
}
.carousel-step {
  color: var(--teal-bright);
  font-weight: 500;
  margin-right: 10px;
  letter-spacing: 0.06em;
}
.carousel-controls {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: 18px;
}
.carousel-btn {
  flex: 0 0 auto;
  width: 42px; height: 42px;
  border: 1px solid var(--line-teal);
  background: none;
  cursor: pointer;
  position: relative;
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), opacity var(--dur-fast) var(--ease);
}
.carousel-btn::before {
  content: '';
  position: absolute;
  top: 50%; left: 50%;
  width: 9px; height: 9px;
  border-right: 1.5px solid var(--teal-ink);
  border-bottom: 1.5px solid var(--teal-ink);
}
.carousel-next::before, [data-carousel-next]::before { transform: translate(-60%, -50%) rotate(-45deg); }
.carousel-prev::before, [data-carousel-prev]::before { transform: translate(-40%, -50%) rotate(135deg); }
.carousel-btn:hover:not(:disabled) { background: rgba(0, 175, 134, 0.1); border-color: var(--teal); }
.carousel-btn:disabled { opacity: 0.3; cursor: default; }
.carousel-dots { display: flex; gap: 10px; flex: 1 1 auto; }
.carousel-dot {
  width: 100%;
  max-width: 64px;
  height: 3px;
  padding: 0;
  border: 0;
  background: var(--line);
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease);
}
.carousel-dot:hover { background: var(--teal-bright); }
.carousel-dot[aria-current="true"] { background: var(--teal); }
@media (max-width: 640px) {
  .carousel-slide figcaption { padding: 14px 16px 16px; min-height: 7.5em; }
}
@media (prefers-reduced-motion: reduce) {
  .carousel-track { scroll-behavior: auto; }
}

/* ==========================================================================
   37 TEST-LINK BUTTON, CAROUSEL IN A SPLIT COLUMN
   ========================================================================== */

/* The testing-facility cross-link is now a button rather than an inline link,
   so the note reads as a note and the route out reads as a route out. */
.test-link p { margin: 0; }
.test-link .btn { margin-top: 16px; padding: 11px 20px; font-size: var(--fs-tiny); }
/* White on brand teal is 2.81:1 and fails AA at button sizes; the ghost
   hover state was still setting it. */
.btn--ghost:hover { color: var(--black); }
.on-dark .btn--ghost:hover, .dark-band .btn--ghost:hover,
.capabilities .btn--ghost:hover { color: var(--black); }

/* The carousel sizes itself to its column when it sits in a split. */
.copy-split .carousel { max-width: none; margin: 0; }
.copy-split .carousel-slide figcaption { min-height: 7.2em; }
@media (max-width: 900px) {
  .copy-split .carousel { margin-top: 32px; }
  .copy-split .carousel-slide figcaption { min-height: 0; }
}

/* ==========================================================================
   38 TRACK RECORD — PHONE-FIRST DOCUMENT
   The page was 12,059px on a 390px viewport, 14.3 phone screens for 1,444
   words, with the on-page nav taking 355px before the first sentence and two
   tables that could only be read by scrolling sideways. Three changes:
   the records collapse, the nav becomes one scrollable row, and the tables
   restack as label-and-value rows.
   ========================================================================== */

/* --- On-page nav --------------------------------------------------------- */
.doc-nav-head {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 12px;
}
@media (max-width: 900px) {
  /* One row, swipeable, instead of a nine-row stack. */
  .doc-nav { display: block; margin-bottom: 28px; }
  .doc-nav-head { margin-bottom: 8px; }
  .doc-nav ul {
    display: flex;
    flex-wrap: nowrap;
    gap: 6px;
    overflow-x: auto;
    min-width: 0;
    scrollbar-width: none;
    padding-bottom: 2px;
    -webkit-overflow-scrolling: touch;
  }
  .doc-nav ul::-webkit-scrollbar { display: none; }
  .doc-nav li { flex: 0 0 auto; }
  .doc-nav a { white-space: nowrap; padding: 9px 14px; }
}

/* --- Records as accordions ---------------------------------------------- */
/* The accordion body carries metrics, photo bands and tables as well as
   prose, so the 74ch measure applies to the prose only. */
.doc .record-acc { margin: 8px 0 40px; }
.doc .record-acc .acc-body { max-width: none; }
.doc .record-acc .acc-body > p { max-width: 74ch; }
.doc .record-acc .acc-body > h4 {
  font-size: var(--fs-h4);
  margin-top: 1.6em;
  margin-bottom: 0.55em;
}
.doc .record-acc .acc-body > h4 + p { margin-top: 0.15em; }
.doc .record-acc .acc-body > .band:last-child,
.doc .record-acc .acc-body > .scroll-x:last-child { margin-bottom: 0; }
.doc .record-acc .acc-title { text-transform: none; letter-spacing: 0; }
/* An anchored record is opened by script; mark it so the reader can see
   which one the jump link landed on. */
.doc .record-acc .acc:target > summary .acc-num { background: var(--teal); color: var(--black); }

/* --- Tables: label-and-value rows on a phone ----------------------------- */
@media (max-width: 700px) {
  .scroll-x { overflow-x: visible; }
  .scroll-x .spec, .scroll-x .spec tbody, .scroll-x .spec tr,
  .scroll-x .spec th, .scroll-x .spec td { display: block; width: auto; }
  .scroll-x .spec thead { display: none; }
  .scroll-x .spec caption {
    display: block;
    text-align: left;
    padding-bottom: 10px;
  }
  .scroll-x .spec tbody tr {
    border-bottom: 1px solid var(--line);
    padding: 14px 0;
  }
  .scroll-x .spec tbody tr:last-child { border-bottom: 0; }
  .scroll-x .spec th[scope="row"] {
    background: none;
    white-space: normal;
    padding: 0 0 8px;
    border-bottom: 0;
    color: var(--ink);
    font-size: var(--fs-tiny);
    letter-spacing: 0.06em;
  }
  .scroll-x .spec td {
    padding: 3px 0 3px 0;
    border-bottom: 0;
    color: var(--grey);
  }
  .scroll-x .spec td::before {
    content: attr(data-label) " ";
    display: inline;
    color: var(--teal-ink);
  }
}

/* --- Document rhythm ----------------------------------------------------- */
/* Every section type on this site declares its own vertical rhythm, and
   .doc-body never got one: paragraphs computed to margin 0 and abutted each
   other, and headings sat flush against the text below them. That is the
   real reason this page read as a wall of type at any width. */
.doc-body > p + p,
.doc-body .acc-body > p + p { margin-top: 1.1em; }
.doc-body > h2 {
  margin-top: 1.9em;
  margin-bottom: 0.7em;
  padding-bottom: 18px;
  position: relative;
}
.doc-body > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.doc-body > :first-child { margin-top: 0; }
.doc-body > h2:first-of-type { margin-top: 0.6em; }
.doc-body > p + ul,
.doc-body .acc-body > p + ul { margin-top: 1.1em; }
.doc-body > .callout:first-child { margin-top: 0; }
.doc-body .acc-body > p + .insert-note,
.doc-body > p + .insert-note { margin-top: 1.2em; }
.doc-body .insert-note + p { margin-top: 1.2em; }
@media (max-width: 900px) {
  /* The collapsed grid already supplies a 32px row gap. */
  .doc-nav { margin-bottom: 4px; }
}

/* .doc-body was grouped with the band-level sections and inherited
   `padding: var(--band-y) 0`, but it is a grid column inside a section that
   already carries its own padding. That was 64px of dead space above the
   first line at every width, and on a phone it sat between the jump-link row
   and the opening callout. */
.doc-body { padding: 0; }

/* --- Industry feature rhythm --------------------------------------------- */
/* .ind-feature never declared a vertical rhythm, so its headings sat flush on
   the first paragraph and the paragraphs abutted each other. Same omission as
   .doc-body carried on the track record page. */
.ind-feature .wrap > div > h2 {
  margin-bottom: 26px;
  padding-bottom: 18px;
  position: relative;
}
.ind-feature .wrap > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.ind-feature.on-dark .wrap > div > h2::after { background: var(--teal-bright); }
.ind-feature .wrap > div > p + p { margin-top: 1.1em; }
.ind-feature .wrap > div > p + .insert-note { margin-top: 1.6em; }
/* A placeholder heading is an open item, not a section title: no rule under it. */
.ind-feature .wrap > div > h2.to-come::after,
.ind-feature .wrap > div > h2:has(+ .insert-note)::after { display: none; }

/* --- Industry page image sizing ------------------------------------------ */
/* `.ind-photo` was left out of the `:has(img)` reset, so it kept the 20px
   dashed-placeholder inset once a real photograph went in and rendered 50px
   narrower than every other feature image on the site. */
.ind-photo:has(img),
.ind-photo.light:has(img),
.ind-photo.dark:has(img) { padding: 0; border: 0; background: none; }
.ind-photo > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The shared feature grid is 5fr/6fr, written for markup that puts the image
   first. The industry pages put the copy first, so the image column came out
   wider than the copy and the photographs rendered at 606px against 508px
   everywhere else. Reversed for .ind-feature only. */
.ind-feature .wrap { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
@media (max-width: 860px) { .ind-feature .wrap { grid-template-columns: 1fr; } }

/* `.ind-hero .wrap` was a grid with a single column, so the industry heroes
   stacked and the photograph ran the full 1176px wrap. Brought into line with
   the other page heroes. */
.ind-hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
@media (max-width: 860px) { .ind-hero .wrap { grid-template-columns: 1fr; } }
.ind-hero .ind-photo { aspect-ratio: 16 / 11; }

/* The asked block on an industry page uses the same split as the sector
   pages, so its photograph lands at the shared feature width. */
.asked--split .ind-photo { width: 100%; aspect-ratio: 16 / 11; }

/* The asked and hero headings sit one level deeper in the split layouts, so
   the teal underline rule and the heading-to-lede gap both missed them. */
.asked--split > .wrap > div > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 20px;
  position: relative;
  max-width: 44ch;
}
.asked--split > .wrap > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}
.ind-hero .wrap > div > h1 + p { margin-top: 18px; }
.ind-hero .wrap > div > p + p { margin-top: 1em; }

/* One deliberate exception to the shared feature ratio. The tidal turbine is
   the page's only renewables photograph and it is natively portrait: cropped
   to 16/11 it lost the support structure and the base entirely. It runs at
   its own aspect ratio instead. */
.ind-photo--tall { aspect-ratio: 673 / 1100; }
.ind-photo--tall > img { object-fit: contain; }
.ind-feature .wrap:has(.ind-photo--tall) { align-items: center; }
/* Uncropped on a phone too. A 3/4 crop was tried and cut the tower, which is
   the part that makes the photograph worth having. */

/* .ind-feature carried no list rhythm and its lists were missing from the hex
   bullet group, so a bulleted list rendered as unmarked lines running into the
   surrounding paragraphs. */
.ind-feature .wrap > div > p + ul,
.ind-feature .wrap > div > h2 + ul { margin-top: 1.2em; }
.ind-feature .wrap > div > ul + p { margin-top: 1.4em; }
/* An empty .ind-photo had no intrinsic size, so a placeholder collapsed to a
   thin strip instead of reading as an image slot. */
.ind-photo { aspect-ratio: 16 / 11; }

/* Declared after the blanket .ind-photo ratio so the portrait exception wins
   by cascade order rather than by content-driven accident. */
.ind-photo.ind-photo--tall { aspect-ratio: 673 / 1100; }

/* The dark-ground amber flag only covered .cap-band and .map-block, so an
   editorial note placed in a dark page hero or a dark industry band rendered
   its bold lead in a near-invisible tone. Extended to every dark ground. */
.tf-hero .insert-note, .ind-hero .insert-note, .sub-hero .insert-note,
.cap-head .insert-note, .cap-hero .insert-note, .sec-hero .insert-note,
.tr-head .insert-note, .on-dark .insert-note, .dark-band .insert-note,
.capabilities .insert-note, .cta-band .insert-note {
  color: #F2DCA6;
  background: rgba(224, 163, 46, 0.14);
}
.tf-hero .insert-note strong, .ind-hero .insert-note strong,
.sub-hero .insert-note strong, .cap-head .insert-note strong,
.cap-hero .insert-note strong, .sec-hero .insert-note strong,
.tr-head .insert-note strong, .on-dark .insert-note strong,
.dark-band .insert-note strong, .capabilities .insert-note strong,
.cta-band .insert-note strong { color: #F7E9C4; }

/* The workshop is a separate site from the Kewdale office, so it gets its own
   card spanning the pair rather than sharing a heading with the office. */
.detail-card--wide { grid-column: 1 / -1; }
@media (max-width: 640px) { .detail-card--wide { grid-column: auto; } }
.ph-inline {
  display: inline-block;
  margin-top: 8px;
  color: #F2DCA6;
  background: rgba(224, 163, 46, 0.14);
  padding: 4px 9px;
  font-size: var(--fs-tiny);
}

/* Portrait feature image inside a copy split. Same exception as the tidal
   turbine: cropping a vertical subject to 16/11 throws away the subject. */
.copy-split .split-img--tall { aspect-ratio: 3 / 4; }

/* Two-column intro inside a band whose lower content stays full width. */
.band-intro {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
  margin-bottom: 8px;
}
.band-intro > div > p + p { margin-top: 1.1em; }
.band-intro .split-img { width: 100%; aspect-ratio: 16 / 11; object-fit: cover; display: block; }
.band-intro > div > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 24px;
  padding-bottom: 18px;
  position: relative;
  max-width: 44ch;
}
.band-intro > div > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal-bright);
}
@media (max-width: 900px) { .band-intro { grid-template-columns: 1fr; } }

/* Paragraph rhythm inside a copy split. The .cap-body rule targets a direct
   child of .wrap, so consecutive paragraphs one level deeper had no gap. */
.copy-split > .wrap > div > p + p,
.copy-split > .wrap > div > ul + p,
.copy-split > .wrap > div > p + ul { margin-top: 1.1em; }

/* ==========================================================================
   39 MOBILE NAV STACKING — CRITICAL FIX
   `header` is position: sticky with a z-index, so it forms a stacking context.
   `.nav-links` sat at z-index 110 *inside* that context, so it painted at the
   header's level. `.nav-scrim` is a sibling of <header> at root level, so at
   z-index 105 it painted over the open drawer with pointer-events: auto and
   swallowed every tap on a nav link. Verified with elementFromPoint: taps on
   the drawer returned DIV.nav-scrim, not the anchor. The menu opened and no
   link could be reached on any page that carries the scrim, which is 14 of 16.
   The header now sits above the scrim, so the drawer inside it does too.
   ========================================================================== */
header { z-index: 120; }

/* ==========================================================================
   40 TESTING CENTRE — BENEFITS GRID AND STREAM ACCORDION
   ========================================================================== */

/* --- Why test here, four benefits ---------------------------------------- */
.benefits {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 40px);
  margin: 40px 0 0;
  padding: 0;
  list-style: none;
}
.benefits > li { padding: 0; margin: 0; }
.benefits > li::before { content: none; }
.benefit-icon {
  display: grid;
  place-items: center;
  width: 48px; height: 55px;
  margin-bottom: 16px;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: rgba(0, 175, 134, 0.14);
  color: var(--teal-ink);
}
.benefit-icon svg { width: 24px; height: 24px; display: block; }
.benefits h3 {
  font-size: var(--fs-h4);
  text-transform: uppercase;
  letter-spacing: 0;
  margin-bottom: 10px;
  max-width: 26ch;
}
.benefits p { font-size: var(--fs-body-sm); color: var(--grey); max-width: 46ch; }
@media (max-width: 760px) { .benefits { grid-template-columns: 1fr; } }

/* --- Stream accordion ----------------------------------------------------- */
/* The abbreviation and the full name were both set at eyebrow size, so a code
   and a title carried identical weight and the row read as three competing
   lines. The code now leads at display size, the name reads as a title beside
   it, and the rule sits under the pair. */
.stream { border-bottom: 0; }
.stream > summary {
  display: grid;
  grid-template-columns: minmax(6.5rem, auto) minmax(0, 1fr) auto;
  align-items: baseline;
  gap: clamp(14px, 2.5vw, 34px);
  padding: 22px 0 14px;
  border-bottom: 1px solid var(--line);
  font-size: inherit;
  letter-spacing: 0;
  text-transform: none;
}
.stream > summary .chev { align-self: center; }
.stream-abbr {
  font-family: var(--font-display);
  font-size: clamp(1.25rem, 2.1vw, 1.7rem);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: 0.01em;
  color: var(--teal-ink);
  white-space: nowrap;
}
.stream-name {
  font-size: var(--fs-h3);
  font-weight: 500;
  line-height: 1.25;
  color: var(--ink);
  text-transform: none;
  letter-spacing: 0;
}
.stream > summary:hover .stream-name { color: var(--teal-ink); }
.stream[open] > summary .stream-name { color: var(--teal-ink); }
.stream .acc-body { padding: 18px 0 30px; max-width: none; }
.stream-who {
  font-size: var(--fs-body-sm);
  color: var(--teal-ink);
  margin-bottom: 12px;
}
.stream .acc-body > p { max-width: 74ch; }
.stream-eg {
  margin-top: 18px;
  padding: 14px 18px;
  background: var(--surface-alt);
  border-left: 2px solid var(--line-teal);
  font-size: var(--fs-body-sm);
  color: var(--grey);
}
.stream-eg > span {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 6px;
}
.stream-outro { margin-top: 34px; max-width: 74ch; }
@media (max-width: 700px) {
  .stream > summary {
    grid-template-columns: minmax(0, 1fr) auto;
    row-gap: 4px;
  }
  .stream-abbr { grid-column: 1; white-space: normal; }
  .stream-name { grid-column: 1; }
  .stream > summary .chev { grid-column: 2; grid-row: 1 / span 2; }
}

/* --- Launch switch -------------------------------------------------------- */
/* Editorial flags are deliberately loud so they cannot be missed internally.
   Add data-build="live" to the <html> element of the deploy build to suppress
   every note in one move. Placeholder SECTIONS still have to be filled or
   removed; this only hides the notes, it does not finish the page. */
html[data-build="live"] .insert-note,
html[data-build="live"] .cap-note,
html[data-build="live"] .flag,
html[data-build="live"] .ph-inline,
html[data-build="live"] .todo { display: none !important; }
/* A whole section held open for copy that has not arrived. Hiding only the
   note would leave a heading standing over nothing, which is worse than the
   note, so the section goes as one. Rev 3.7: bespoke, hull plugs. */
html[data-build="live"] .ph-section { display: none !important; }

/* `.intro` sits in the band-level padding group alongside .sec-block and
   .ind-feature, but the only element using it is a paragraph on the Testing
   Centre. It was inheriting 115px of section padding-bottom, which read as a
   hole between the heading and the first stream. No section.intro exists. */
p.intro { padding: 0; margin-bottom: 8px; }

/* .tf-problem never declared a paragraph rhythm, so its two opening
   paragraphs ran together. */
.tf-problem > .wrap > p + p { margin-top: 1.1em; }

/* Fixed abbreviation column so the four stream titles align down the page.
   Each <details> is its own grid, so an auto column cannot align across them. */
.stream-abbr {
  width: clamp(8rem, 13vw, 11.5rem);
  font-size: clamp(1.15rem, 1.9vw, 1.55rem);
}
.stream > summary { grid-template-columns: auto minmax(0, 1fr) auto; }
.stream-who { font-size: var(--fs-body); }
@media (max-width: 700px) { .stream-abbr { width: auto; } }

/* The four benefits sit in cards. Equal-height by grid stretch, so the row
   reads as a block whatever the heading lengths do. */
.benefits { grid-auto-rows: 1fr; }
.benefits > li {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-top: 3px solid var(--teal);
  padding: clamp(22px, 2.6vw, 30px);
  transition: box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.benefits > li:hover { box-shadow: var(--shadow-lift); transform: translateY(-3px); }
.benefits h3 { max-width: none; }
.benefits p { max-width: none; margin-top: auto; padding-top: 2px; }
/* Single column: cards size to their own content, so the auto margin that
   bottom-aligns body copy across a row is not needed and leaves a gap. */
@media (max-width: 760px) {
  .benefits { grid-auto-rows: auto; }
  .benefits p { margin-top: 14px; }
}

/* ==========================================================================
   41 CONTACT — TWO-COLUMN LAYOUT, LIGHT FORM PANEL
   The h1 had no colour rule of its own. `.contact-band h2` is set to
   teal-bright, but this page uses an h1, and the only h1 rule set size and
   letter-spacing, so the page title fell back to near-black ink on the
   anthracite band. The lead used --grey-light, also too dark on that ground.
   ========================================================================== */

.contact-band h1 { color: #fff; }
.contact-band .lead { color: #C3CACE; }

/* --- Split layout --------------------------------------------------------- */
.contact-band--split .wrap {
  max-width: var(--wrap);
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(32px, 4vw, 72px);
  align-items: start;
}
.contact-band--split .contact-eyebrow,
.contact-band--split h1,
.contact-band--split .lead { text-align: left; margin-left: 0; margin-right: 0; }
.contact-band--split .lead { max-width: 46ch; margin-bottom: 32px; }
.contact-band--split .contact-details { grid-template-columns: 1fr; gap: 14px; margin-bottom: 0; }
@media (max-width: 940px) {
  .contact-band--split .wrap { grid-template-columns: 1fr; }
  .contact-band--split .contact-details { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .contact-band--split .contact-details { grid-template-columns: 1fr; }
}

/* --- The form sits on a light panel --------------------------------------- */
/* Dark option cards on a dark band read as boxes rather than as controls.
   On white they read as choices, which is what they are. */
.contact-panel {
  background: var(--surface);
  padding: clamp(24px, 3vw, 40px);
  border-top: 3px solid var(--teal);
}
.contact-panel .enq-set { border: 0; padding: 0; margin: 0; }
.contact-panel .enq-legend {
  color: var(--ink);
  text-align: left;
  font-size: var(--fs-h4);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  margin: 0 0 18px;
  padding: 0;
}
.contact-panel .enq-options { gap: 12px; margin-bottom: 0; }
.contact-panel .enq-option--wide { grid-column: 1 / -1; }
.contact-panel .enq-option label {
  background: var(--surface-alt);
  border: 1.5px solid var(--line);
  border-radius: 3px;
  padding: 15px 16px;
  height: 100%;
}
.contact-panel .enq-option label:hover {
  border-color: var(--teal);
  background: rgba(0, 175, 134, 0.07);
}
.contact-panel .enq-option input:checked + label {
  border-color: var(--teal);
  background: rgba(0, 175, 134, 0.12);
  box-shadow: inset 3px 0 0 var(--teal);
}
.contact-panel .enq-option .eo-title { color: var(--ink); font-size: var(--fs-body-sm); }
.contact-panel .enq-option input:checked + label .eo-title { color: var(--teal-ink); }
.contact-panel .enq-option .eo-sub { color: var(--grey); }

/* --- Tailored panel: icon, heading, copy, route out ------------------------ */
.contact-panel .enq-proof {
  display: none;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 18px;
  margin: 22px 0 0;
  padding: 20px 22px;
  background: var(--anthracite-deep);
  border-left: 0;
  border-radius: 3px;
}
.contact-panel .enq-proof.is-shown { display: grid; }
.enq-proof-icon {
  display: grid;
  place-items: center;
  width: 42px; height: 48px;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: rgba(0, 175, 134, 0.2);
  color: var(--teal-bright);
}
.enq-proof-icon svg { width: 22px; height: 22px; display: block; }
.contact-panel .enq-proof h3 {
  color: #fff;
  font-size: var(--fs-body);
  line-height: 1.35;
  margin-bottom: 8px;
}
.contact-panel .enq-proof p { color: #C3CACE; font-size: var(--fs-body-sm); }
.enq-proof-link {
  display: inline-block;
  margin-top: 12px;
  color: var(--teal-bright);
  font-size: var(--fs-tiny);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border-bottom: 1px solid rgba(0, 175, 134, 0.5);
}
.enq-proof-link:hover { color: #fff; border-bottom-color: #fff; }
.contact-panel .enq-proof .todo { margin-top: 10px; }

/* --- Fields on a light panel ---------------------------------------------- */
.contact-panel .field label { color: var(--grey); }
.contact-panel .field input,
.contact-panel .field textarea {
  background: var(--surface);
  border: 1.5px solid var(--line);
  color: var(--ink);
}
.contact-panel .field input:focus,
.contact-panel .field textarea:focus { border-color: var(--teal); outline: none; }
.contact-panel .field-hint { color: var(--grey); }
.contact-panel .contact-submit { text-align: left; }
.contact-panel .form-note { text-align: left; color: var(--grey); }

/* Where the privacy and consent wording goes. */
.form-statement {
  margin-top: 22px;
  padding: 14px 16px;
  background: var(--surface-alt);
  border: 1px dashed var(--line);
  font-size: var(--fs-tiny);
  color: var(--grey);
}
.form-statement strong { color: var(--ink); }
html[data-build="live"] .form-statement,
html[data-build="live"] .todo { display: none !important; }
.contact-band--split h1 { margin-bottom: 16px; }
.contact-band--split .contact-eyebrow { margin-bottom: 12px; }

/* --- Stream icons ---------------------------------------------------------- */
/* The supplied icons are flat single-colour artwork, so they are used as CSS
   masks rather than images. That way they take currentColor and read correctly
   on a light band, a dark band or in a hover state, which a flat PNG cannot. */
.stream-icon {
  width: 34px; height: 34px;
  flex: 0 0 auto;
  align-self: center;
  opacity: 0.72;
  transition: opacity var(--dur-fast) var(--ease);
}
.stream > summary { grid-template-columns: auto auto minmax(0, 1fr) auto; }
.stream[open] > summary .stream-icon,
.stream > summary:hover .stream-icon { opacity: 1; }
@media (max-width: 700px) {
  .stream > summary {
    grid-template-columns: auto minmax(0, 1fr) auto;
    column-gap: 14px;
  }
  .stream-icon { grid-row: 1 / span 2; grid-column: 1; align-self: start; }
  .stream-abbr { grid-column: 2; }
  .stream-name { grid-column: 2; }
  .stream > summary .chev { grid-column: 3; grid-row: 1 / span 2; }
}

/* ==========================================================================
   42 PAGE-LEVEL VERIFICATION FLAG
   For a page whose copy is not yet sourced. Sits above the hero so it cannot
   be scrolled past, and is removed wholesale in the deploy build by the same
   data-build switch that suppresses the inline notes.
   ========================================================================== */
.page-flag {
  background: #4A3B18;
  border-bottom: 3px solid #E0A32E;
  padding: clamp(26px, 3.4vw, 44px) 0;
  color: #F2DCA6;
}
.page-flag-status {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: #1C1608;
  background: #E0A32E;
  padding: 5px 12px;
  margin-bottom: 16px;
}
.page-flag h2 {
  color: #F7E9C4;
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  margin-bottom: 14px;
  max-width: 34ch;
}
.page-flag > .wrap > p { max-width: 82ch; font-size: var(--fs-body-sm); line-height: 1.6; }
.page-flag-list {
  list-style: decimal outside;
  margin: 22px 0 0;
  padding: 0 0 0 1.5em;
  max-width: 82ch;
}
.page-flag-list li {
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  margin-top: 0.85em;
  padding-left: 4px;
}
.page-flag-list li::marker { color: #E0A32E; font-weight: 500; }
.page-flag-list strong, .page-flag p strong { color: #F7E9C4; }
.page-flag-foot {
  margin-top: 22px;
  padding-top: 16px;
  border-top: 1px solid rgba(224, 163, 46, 0.35);
  color: #D8C79A;
}
html[data-build="live"] .page-flag { display: none !important; }

/* Track record photographs sit in the existing .band grid, at the shared ratio. */
.band figure .rec-img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
/* A single-figure band should not render as a quarter-width thumbnail. */
.band:not(.band--2):has(figure:only-child) { grid-template-columns: minmax(0, 1fr); max-width: 620px; }

/* Headline metrics above the record accordion. These are the page's proof, so
   they sit outside every <details> — visible on a phone, and in the crawler's
   rendered opening rather than behind a disclosure. */
.metrics--headline {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 clamp(20px, 3vw, 44px);
  border-top: 2px solid var(--teal);
  border-bottom: 1px solid var(--line);
  margin: 8px 0 40px;
}
.metrics--headline li { border-bottom: 0; padding: 18px 0; }
.metrics--headline .n { color: var(--teal-ink); }
@media (max-width: 640px) { .metrics--headline { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .metrics--headline li { padding: 14px 0; border-bottom: 1px solid var(--line); } }

/* The record titles are now h3 inside <summary>; keep the summary layout. */
.record-acc h3.acc-title { font-size: inherit; margin: 0; font-weight: 500; }

/* ==========================================================================
   43 MOBILE NAV DRAWER — CRITICAL FIX
   `header` carries `backdrop-filter`, and a backdrop-filter establishes a
   containing block for `position: fixed` descendants exactly as `transform`
   does. `.nav-links` is `position: fixed; inset: 0 0 0 auto`, so it was
   resolving against the header's own 128px box rather than the viewport: the
   drawer opened as a 128px stub showing only the first link, with the rest
   clipped and the scrim sitting over where they should have been. Verified
   with elementFromPoint — 14 of 15 drawer links returned DIV.nav-scrim.
   The blur is a desktop flourish, so it is dropped at the drawer breakpoint.
   ========================================================================== */
@media (max-width: 960px) {
  header {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--anthracite-deep);
  }
}

/* The outlined Contact button existed but only three pages carried the class,
   and `.nav-links > a` outranked it on padding so even those rendered tight. */
.nav-links > a.nav-cta, header nav a.contact { padding: 9px 18px; }

/* About hero: photograph beside the copy rather than a tinted band beneath it.
   No duotone, so the image keeps its own colour. */
.page-hero .wrap {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.hero-side-img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
@media (max-width: 860px) { .page-hero .wrap { grid-template-columns: 1fr; } }

/* A 21:9 placeholder with min-height: 200px resolves to a 467px width, which
   overflows a 350px mobile column. The aspect ratio should govern below that. */
@media (max-width: 700px) {
  .photo-ph.wide, .ph.wide { min-height: 0; }
}

/* ============================================================================
   44  CASE STUDIES — index cards, sector filter, detail page furniture
   ==========================================================================*/

/* --- 44.1  filter chips ------------------------------------------------- */
.cs-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: clamp(28px, 3.4vw, 44px);
}
.cs-chip {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--ink);
  background: none;
  border: 1px solid var(--line);
  padding: 9px 16px;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.cs-chip:hover { border-color: var(--teal); }
.cs-chip.is-on {
  background: var(--teal);
  border-color: var(--teal);
  color: var(--anthracite-deep);
}
.cs-chip:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 2px; }

.cs-empty {
  margin-top: 32px;
  color: var(--grey);
  font-size: var(--fs-body-sm);
}

/* --- 44.2  card grid ---------------------------------------------------- */
.cs-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 2.4vw, 32px);
}
.cs-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  color: inherit;
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.cs-card:hover {
  border-color: var(--teal);
  transform: translateY(-3px);
  box-shadow: 0 14px 34px rgba(19, 22, 25, 0.09);
}
.cs-card-media {
  display: block;
  position: relative;
  aspect-ratio: 16 / 11;
  overflow: hidden;
  background: var(--surface-alt);
}
.cs-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 620ms var(--ease);
}
.cs-card:hover .cs-card-media img { transform: scale(1.035); }

.cs-card-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: clamp(20px, 2.2vw, 28px);
}
.cs-card-tag {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
}
.cs-card-title {
  display: block;
  margin-top: 12px;
  font-family: var(--font-display);
  font-size: clamp(1.0625rem, 1.35vw, 1.25rem);
  font-weight: 500;
  line-height: 1.22;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: var(--ink);
}
.cs-card-hook {
  display: block;
  margin-top: 12px;
  font-size: var(--fs-body-sm);
  line-height: 1.55;
  color: var(--grey);
}
.cs-card-meta {
  display: block;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-tiny);
  line-height: 1.45;
  color: var(--grey);
}
.cs-card-meta b {
  display: block;
  font-weight: 500;
  color: var(--ink);
}
.cs-card-meta span { display: block; margin-top: 2px; }
.cs-card-more {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: auto;
  padding-top: 18px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
}
.cs-card-more::after {
  content: '';
  width: 16px;
  height: 1px;
  background: currentColor;
  transition: width var(--dur-fast) var(--ease);
}
.cs-card:hover .cs-card-more::after { width: 28px; }

/* --- 44.3  detail page fact strip --------------------------------------- */
.cs-facts {
  background: var(--surface-alt);
  border-bottom: 1px solid var(--line);
  padding: clamp(22px, 2.6vw, 34px) 0;
}
.cs-facts-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 40px);
  margin: 0;
}
.cs-facts-grid dt {
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
}
.cs-facts-grid dd {
  margin: 8px 0 0;
  font-size: var(--fs-body-sm);
  line-height: 1.45;
  color: var(--ink);
}

/* --- 44.4  detail page body --------------------------------------------- */
.cs-body .metrics--headline { margin-top: 0; }
.cs-body h2 {
  margin-top: 2.2em;
  padding-bottom: 16px;
  position: relative;
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
}
.cs-body h2::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: 0;
  width: 48px;
  height: 3px;
  background: var(--teal);
}
.cs-body h2 + * { margin-top: 1.2em; }
.cs-body h3 { margin-top: 1.9em; }
.cs-body p { max-width: 68ch; }

.cs-figure { margin: clamp(32px, 4vw, 52px) 0; }
.cs-figure img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
.cs-figure .figure-note { left: 0; bottom: 62px; }

/* --- 44.5  responsive ---------------------------------------------------- */
@media (max-width: 1020px) {
  .cs-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cs-facts-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 680px) {
  .cs-grid { grid-template-columns: minmax(0, 1fr); }
  .cs-facts-grid { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .cs-facts-grid > div {
    display: grid;
    grid-template-columns: 96px minmax(0, 1fr);
    gap: 12px;
    align-items: baseline;
  }
  .cs-facts-grid dd { margin-top: 0; }
  .cs-filter { gap: 8px; }
  .cs-chip { padding: 8px 13px; }
  .cs-figure .figure-note { display: none; }
}

/* --- 44.6  launch switch ------------------------------------------------- */
html[data-build="live"] .cs-flag { display: none !important; }

/* ============================================================================
   45  MOBILE NAV — CONTACT CTA BELOW THE FOLD
   Fifteen links across three expanded dropdowns give the drawer a 916px
   scroll height inside an 844px viewport, so on a 390x844 phone the Contact
   button sat at y=828 with 16px of it showing. elementFromPoint returned null
   for its centre on all 23 pages. It is the conversion path, so it should not
   be the thing you have to scroll to find. Two changes: tighten the list so it
   very nearly fits, and pin the CTA to the bottom of the drawer so it is
   visible at any list length or phone height.
   ==========================================================================*/
@media (max-width: 960px) {
  .nav-links {
    padding-bottom: 78px;
    overscroll-behavior: contain;
    scroll-padding-bottom: 78px;
  }

  /* The CTA rides the bottom of the scroll container. */
  .nav-links > a.nav-cta {
    position: sticky;
    bottom: 0;
    z-index: 2;
    margin-top: 18px;
    text-align: center;
    justify-content: center;
    padding: 15px 18px;
    background: var(--teal);
    border-color: var(--teal);
    color: var(--anthracite-deep);
    /* Fade the list out above the bar and fill the reserved space below it,
       so the CTA reads as a pinned footer rather than a button floating over
       whichever link happens to be behind it. */
    box-shadow: 0 -20px 26px 10px var(--anthracite-deep),
                0 44px 0 26px var(--anthracite-deep);
  }
  .nav-links > a.nav-cta:hover,
  .nav-links > a.nav-cta:focus-visible {
    background: var(--teal-bright);
    border-color: var(--teal-bright);
    color: var(--anthracite-deep);
  }
}

/* ============================================================================
   46  CASE STUDY FILTER — [hidden] WAS BEING OVERRIDDEN
   `.cs-card { display: flex }` is an author rule and beats the UA stylesheet's
   `[hidden] { display: none }`, so the filter set the attribute correctly and
   every card stayed on screen. Verified by attribute rather than by computed
   display first time round, which is why it passed.
   ==========================================================================*/
.cs-card[hidden] { display: none !important; }

/* ==========================================================================
   47 ABOUT — ORIGIN STORY AND THE MARK DECODE
   Two sections replacing the old three-question .story block.

   The brief was "authentic, organic, a passionate small team". The devices
   that carry that here are all restraint rather than decoration: a single
   reading column at 62ch instead of the site's usual two-column grids, a
   signature block instead of a heading, and Linden's own hand-annotated
   sketch shown as four steps rather than redrawn cleanly. The wobble in the
   red trace is the point. Do not vectorise it.

   Light ground throughout. The mark is charcoal and teal; on anthracite the
   charcoal half of it vanishes.
   ==========================================================================*/

.origin { padding: var(--band-y) 0; }
.origin-wrap { max-width: 1120px; }
.origin-eyebrow {
  font-size: var(--fs-tiny);
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 12px;
}
.origin-body {
  max-width: 62ch;
  margin-top: clamp(22px, 3vw, 32px);
  font-size: 1.0625rem;
  line-height: 1.75;
}
.origin-body > p + p { margin-top: 1.15em; }

.origin-quote {
  margin: clamp(28px, 3.4vw, 40px) 0;
  padding-left: clamp(20px, 2.4vw, 28px);
  border-left: 3px solid var(--teal);
}
.origin-quote p {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.2rem, 2.1vw, 1.65rem);
  line-height: 1.32;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.origin-sign {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-top: clamp(30px, 3.6vw, 44px);
}
.origin-sign-rule { flex: none; width: 44px; height: 2px; background: var(--teal); }
.origin-sign-name { font-weight: 500; color: var(--ink); }
.origin-sign-role { margin-top: 3px; font-size: var(--fs-tiny); color: var(--grey); }

/* --- the mark decode ----------------------------------------------------- */
.mark { padding: var(--band-y) 0; background: var(--surface-alt); }
.mark > .wrap > h2 { max-width: 22ch; }
.mark-head { max-width: 66ch; }

/* the four readings — two columns of hairline rows */
.mark-reads {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 clamp(28px, 4vw, 64px);
  margin-top: clamp(34px, 4vw, 54px);
  border-top: 1px solid var(--line);
}
@media (max-width: 720px) { .mark-reads { grid-template-columns: 1fr; } }
.mark-read {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 14px;
  align-items: start;
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}
.mark-read .hxm {
  width: 18px;
  height: 21px;
  margin-top: 3px;
  background: var(--teal);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
.mark-read p { font-size: var(--fs-small); line-height: 1.65; color: var(--ink); }
.mark-steps + .flag { margin-top: 22px; }

/* ==========================================================================
   48 ABOUT — SPACING FIXES SURFACED BY THE SECTION REORDER
   Two long-standing defects, visible once the story sections sat above them:
   the lineage block was an inline-styled div with no paragraph rule at all,
   and .work-copy set p + p but nothing around its h3, so "How we can help"
   collided with the paragraph either side of it.
   ==========================================================================*/
.lineage-copy { max-width: 76ch; }
.lineage-copy > p + p { margin-top: 1.1em; }
.work-copy > h3 { margin-top: 1.6em; margin-bottom: 0.5em; }
.work-copy > h3 + p { margin-top: 0; }

/* ==========================================================================
   49 ABOUT — THE STORY BEHIND BLAKEMERE
   Copy left as accordions, media rail right. The accordions are native
   <details>, reusing the .acc pattern from the capability pages, so there is
   no JavaScript and no state to lose. The section costs one screen instead of
   four; the name is open by default because it is the question people ask.

   The mark is a rendered reveal (images/blakemere-logo-reveal.mp4) on white,
   matching the plate it sits on; it plays once when it comes into view and
   holds the final frame. Reduced motion gets the still instead.
   ==========================================================================*/

.tale { padding: var(--band-y) 0; background: var(--surface-alt); }
.tale-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  gap: clamp(30px, 4.5vw, 76px);
  align-items: start;
  margin-top: clamp(26px, 3.4vw, 44px);
}
@media (max-width: 900px) { .tale-grid { grid-template-columns: 1fr; } }

.tale-copy .acc:first-child { border-top: 1px solid var(--line); }
.tale-copy .acc > summary { font-size: clamp(1.05rem, 1.7vw, 1.3rem); }
/* the shared .acc indents its body to clear the 01/02 numerals used on the
   capability pages; these accordions have no numerals, so pull it back */
.tale-copy .acc-body { padding-left: 0; display: flow-root; }  /* contains the float */
.tale-list { margin: 1.1em 0 0; padding-left: 1.15em; }
.tale-list li { margin-top: 0.55em; line-height: 1.6; }
.tale-hint {
  margin-top: 1.3em;
  padding-top: 1em;
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  color: var(--grey);
}

.tale-media { display: grid; gap: clamp(18px, 2.2vw, 26px); }
.tale-fig { margin: 0; }
.tale-ph {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  background: var(--surface);
  border: 1px dashed var(--line);
}
.tale-ph span {
  font-size: var(--fs-tiny);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--grey);
}
.tale-fig figcaption {
  margin-top: 10px;
  font-size: var(--fs-small);
  color: var(--ink);
}
.tale-fig-note {
  display: block;
  margin-top: 4px;
  font-size: var(--fs-tiny);
  line-height: 1.5;
  color: #8A6414;
}
.tale-fig--mark { background: var(--surface); padding: clamp(12px, 2vw, 22px); }

/* the animated mark: a 16:9 reveal on white, cropped square to the plate */
.bm-video, .bm-canvas-still {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
}
/* The mark fills about half the frame height; scale it to match the still
   (~85%). The overflow falls on the white plate, which the figure clips. */
.tale-fig--mark:has(.bm-video) { overflow: hidden; }
.bm-video { object-fit: cover; background: #FFFFFF; transform: scale(1.6); }
.bm-canvas-still { display: none; }

@media (prefers-reduced-motion: reduce) {
  .bm-video { display: none; }
  .bm-canvas-still { display: block; }
}

/* ==========================================================================
   51 ABOUT — MERGED EVIDENCE AND THE RECORD POINTER
   Ordering change: the page ran three consecutive sections of assertion before
   any evidence, and the capability tiles — the only block that sends people
   off the page — sat in the middle of the argument rather than at the end.
   Now: story, how we work, proof, where to see it, what to buy.

   No team section by decision: the company does not want its people on the
   page. Linden appears once, inside the answer about his father, because that
   passage is about him.
   ==========================================================================*/

/* Linden sits inside the answer that is about him and his father, rather than
   in the media rail — he appears when the reader opens that question, and the
   rail stays as the mockup had it: the hamlet, then the mark. */
.tale-portrait {
  float: right;
  width: clamp(130px, 34%, 190px);
  margin: 0 0 18px 24px;
}
.tale-ph--portrait { aspect-ratio: 3 / 4; }
.tale-portrait figcaption {
  margin-top: 9px;
  font-size: var(--fs-small);
  color: var(--ink);
}
@media (max-width: 560px) {
  .tale-portrait { float: none; width: 190px; margin: 0 0 20px; }
}

/* the award now shares a section with the accreditation rather than standing
   alone; the rule marks the join without starting a new band */
.award-grid--inset {
  margin-top: clamp(40px, 5vw, 68px);
  padding-top: clamp(34px, 4vw, 52px);
  border-top: 1px solid var(--line-dark);
}
.award-grid--inset h3 {
  margin-top: 18px;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
}

/* --- About: values in the story band, and the recognition band ----------- */
/* Every About heading carries a teal accent phrase, as on the home page.
   The map and contact bands are dark, so they take the bright teal. */
.map-block .accent, .cta-band .accent { color: var(--teal-bright); }
/* On the dark bands' headings the bright teal jumped too far from the
   teal-ink accents on the light bands either side, so those headings step
   down to the brand teal: 3.95:1 on anthracite, clear of the 3:1 large-text
   minimum. Body-size teal on dark (place names, figures) stays bright. */
h2 .accent--soft,
.capabilities h2 .accent--soft,
.map-block h2 .accent--soft,
.cta-band h2 .accent--soft { color: var(--teal); }
/* The four values moved out of the dark How We Work band into the light
   story band, under the timeline. */
.tale-values { margin-top: clamp(40px, 5vw, 64px); }
.tale-values .eyebrow { margin-bottom: 18px; }
/* The recognition band replaced the capability tiles. The Subsea Energy
   Australia award keeps its logo and photo layout; the two 2026 entries sit
   as a pair of linked cards beneath it. */
#awards .award-grid { margin-top: clamp(30px, 4vw, 48px); }
#awards .award-col h3 {
  margin-top: 18px;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
}
.award-pair {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(16px, 2vw, 24px);
  margin-top: clamp(34px, 4vw, 52px);
}
@media (max-width: 860px) { .award-pair { grid-template-columns: 1fr; } }
.award-card {
  display: flex;
  flex-direction: column;
  padding: clamp(18px, 2vw, 24px);
  background: var(--surface);
  border: 1px solid var(--line);
  color: inherit;
  text-decoration: none;
  transition: border-color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.award-card:hover { border-color: var(--teal); transform: translateY(-3px); }
.award-card h3 {
  margin-top: 20px;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
}
.award-card p { margin-top: 10px; font-size: var(--fs-body-sm); color: var(--grey); flex-grow: 1; }
.award-card .arrow { margin-top: 18px; }
/* Both cards open with a block the same height: the ZeroStab banner, and a
   typographic mark for the Engineers Australia nomination. */
/* Scoped to the card so it outranks the later .zs-card margin-top. */
.award-card .award-card-banner { margin-top: 0; }
.award-card-banner img { height: 200px; max-height: none; width: 100%; }
.award-card-mark {
  height: 200px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  padding: 0 clamp(18px, 2.4vw, 32px);
  background: var(--ink);
  color: #fff;
  /* Same cut corner as the .zs-card banner beside it */
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
}
.award-card-yr { font-family: var(--font-display); font-size: 2.6rem; line-height: 1; color: var(--teal-bright); }
.award-card-tag { font-family: var(--font-display); font-size: var(--fs-h4); text-transform: uppercase; letter-spacing: 0.06em; }
.award-card-org { font-size: var(--fs-tiny); color: #B9C1C6; }
@media (prefers-reduced-motion: reduce) { .award-card { transition: none; } .award-card:hover { transform: none; } }

.record-band { padding: var(--band-y) 0; background: var(--surface-alt); }
.record-band .work-copy > p + p { margin-top: 1.1em; }
.record-links {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: clamp(24px, 3vw, 34px);
}

/* --- Testing Centre: enlarged hero and the facility section --------------- */
/* The hero image was a 16:9 inset in the narrower of two columns. The banner
   photograph is the strongest asset on the page, so the image column now takes
   the larger share and the frame is 3:2 to match the source and stop the
   roller doors being cropped out of the bottom. */
.tf-hero .wrap { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
.tf-hero-img { aspect-ratio: 3 / 2; width: 100%; height: auto; object-fit: cover; }
@media (max-width: 860px) {
  /* Re-stated because the rule above sits after the original single-column
     media query and would otherwise keep the two-column grid on a phone. */
  .tf-hero .wrap { grid-template-columns: 1fr; }
  .tf-hero-img { aspect-ratio: 16 / 10; }
}

/* One frame for both photographs on this page, so the workshop interior and
   the frontage render at identical size regardless of their source aspect
   ratios (2.16:1 and 1.45:1 respectively). */
.tc-photo {
  display: block;
  width: 100%;
  height: auto;              /* the width/height attributes are presentational
                                hints; without this the height attribute wins
                                over aspect-ratio and the two frames differ */
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--surface-sunk);
}

.tf-floor { padding: var(--band-y) 0; background: var(--surface-alt); }
.tf-floor .intro { max-width: 62ch; margin-top: 14px; }
.tf-floor-copy h3 {
  margin-top: clamp(24px, 3vw, 34px);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
}
.tf-floor-copy h3 + p { margin-top: 10px; }
.tf-floor-fig { margin: 0; }
.tf-floor-fig .fig-cap { margin-top: 10px; }
/* The stat strip's default 8px top margin sits tight under the copy column;
   match the 40px it keeps below itself, before the pressure strip. */
.tf-floor .band-intro + .metrics--headline { margin-top: 40px; }

/* Four Testing Streams has no photo; keep the gap between its intro and the
   first stream that the old heading-and-photo grid used to provide. */
.tf-streams > .wrap > .intro { margin-bottom: clamp(28px, 3.5vw, 44px); }

/* --- Energy: the CSIRO direct air capture section ------------------------- */
/* Copy left, the two figures stacked right. The photograph is the evidence and
   the render explains the mechanism, so they sit together rather than being
   spread through the prose. */
.csiro-grid {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
  margin-top: clamp(24px, 3vw, 36px);
}
.csiro-copy .intro { font-size: var(--fs-lede); }
/* The site sets body paragraph rhythm with selectors scoped to section
   wrappers, which do not reach inside this grid child, so it is restated. */
.csiro-copy > p + p { margin-top: 1.1em; }
.csiro-copy h3 {
  margin-top: clamp(24px, 3vw, 34px);
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
}
.csiro-copy h3 + p { margin-top: 10px; }
.csiro-figs { display: grid; gap: clamp(18px, 2.5vw, 26px); }
.csiro-figs figure { margin: 0; }
.csiro-figs img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--surface-sunk);
}
.csiro-figs .fig-cap { margin-top: 8px; }

@media (max-width: 900px) {
  .csiro-grid { grid-template-columns: 1fr; }
  .csiro-figs { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) {
  .csiro-figs { grid-template-columns: 1fr; }
}

/* --- Energy: three-across icon row --------------------------------------- */
/* Reuses the .benefits component from the Testing Centre so the hexagon tiles,
   type and spacing stay identical across the site. Only the column count and
   the photo band below it are new. */
/* Doubled class rather than a single one: `.asked ul` earlier in the file is
   a class plus an element type (0,1,1) and outranks a lone class (0,1,0). It
   also sets its own gap, so that is restated here or the tiles bunch up. */
.benefits.benefits--three {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 40px);
}
@media (max-width: 860px) {
  .benefits.benefits--three { grid-template-columns: 1fr; }
}

.asked .intro { max-width: 60ch; margin-top: 12px; }
.asked-band { margin-top: clamp(34px, 4vw, 52px); }
.asked-band img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 21 / 9;
  object-fit: cover;
  background: var(--surface-sunk);
}

/* --- Energy: cross-reference to two published case studies ---------------- */
/* Not cards. These are pointers to further reading, so they get a rule and a
   sector label rather than card chrome, which would compete with the icon
   row further up the same page. */
.xref-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 56px);
  margin-top: clamp(26px, 3vw, 38px);
}
.xref { border-top: 2px solid var(--teal); padding-top: 18px; }
.xref-sector {
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
  margin-bottom: 8px;
}
.xref h3 { font-size: var(--fs-h4); margin-bottom: 10px; }
.xref h3 a { color: inherit; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.xref h3 a:hover { color: var(--teal-ink); }
.xref-meta { margin-top: 12px; font-size: var(--fs-tiny); color: var(--grey); }
@media (max-width: 760px) { .xref-grid { grid-template-columns: 1fr; } }

/* The three-across row sits on a white ground, where the card chrome from the
   Testing Centre version is invisible until hover and then pops. Flat here.
   The ::before reset needs two classes: `.asked ul li::before` earlier in the
   file is one class and three elements, which outranks a single class. */
.benefits.benefits--three > li::before { content: none; }
.benefits.benefits--three > li {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
  border-top: 2px solid var(--teal);
  padding-top: 18px;
  border-radius: 0;
}
.benefits.benefits--three > li:hover { box-shadow: none; transform: none; }


/* --- Mining page ---------------------------------------------------------- */
/* The page is text-led because there is no mining imagery in the library yet,
   so the work is done by band rhythm rather than photography. Three things are
   needed: one reading measure across every band, an alternating ground so two
   consecutive white sections do not read as one band with a hole in it, and a
   hero that does not reserve half its width for a photo that does not exist. */

/* `.stages > .wrap` takes the full 1240px wrap while `.prose-section > .wrap`
   is capped at 880px. Mixing the two on one page puts the headings on two
   different left edges, so the stages band is brought onto the same measure. */
.mining-page .stages > .wrap { max-width: 880px; }

.mining-page .prose-section--tint { background: var(--surface-sunk); }

/* `.ind-feature .wrap` is a two-column grid holding copy and a photo. With no
   photo the copy is stranded in the left half, so the band is collapsed to one
   column and given the same 880px measure as the rest of the page. */
.mining-page .ind-feature > .wrap { max-width: 880px; grid-template-columns: 1fr; }

/* Subheads inside a prose band need their own rhythm. The wrapper-scoped
   paragraph rule at 2241 covers p + p only, so an h3 following a paragraph
   otherwise sits hard against it. */
.mining-page .prose-section > .wrap > h3 {
  margin-top: clamp(30px, 3.2vw, 44px);
  margin-bottom: 10px;
}
.mining-page .prose-section > .wrap > h3:first-of-type { margin-top: clamp(24px, 2.6vw, 34px); }
.mining-page .prose-section > .wrap > h3 + p { margin-top: 0; }

/* `.ind-hero .wrap` is restored to two columns at 4296 for the photo slot. */
.mining-page .ind-hero .wrap { grid-template-columns: 1fr; }
.mining-page .ind-hero .wrap > div { max-width: 60ch; }

/* The three-across row keeps its icon tiles but the paragraph is pushed to the
   bottom of the tile by `.benefits p { margin-top: auto }` at 4586, which only
   reads well when the tiles are of similar length. */
.mining-page .benefits.benefits--three > li { align-content: start; }
.mining-page .benefits.benefits--three p { margin-top: 8px; }

/* Two reference photographs of the customer's existing arrangement, sat inside
   the 880px reading measure. Portrait source, so the shared .tc-photo frame is
   overridden from 16/10 to 4/5 rather than cropping the subject out. */
.mine-figs {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(20px, 2.6vw, 32px);
  margin: clamp(22px, 2.6vw, 30px) 0 clamp(8px, 1vw, 12px);
}
.mine-photo { aspect-ratio: 4 / 5; }
.mine-figs .fig-cap { margin-top: 10px; }
@media (max-width: 620px) { .mine-figs { grid-template-columns: 1fr; } }

/* --- Subsea & Offshore: the eight build categories ------------------------ */
/* Same card language as the Rentals fleet grid so the two read as one system,
   but the renders supplied for this page are square and sit on their own
   near-black ground, so the plate is 1:1 and filled rather than 16:10 and
   contained. Letterboxing a near-black render inside a light plate puts grey
   bars either side of it. */
.kit-block > .wrap { max-width: 1240px; }
.kit-lede { max-width: 74ch; margin-top: 14px; }
.kit-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 20px);
  margin-top: clamp(28px, 3vw, 40px);
}
@media (max-width: 1000px) { .kit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Held at two columns on a phone rather than dropping to one. Eight full-width
   square renders stacked added roughly 2,300px of scroll for no gain in
   legibility, since the card text is short. */
@media (max-width: 560px) {
  .kit-grid { gap: 10px; }
  .kit-card h3 { margin: 14px 14px 0; font-size: var(--fs-body-sm); }
  .kit-card .spec { margin: 5px 14px 0; }
  .kit-card p:not(.spec) { margin: 8px 14px 16px; }
}

.kit-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.kit-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lift); border-color: var(--teal); }

.kit-photo {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: #04120F;
}
.kit-card h3 {
  font-size: var(--fs-h4);
  text-transform: uppercase;
  letter-spacing: 0;
  margin: 18px 20px 0;
}
.kit-card .spec {
  margin: 6px 20px 0;
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
}
.kit-card p:not(.spec) {
  margin: 10px 20px 22px;
  font-size: var(--fs-tiny);
  line-height: 1.6;
  color: var(--grey);
}

/* The certification statement moved off the Subsea page as its own band and
   into the FAQ answer, where a reader goes looking for it. Verbatim copies of
   it, of the deliverables list and of the contracting paragraph already sit on
   capabilities.html and bespoke-engineering.html. Inside an accordion body the
   badge needs to be smaller than the 340px it takes in a full-width band. */
.cert-split--faq { align-items: start; gap: clamp(18px, 2.4vw, 32px); }
.cert-split--faq .cert-mark { width: clamp(150px, 18vw, 210px); }
.cert-split--faq > div > p + p { margin-top: 1.1em; }
@media (max-width: 760px) { .cert-split--faq .cert-mark { width: 180px; } }

/* --- Sectors hub ---------------------------------------------------------- */
/* The only links in the page body were three headings and the contact button.
   A styled H2 does not read as a route, so each sector block now ends in an
   explicit one. */
.sec-more {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: clamp(20px, 2.2vw, 28px);
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  padding-bottom: 3px;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.sec-more::after { content: '\2192'; transition: transform var(--dur-fast) var(--ease); }
.sec-more:hover { border-bottom-color: currentColor; }
.sec-more:hover::after { transform: translateX(4px); }
.on-dark .sec-more { color: var(--teal-bright); }

/* Marine and civil is not one of the three and has no page behind it, so it
   gets a single text band rather than the two-column photo treatment the
   sectors use. Giving it peer styling implied a fourth sector. */
.adjacent { padding: var(--band-y) 0; background: var(--surface-sunk); }
.adjacent > .wrap { max-width: 880px; }
.adjacent p { max-width: 74ch; }
.adjacent p + p { margin-top: 1.1em; }
.adjacent a { color: var(--teal-ink); text-decoration: underline; text-underline-offset: 3px; }

/* The low-commitment entry points were dressed as a fifth sector block, which
   buried the one section on the page whose job is conversion. */
.sec-block.start-small { background: var(--anthracite-deep); color: #D7DCDF; }
.sec-block.start-small h2 { color: #fff; }
.sec-block.start-small .sec-lead { color: #C7CDD0; }
.sec-block.start-small .sec-copy li { color: #C7CDD0; }

/* The sectors hero photograph was 508x350 while every sector block photograph
   below it was 505x347, so the hero led nothing. The column split is widened
   in the image's favour and the plate deepened, which puts the hero at roughly
   1.75 times the area of a block image without changing the two-column hero
   pattern the other sector and capability pages use. */
.sec-hero .wrap { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
.sec-hero .cap-photo { aspect-ratio: 16 / 10; }
@media (max-width: 860px) { .sec-hero .wrap { grid-template-columns: 1fr; } }

/* --- Bespoke engineering: buyer-route labelling --------------------------- */
/* "Who Tends to Bring It" splits the work into three buyer routes and the
   examples below now answer it one route at a time, so each worked example
   carries the route it came in through. */
.route-lede { max-width: 62ch; margin-bottom: clamp(22px, 2.4vw, 30px); }
.route-tag {
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
  margin-bottom: 8px;
}

/* Bespoke: the two process bands merged into one two-column band. Text-only
   bands on this page put their copy in the left column and left the right half
   empty, which was the flattest stretch of the page. */
.eng-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 4vw, 56px);
  margin-top: clamp(24px, 2.8vw, 34px);
}
.eng-grid h3 { font-size: var(--fs-h4); margin-bottom: 10px; }
.eng-grid > div > p + p { margin-top: 1.1em; }
@media (max-width: 820px) { .eng-grid { grid-template-columns: 1fr; } }

/* The strongest line on the bespoke page was the trailing sentence of a list.
   It is a statistic, so it is set as one: a dark plate against the light band,
   with the approximation kept as a kicker rather than dropped, because "two
   thirds" on its own reads as a counted figure and it is not one. */
.stat-block {
  margin: clamp(26px, 3vw, 36px) 0 0;
  padding: clamp(22px, 2.6vw, 30px) clamp(22px, 2.6vw, 30px) clamp(24px, 2.8vw, 32px);
  background: var(--anthracite-deep);
  color: #fff;
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
}
.stat-kicker {
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-bright);
  margin: 0 0 6px;
}
.stat-figure {
  font-size: clamp(2.25rem, 5.2vw, 3.5rem);
  line-height: 0.95;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  color: #fff;
  margin: 0;
}
.stat-block figcaption {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 2px solid var(--teal);
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: #C7CDD0;
  max-width: 40ch;
}

/* Photograph above the bespoke FAQ. The band lost its two-column photo when the
   prose became questions, and the page was down to two static images. */
.faq-band { margin: clamp(20px,2.4vw,28px) 0 clamp(28px,3vw,38px); }
.faq-band img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 21 / 8; object-fit: cover;
  background: var(--surface-sunk);
}

/* --- Sector and capability page layout fixes ------------------------------ */
/* Energy: the tidal turbine plate is held at the photograph's native 673x1100
   portrait ratio on purpose, because a landscape crop cuts the tower. But at
   full column width that made the plate 826px against 138 words of copy and the
   section 1,056px, a fifth of the page. The ratio and the full uncropped frame
   are kept; the plate is just capped and centred in its column. */
.ind-photo--tall {
  max-height: 560px;
  width: auto;
  margin-inline: auto;
}

/* Sectors: "Where We Have Worked" stacked its one sentence above a 479px map,
   making the section 915px for 39 words. Two columns puts the sentence and the
   legend beside the map, which is also where a reader looks for the key. */
.map-block > .wrap {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
}
@media (max-width: 900px) { .map-block > .wrap { grid-template-columns: 1fr; } }

/* Specification pairs, taken from the printed datasheets. A definition list
   rather than prose, because a reader checking whether their duty is covered
   is scanning for a term, not reading a paragraph. */
.spec-list { margin-top: clamp(24px, 2.8vw, 32px); }
.spec-list > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.7fr);
  gap: clamp(12px, 1.6vw, 22px);
  padding: 13px 0;
  border-top: 1px solid var(--line);
}
.spec-list > div:last-child { border-bottom: 1px solid var(--line); }
.spec-list dt { font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--ls-head); color: var(--teal-ink); }
.spec-list dd { margin: 0; font-size: var(--fs-body-sm); color: var(--grey); line-height: 1.5; }
@media (max-width: 620px) { .spec-list > div { grid-template-columns: 1fr; gap: 4px; } }

/* `.copy-split .split-img` crops to 16:11, which is right for a photograph and
   wrong for a technical render. The manifold is 1100x966 on a light ground, so
   it is shown whole and centred rather than cropped into. */
.copy-split .split-img.manifold-img {
  aspect-ratio: auto;
  height: auto;
  max-height: 480px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  margin-inline: auto;
}

/* --- DNV certification marks ---------------------------------------------- */
/* The legacy DNV·GL combined badge was replaced site-wide with the three
   current DNV marks. DNV's guideline requires the mark to appear in
   conjunction with the certified company's name or logo, so every placement
   now carries an owner line naming Blakemere Engineering directly above it. */
.cert-badges-row {
  display: flex;
  gap: clamp(12px, 1.6vw, 20px);
  flex-wrap: wrap;
  align-items: center;
}
.cert-badges-row img {
  width: clamp(76px, 9vw, 112px);
  aspect-ratio: 1 / 1;
  background: #fff;
  border-radius: 50%;
  padding: 10px;
  object-fit: contain;
  display: block;
}
.cert-owner {
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
  margin: 0 0 14px;
}
.cert-badges--named { margin-top: clamp(22px, 2.6vw, 30px); }
.cert-plate { display: flex; align-items: center; }
.cert-badges-row--faq img { width: clamp(64px, 7vw, 84px); }
.on-dark .cert-owner, .cap-band .cert-owner, .dark-band .cert-owner,
.capabilities .cert-owner, .proven-grid .cert-owner { color: #fff; }

/* --- Footer, unified ------------------------------------------------------ */
/* Was four different footers across 23 pages, most of them repeating the main
   navigation the header already carries, with LinkedIn and the capability
   statement both pointing at "#". One template now: identity and address,
   contact actions, social, and the legal links the site is required to expose
   once analytics and session recording are running. */
.foot-grid { grid-template-columns: minmax(0, 4fr) repeat(3, minmax(0, 3fr)); }
@media (max-width: 980px) { .foot-grid { grid-template-columns: 1fr 1fr; row-gap: 34px; } }
@media (max-width: 560px) { .foot-grid { grid-template-columns: 1fr; } }
.foot-brand .foot-addr { margin-top: 18px; }
.foot-col { display: flex; flex-direction: column; gap: 9px; }
.foot-head {
  font-size: var(--fs-tiny);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: #E7ECEE;
  margin: 0 0 5px;
}
.foot-col a { font-size: var(--fs-small); color: #A2ABB0; text-decoration: none; }
.foot-col a:hover { color: var(--teal-bright); }
.foot-pending { pointer-events: none; opacity: 0.55; }
.foot-pending span, .foot-pending-inline { font-size: var(--fs-tiny); color: #7C858A; }
.foot-brand .foot-addr + .foot-addr { margin-top: 14px; }
.foot-addr b { display: block; color: #C3CACE; font-weight: 500; margin-bottom: 3px; }

/* --- Legal pages ---------------------------------------------------------- */
.legal-body > .wrap { max-width: 780px; }
.legal-body h2 { font-size: var(--fs-h3); margin: clamp(34px, 4vw, 48px) 0 12px; }
.legal-body h2:first-of-type { margin-top: clamp(28px, 3vw, 36px); }
.legal-body p { max-width: 74ch; }
.legal-body p + p { margin-top: 1.05em; }
.legal-body .spec-list { margin: 20px 0 6px; }
.legal-meta {
  font-size: var(--fs-tiny); text-transform: uppercase; letter-spacing: var(--ls-head);
  color: var(--teal-ink); padding-bottom: 16px; border-bottom: 1px solid var(--line); margin-bottom: 26px;
}
.legal-contact { border-left: 2px solid var(--teal); padding-left: 18px; }
.legal-foot { margin-top: 26px; padding-top: 18px; border-top: 1px solid var(--line); font-size: var(--fs-body-sm); color: var(--grey); }
.legal-body a { color: var(--teal-ink); text-decoration: underline; text-underline-offset: 3px; }
/* Named example heading inside the evidence band. */
.ex-head { font-size: var(--fs-h4); margin: clamp(20px,2.2vw,26px) 0 10px; }
.ex-head + p { margin-top: 0; }
.ex-head a { color: inherit; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
.ex-head a:hover { color: var(--teal-ink); }

/* EDU case photographs, three across under the metrics strip. */
.edu-figs {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px);
  margin: clamp(28px, 3vw, 38px) 0 clamp(8px, 1vw, 12px);
}
.edu-figs img {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: cover;
  background: var(--surface-sunk);
}
.edu-figs .fig-cap { margin-top: 10px; }
.edu-lede { max-width: 74ch; }
@media (max-width: 760px) { .edu-figs { grid-template-columns: 1fr; } }

/* Defensive reset. The hex bullet is applied by wrapper-scoped rules on nine
   different containers, and a metrics strip dropped into any of them picked up
   a dot above the numeral. It showed on all seven case studies and on
   operations support. A metrics strip never takes a bullet. */
ul.metrics li::before, ul.metrics li::after { content: none; }
ul.metrics li { padding-left: 0; }

/* Two reference lists side by side rather than stacked. Each used half the
   width on its own, so the pair cost 1,590px to say what fits in ~950px.
   Collapsing them into accordions was the alternative and would have hidden
   the search vocabulary a buyer scans for. */
.range-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(32px, 4.5vw, 64px);
  align-items: start;
}
.range-grid > div > h2 { margin-bottom: 14px; }
.range-grid .spec-list { margin-top: 18px; }
.range-grid ul { margin: 16px 0 20px; }
/* The photograph sits in the plugging column at its own proportions. As a
   full-width 21:8 band it cost back most of the height the merge saved, and
   cropped a landscape bench shot into a strip. */
.range-col-img {
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 420px;
  margin: clamp(20px, 2.4vw, 28px) auto 0;
  background: var(--surface-sunk);
}
@media (max-width: 900px) { .range-grid { grid-template-columns: 1fr; row-gap: 40px; } }

/* The three decommissioning photographs were replaced with the CAD renders
   used on the subsea page. They are square sources, and the frames they landed
   in cropped them to three different aspects. Held at 1:1, contained rather
   than cropped, and capped so a short section is not swamped. */
/* Doubled class plus the element: `.copy-split .split-img` and the
   `.rental-feature` photo rules are two classes each, so a single class lost
   and the square renders were cover-cropped to 4:3, cutting the top and
   bottom off the tool. */
img.kit-render.kit-render {
  aspect-ratio: 1 / 1;
  object-fit: contain;
  width: auto;
  max-width: 100%;
  max-height: 400px;
  height: auto;
  display: block;
  margin-inline: auto;
  background: #04120F;
}

/* ============================================================
   45  INLINE PROSE LINKS ON DARK BANDS
   A text link inside .cap-band copy inherited the band's body
   colour (#D7DCDF) and read as ordinary prose, so the reader had
   no way of knowing it was a link. Matches the light-ground
   treatment at .test-link a, using the on-dark teal.
   Buttons are excluded so ghost and solid CTAs keep their own
   styling.
   ============================================================ */
.cap-band .wrap p a:not(.btn),
.dark-band .wrap p a:not(.btn),
.on-dark .wrap p a:not(.btn) {
  color: var(--teal-bright);
  border-bottom: 1px solid rgba(51, 214, 172, 0.45);
  transition: border-color var(--dur-fast) var(--ease);
}
.cap-band .wrap p a:not(.btn):hover,
.dark-band .wrap p a:not(.btn):hover,
.on-dark .wrap p a:not(.btn):hover { border-bottom-color: var(--teal-bright); }

/* ============================================================
   47  HEXTILE ON A LIGHT GROUND
   a.hextile h3 was set to #fff at a point when the tile only ever
   appeared on .capabilities or .dark-band. Moving the capabilities
   page's tile row onto a light band left three white headings on
   near-white, which is the same wrapper-scoped collision that hit
   the metrics strips and the kit renders. The white is now scoped
   to the dark wrappers and the light case gets its own colour.
   ============================================================ */
a.hextile h3 { color: var(--black); }
.capabilities a.hextile h3, .dark-band a.hextile h3, .on-dark a.hextile h3 { color: #fff; }
a.hextile:hover h3 { color: var(--teal-ink); }
.capabilities a.hextile:hover h3, .dark-band a.hextile:hover h3, .on-dark a.hextile:hover h3 { color: var(--teal-bright); }

/* ============================================================
   48  LIST MARKERS ON THE PLAIN DARK BANDS
   The teal hexagon marker is drawn by .acc-body ul li::before and
   .ind-feature ul li::before only. The .on-dark / .dark-band rule
   below it recolours a marker it assumes already exists, so a
   plain <ul> sitting straight inside .dark-band > .wrap rendered
   with no marker at all and the items ran together as prose.
   Pre-existing, visible on the Capabilities "Where to Start" list.
   Metrics strips stay excluded, as they do everywhere else.
   ============================================================ */
.dark-band > .wrap > ul:not(.metrics) > li,
.cap-band > .wrap > ul:not(.metrics) > li {
  position: relative;
  padding-left: 22px;
}
.dark-band > .wrap > ul:not(.metrics) > li::before,
.cap-band > .wrap > ul:not(.metrics) > li::before {
  content: '';
  position: absolute;
  left: 0; top: 0.52em;
  width: 9px; height: 10px;
  background: var(--teal-bright);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}
/* Copy that follows the list needs the band's own paragraph rhythm. */
.dark-band > .wrap > ul + p,
.cap-band > .wrap > ul + p { margin-top: 22px; }
/* A button following body copy on a plain dark band had no gap of its own. */
.dark-band > .wrap > p + .btn,
.cap-band > .wrap > p + .btn { margin-top: 26px; }

/* ============================================================
   49  ROUTES GRID — CAPABILITIES "WHERE TO START"
   Four low-commitment entry points across the full width of the
   band. The band's copy is capped at 72ch, which left roughly a
   third of it empty; the routes use that width rather than a
   photograph, because none of the four has an honest picture.
   ============================================================ */
.routes {
  margin-top: 30px;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(22px, 3vw, 44px) clamp(32px, 5vw, 72px);
  max-width: 1000px;
}
@media (max-width: 700px) { .routes { grid-template-columns: 1fr; } }
.route { padding-top: 16px; border-top: 1px solid rgba(255, 255, 255, 0.16); }
.route h3 {
  font-size: var(--fs-body);
  font-weight: 500;
  color: #fff;
  letter-spacing: 0;
  text-transform: none;
}
.route p { margin-top: 7px; font-size: var(--fs-body-sm); color: #AEB7BC; max-width: 46ch; }
.routes + p { margin-top: 30px; }
/* The plug-under-test plate is close to square, so the 16:11 band-intro frame
   would crop the tool. Squared off for this one instance. */
.testing-handoff .band-intro .split-img { aspect-ratio: 1 / 1; }

/* ============================================================
   50  CAREERS — EOI FORM AND LIGHT ROUTES
   The routes grid was written for the dark band on capabilities.
   The careers page uses it twice, once on light, so the light case
   gets its own colours rather than white text on near-white.
   ============================================================ */
.routes--light .route { border-top-color: var(--line); }
.routes--light .route h3 { color: var(--black); }
.routes--light .route p { color: var(--grey); }

.eoi-form { margin-top: 26px; max-width: 900px; }
.enq-options--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 700px) { .enq-options--2 { grid-template-columns: 1fr; } }

.file-fields {
  margin-top: 18px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px 24px;
}
.file-fields .field[hidden] { display: none; }
.file-fields input[type="file"] {
  width: 100%;
  padding: 11px 12px;
  border: 1px dashed rgba(38, 44, 49, 0.28);
  background: #fff;
  font-size: var(--fs-body-sm);
  color: var(--grey);
}
.file-fields input[type="file"]::file-selector-button {
  margin-right: 12px;
  padding: 7px 13px;
  border: 1px solid var(--line);
  background: var(--surface-alt);
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--teal-ink);
  cursor: pointer;
}
.file-fields input[type="file"]:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 2px; }

.field .req, .field .opt {
  margin-left: 8px;
  font-family: var(--font-mono);
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.field .req { color: var(--teal-ink); }
.field .opt { color: var(--grey); }

/* Running total against the 8 MB Netlify request limit. Turns amber as it
   approaches and red past it, because a silent failure at the upload timeout
   is the worst outcome for someone who has just attached a transcript. */
[data-eoi-size] { margin-top: 14px; font-family: var(--font-mono); font-size: var(--fs-eyebrow); letter-spacing: 0.1em; text-transform: uppercase; }
[data-eoi-size].is-warn { color: #9A6B12; }
[data-eoi-size].is-over { color: #A8322B; }

.eoi-form .field select {
  width: 100%;
  padding: 11px 12px;
  border: 1px solid var(--line);
  background: #fff;
  font-family: inherit;
  font-size: var(--fs-body-sm);
  color: var(--black);
}

/* ============================================================
   51  CAREERS EOI FORM ON A LIGHT GROUND
   The contact form's light treatment is entirely scoped to
   .contact-panel, so a form outside that wrapper inherits the
   dark-ground defaults: pale labels, transparent inputs, a
   bordered fieldset and an invisible legend. Same wrapper-scoped
   collision as the hextile headings and the metrics strips.
   ============================================================ */
.eoi-form .enq-set { border: 0; padding: 0; margin: 0 0 6px; }
.eoi-form .enq-legend {
  color: var(--ink);
  text-align: left;
  font-size: var(--fs-h4);
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  margin: 0 0 16px;
  padding: 0;
}
.eoi-form .enq-options { gap: 12px; margin-bottom: 0; }
.eoi-form .enq-option label { background: var(--surface-alt); border: 1.5px solid var(--line); }
.eoi-form .enq-option label:hover { border-color: var(--line-teal); }
.eoi-form .enq-option input:checked + label { border-color: var(--teal); background: rgba(0, 175, 134, 0.07); }
.eoi-form .enq-option .eo-title { color: var(--black); }
.eoi-form .enq-option .eo-sub { color: var(--grey); }

.eoi-form .field label { color: var(--grey); }
.eoi-form .field input, .eoi-form .field textarea {
  background: var(--surface);
  border: 1.5px solid var(--line);
  color: var(--ink);
}
.eoi-form .field input:focus, .eoi-form .field textarea:focus { border-color: var(--teal); outline: none; }

/* These hints always apply, unlike the contact form's conditional reveals,
   so they are not held at zero opacity waiting for an is-shown class. */
.eoi-form .field-hint { opacity: 1; max-height: none; color: var(--grey); }
.eoi-form .contact-submit { text-align: left; }
.eoi-form fieldset + .contact-fields { margin-top: 22px; }

/* ============================================================
   52  DIMENSION STRIP, HEADINGS ON ONE BASELINE
   The ISO panel's label always runs to two lines while its
   neighbours run to one, so the subheadings started at different
   heights and the strip read as misaligned. Present on the home,
   rentals and careers strips. Line-height on the label is 1, so
   two ems is exactly two lines. Released on a single-column phone
   layout, where there is nothing to align against.
   ============================================================ */
/* Reserving two ems on every label fixed the home and rentals strips, where
   the ISO panel genuinely runs to two lines, and broke the careers strip, where
   no label does. Every title there sat at the bottom of an empty reserved line,
   which read as the whole strip being pushed off centre.

   Subgrid does the job properly. The labels share one row and the captions
   share another, both sized to the tallest in the strip, so the baselines line
   up when something wraps and nothing is reserved when nothing does. The 2em
   reservation stays as the fallback for engines without subgrid. */
.hero-foot b {
  min-height: 2em;
  display: flex;
  align-items: flex-end;
}
@media (max-width: 460px) { .hero-foot b { min-height: 0; display: block; } }

@supports (grid-template-rows: subgrid) {
  @media (min-width: 461px) {
    .hero-foot .wrap { grid-template-rows: auto auto; grid-auto-rows: auto; }
    .hero-foot .wrap > div {
      display: grid;
      grid-template-rows: subgrid;
      grid-row: span 2;
    }
    .hero-foot b { min-height: 0; align-self: end; }
    .hero-foot span { align-self: start; }
  }
}

/* Careers hero: a second, quieter line under the lede, then the call to
   action. The page's whole job is to make applying feel available even when
   nothing is advertised, so the invitation sits above the fold rather than
   eight sections down. */
.cap-head .cap-sub {
  margin-top: 14px;
  max-width: 58ch;
  font-size: var(--fs-body-sm);
  color: var(--grey-light);
}
.cap-head .cap-sub + .btn { margin-top: 24px; }
.sub-hero .lede + .btn { margin-top: 24px; }

/* ============================================================
   53  CAREERS STREAM CARDS AND SCROLL TARGETS
   The two cards at the top of the careers page were text with a
   link buried in the sentence. The whole card is the affordance,
   so it is now the anchor. Scroll targets get a margin so the
   sticky header does not sit over the heading it just jumped to.
   ============================================================ */
a.route--link { display: block; color: inherit; text-decoration: none; }
a.route--link:hover { border-top-color: var(--teal-ink); }
a.route--link:hover h3 { color: var(--teal-ink); }
a.route--link h3 { transition: color var(--dur-fast) var(--ease); }
a.route--link .arrow { margin-top: 16px; }
a.route--link:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 4px; }

#students, #experienced, #register { scroll-margin-top: 96px; }
/* The collection line under the careers form inherited the contact form's
   centred, pale treatment, which is scoped to .contact-panel. */
.eoi-form .form-note {
  text-align: left;
  max-width: 74ch;
  margin-top: 22px;
  color: var(--grey);
}
.eoi-form .form-note + .contact-submit { margin-top: 22px; }

/* ============================================================
   54  CLIENT TESTIMONIAL
   Carried across from the current site, where all three are
   published with full attribution. A named person at a named
   operator is the strongest evidence a services site can hold,
   and none of the competitor set publishes one, so the mark is
   quiet and the attribution does the work.
   The year slot exists because an undated quote attributed to an
   operator implies a current relationship. Both light and dark
   grounds are covered, since these sit on three different pages.
   ============================================================ */
.pull-quote {
  margin: clamp(28px, 3.5vw, 44px) 0 0;
  padding: 26px 0 0;
  border-top: 2px solid var(--teal);
  max-width: 74ch;
}
.pull-quote blockquote { margin: 0; }
.pull-quote p {
  margin: 0;
  font-size: clamp(1.0625rem, 1.35vw, 1.1875rem);
  line-height: 1.6;
  color: var(--black);
}
.pull-quote p + p { margin-top: 0.9em; }
.pull-quote figcaption {
  margin-top: 18px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--grey);
  line-height: 1.6;
}
.pull-quote figcaption b { display: block; color: var(--teal-ink); font-weight: 500; }

/* On the dark bands */
/* The logos band is a light ground, so only the genuinely dark wrappers are
   listed here. Getting this wrong put white text on near-white. */
.cap-band .pull-quote p, .dark-band .pull-quote p, .on-dark .pull-quote p { color: #E4E8EA; }
.cap-band .pull-quote figcaption, .dark-band .pull-quote figcaption,
.on-dark .pull-quote figcaption { color: var(--grey-light); }
.cap-band .pull-quote figcaption b, .dark-band .pull-quote figcaption b,
.on-dark .pull-quote figcaption b { color: var(--teal-bright); }

/* Centred variant for the homepage, where it sits above the logo wall */
.pull-quote--centre { margin-inline: auto; text-align: center; border-top: 0; padding-top: 0; }
.pull-quote--centre::before {
  content: '';
  display: block;
  width: 56px; height: 2px;
  margin: 0 auto 26px;
  background: var(--teal);
}

/* ============================================================
   55  THE BENEFITS COMPONENT NEVER TAKES A LIST MARKER
   .benefits items carry their own icon, so a hex bullet sits
   redundantly beside it. Two resets already existed but the hex
   bullet rule for prose lists outscored them on specificity
   wherever .benefits was dropped inside .asked, .prose-section
   or .ind-feature, which is why the dots reappeared on subsea,
   mining and energy. The component is now excluded at source in
   the same way .metrics is, and this is the backstop.
   ============================================================ */
ul.benefits > li::before, ul.benefits > li::after { content: none; }
/* The indent that went with the hex bullet is set by the prose-list rules at
   2297, which now exclude .benefits at source, so nothing here needs to zero
   padding-left. An earlier backstop did, and because it outscored the card
   rule at 4579 it stripped the left inset off every benefits card, which read
   as the box being cropped down its left edge. Do not reinstate it. */

/* ============================================================
   56  CERTIFICATION ATTRIBUTION ON A DARK BAND
   .cert-owner defaults to --teal-ink, which is drawn for light
   grounds. The dark override listed .on-dark, .cap-band and
   .dark-band but not .capabilities, so on the about page the
   line "Blakemere Engineering is certified by DNV" was dark
   green on dark grey and close to unreadable. It is now white
   on every dark ground, which suits a statement of fact better
   than an accent colour would.
   ============================================================ */

/* ============================================================
   57  BOXED CARD VARIANTS
   Rev 2 feedback: the two career streams and the two cross-
   referenced solutions on bespoke read as text with a rule above
   them rather than as things to click. Boxing them makes the
   choice explicit without introducing a new component, so both
   reuse the grids they already sit in.
   ============================================================ */
.routes--boxed .route,
.xref-grid--boxed .xref {
  padding: clamp(22px, 2.4vw, 30px);
  background: #fff;
  border: 1px solid var(--line);
  border-top: 2px solid var(--teal);
  clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%);
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease);
}
.routes--boxed .route { padding-top: clamp(20px, 2.2vw, 26px); }

a.route--link.route:hover,
.xref-grid--boxed .xref:hover {
  border-color: var(--line-teal);
  border-top-color: var(--teal);
  box-shadow: var(--shadow-lift);
  transform: translateY(-2px);
}
.xref-grid--boxed .xref h3 { margin-top: 0; }
.routes--boxed .route h3 { margin-top: 0; }

/* ============================================================
   58  ONWARD LINKS, THE .k AND .t SPANS
   The component was styled for .eyebrow and <strong>, which is
   the markup the case study pages use. Seven other pages use
   .k and .t, which nothing styled, so both spans rendered inline
   with no separation and the link read "NextRentals". Same
   treatment either way, so the two markups now match.
   ============================================================ */
/* Rev 3.6: the colours were the wrong way round. The teal belongs on the
   destination, which is what the reader is deciding about; "Next" and "Back
   to" are labels and should sit back. */
.onward .k {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey);
}
.onward .t {
  display: block;
  margin-top: 10px;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
  color: var(--teal-ink);
}
.onward > a:hover .t { color: var(--teal); }
.on-dark .onward .k, .dark-band .onward .k, .cap-band .onward .k { color: #9AA4A9; }
.on-dark .onward .t, .dark-band .onward .t, .cap-band .onward .t { color: var(--teal-bright); }

/* ============================================================
   59  THE CANVAS BEHIND THE PAGE IS THE FOOTER'S COLOUR

   Reported symptom: a tall blank band below the footer on the
   staging host, on every page, which does not occur when the
   files are served on their own. The pages are being rendered
   inside a container taller than the document, so the space
   is the container, not the page.

   First attempt made the body a full-height flex column with
   the footer pushed to the end. That pinned the footer to the
   bottom of the container correctly, but the space had to go
   somewhere and it went into main, so the gap simply moved
   above the footer, which looked worse. Reverted.

   The space cannot be removed from a container the document
   cannot see, so make it invisible instead. Any area of the
   viewport not covered by the document paints the canvas, and
   the canvas takes the html background in preference to the
   body's. Setting html to the footer's own colour means an
   over-tall container reads as the footer continuing rather
   than as the page having stopped early. Both ends are dark,
   the header as well as the footer, so overscroll at the top
   behaves the same way.

   Nothing changes when the page is served normally, because
   the document covers the canvas completely.
   ============================================================ */
html { background: var(--black); }
body { background: var(--surface); }

/* ============================================================
   60  BENEFITS CARDS, BODY COPY TOP-ALIGNED

   4589 sets `margin-top: auto` on the paragraph so the bottom
   edges of the body copy line up across a row of equal-height
   cards. With varying text lengths something has to be ragged,
   and putting the rag at the bottom means a short paragraph
   floats away from its own heading, which reads as a fault
   rather than as alignment. On Testing Centre the first card
   sat 25px lower than the other three for that reason.

   Top-aligned instead, so every heading is followed by its
   paragraph at the same distance and the rag falls at the
   bottom of the card where the eye does not track it.
   Mining sets its own spacing at 5627 and is unaffected.
   ============================================================ */
.benefits p { margin-top: 14px; }

/* ============================================================
   61  ONE FRAME FOR EVERY HERO PHOTOGRAPH

   Seven pages carry a photograph in the hero. They had grown
   four different treatments. Capabilities, Rentals and Sectors
   wrapped the image in .cap-photo and so picked up the corner
   registration marks. Energy used .ind-photo, which was never
   in the marks selector. About, Subsea and Testing Centre put
   a bare <img> in the grid cell, and a bare <img> cannot carry
   a pseudo-element, so those three could never have the marks
   at all. Measured ratios ran 1.33, 1.45, 1.50 and 1.60, and
   Subsea was set to object-fit: fill, which stretched the
   photograph rather than cropping it.

   The three bare images are now wrapped in .hero-frame and the
   frame, not the image, carries the styling. Every hero photo
   is 16:11, cover-fitted and marked. 16:11 because four of the
   seven were already there and it is the ratio the feature
   images elsewhere on the site use.
   ============================================================ */
.hero-frame {
  position: relative;
  overflow: hidden;
  width: 100%;
  background: var(--surface-sunk);
}
.hero-frame > img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* One ratio, stated last so the historic per-page overrides do not win. */
.page-hero .hero-frame, .sub-hero .hero-frame, .tf-hero .hero-frame,
.cap-hero .cap-photo, .sub-hero .cap-photo, .sec-hero .cap-photo,
.ind-hero .ind-photo { aspect-ratio: 16 / 11; }

@media (max-width: 860px) {
  .page-hero .hero-frame, .sub-hero .hero-frame, .tf-hero .hero-frame,
  .cap-hero .cap-photo, .sub-hero .cap-photo, .sec-hero .cap-photo,
  .ind-hero .ind-photo { aspect-ratio: 16 / 10; }
}

/* The corner marks, extended to the two treatments that never had them.
   :has(img) so a placeholder panel is not framed as though it were a photo. */
.hero-frame::before, .ind-hero .ind-photo:has(img)::before {
  content: '';
  position: absolute;
  z-index: 2;
  top: 12px; left: 12px;
  width: 22px; height: 22px;
  border-top: 2px solid var(--teal);
  border-left: 2px solid var(--teal);
  opacity: 0.85;
}
.hero-frame::after, .ind-hero .ind-photo:has(img)::after {
  content: '';
  position: absolute;
  z-index: 2;
  bottom: 12px; right: 12px;
  width: 22px; height: 22px;
  border-bottom: 2px solid var(--teal);
  border-right: 2px solid var(--teal);
  opacity: 0.85;
}

/* Same column split as well, or the frames match in shape and still differ in
   size. Five heroes ran 610/508 with the copy in the larger column. Sectors ran
   466/652, which left its copy column narrower than any other page on the site.
   Testing Centre ran 508/610, reversed on purpose so the workshop photograph
   led the page. Reversing it back is one line if the team prefers it that way. */
.page-hero .wrap, .cap-hero .wrap, .ind-hero .wrap,
.sub-hero .wrap, .sec-hero .wrap, .tf-hero .wrap {
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
}
@media (max-width: 900px) {
  .page-hero .wrap, .cap-hero .wrap, .ind-hero .wrap,
  .sub-hero .wrap, .sec-hero .wrap, .tf-hero .wrap { grid-template-columns: 1fr; }
}


/* 62 THE THREE GATES ARE NOT A SECOND PROCESS
   mining.html used to present a three-stage FEED in accordions identical to the
   six delivery stages on capabilities.html, both numbered from 01. Mapped, the
   three are the six with two pairs merged and stage 06 absent, so a reader who
   saw both pages saw two processes and no way to reconcile them.

   The six are the work. The gates are the commercial decisions laid across
   the work. This map is what makes that legible in one look. */
.gatemap { margin: 34px 0 0; }
.gatemap-grid { display: flex; flex-direction: column; gap: 10px; }
.gm-row {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 10px;
}
.gm-stage {
  background: var(--surface-sunk, #F1F4F4);
  border-top: 2px solid var(--teal);
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
  padding: 14px 14px 18px;
  min-height: 92px;
  font-size: var(--fs-small);
  line-height: 1.28;
  font-weight: 500;
  color: var(--ink);
}
.gm-n {
  display: block;
  color: var(--teal-ink);
  font-size: var(--fs-eyebrow);
  letter-spacing: 0.12em;
  margin-bottom: 6px;
}
/* Stage 06 is outside the gates, so it reads as outside them. */
.gm-stage--out {
  background: transparent;
  border-top: 2px dashed var(--rule, #C9D0D2);
  color: var(--grey);
}
.gm-stage--out .gm-n { color: var(--grey); }
.gm-gate {
  position: relative;
  isolation: isolate;
  color: var(--black);
  padding: 13px 15px 16px;
  min-height: 68px;
  font-size: var(--fs-small);
  line-height: 1.3;
}
/* The fill carries the cut corners on its own layer. A clip-path on the gate
   itself would also clip the leader below, which sits outside the box. */
.gm-gate::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--teal);
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 10px 100%, 0 calc(100% - 10px));
}
/* A leader from the cut corner up to the stage above marks the stage the
   gate closes on. */
.gm-gate::after {
  content: '';
  position: absolute;
  right: 0;
  top: -10px;
  width: 3px; height: 20px;
  background: var(--teal);
}
.gm-gate b {
  display: block;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: var(--fs-eyebrow);
  margin-bottom: 5px;
}
.gm-out {
  padding: 13px 2px 16px;
  min-height: 68px;
  font-size: var(--fs-tiny);
  line-height: 1.3;
  color: var(--grey);
  border-top: 1px dashed var(--rule, #C9D0D2);
}
.gatemap-cap {
  margin-top: 14px;
  font-size: var(--fs-small);
  color: var(--grey);
}
/* Six columns will not hold on a phone. Stages stack in pairs and each gate
   takes the full width, which keeps the grouping without the grid. */
@media (max-width: 860px) {
  .gm-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gm-gates .gm-gate, .gm-gates .gm-out { grid-column: 1 / -1 !important; }
  /* Stacked, the gate no longer sits under the stage it closes on. */
  .gm-gate::after { display: none; }
}


/* ============================================================
   63  ABOUT REV 1
   Lineage timeline, people grid, map statistics and the partner
   block. All four are about-page only, so they live together at
   the end rather than being threaded into the shared components.
   ============================================================ */

/* --- Lineage ------------------------------------------------ */
.lineage { margin-bottom: clamp(34px, 4vw, 54px); }
.lineage-lede {
  font-size: var(--fs-body);
  color: var(--ink);
  max-width: 74ch;
}
.lineage-steps {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0;
  margin: clamp(24px, 3vw, 36px) 0;
  border-top: 1px solid var(--line);
}
.lineage-step {
  padding: 22px 26px 24px 0;
  border-top: 3px solid var(--line);
  margin-top: -1px;
}
.lineage-step + .lineage-step { padding-left: 26px; border-left: 1px solid var(--line); }
.lineage-step--now { border-top-color: var(--teal); }
.lineage-yr {
  display: block;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey);
  margin-bottom: 9px;
}
.lineage-step--now .lineage-yr { color: var(--teal-ink); }
.lineage-step h3 {
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: 0;
  margin-bottom: 9px;
}
.lineage-step p {
  font-size: var(--fs-body-sm);
  color: var(--grey);
  line-height: 1.6;
}
.lineage > p + p { margin-top: 1.1em; }
.lineage > p:not(.lineage-lede):not(.insert-note) {
  font-size: var(--fs-body-sm);
  color: var(--grey);
  max-width: 74ch;
}
@media (max-width: 780px) {
  .lineage-steps { grid-template-columns: 1fr; }
  .lineage-step { padding: 20px 0 22px; }
  .lineage-step + .lineage-step { padding-left: 0; border-left: 0; }
}

/* --- People ------------------------------------------------- */
.people {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(18px, 2.4vw, 30px);
  margin-top: clamp(24px, 3vw, 34px);
}
.person { margin: 0; }
.person-ph {
  position: relative;
  aspect-ratio: 3 / 4;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 16px;
  background:
    repeating-linear-gradient(45deg,
      rgba(0, 175, 134, 0.05) 0 8px,
      rgba(0, 175, 134, 0.11) 8px 16px);
  border: 1px dashed var(--line-teal);
}
.person-ph span {
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--grey);
}
.person figcaption { padding-top: 15px; border-top: 3px solid var(--teal); margin-top: 14px; }
.person h3 {
  font-size: var(--fs-h4);
  text-transform: uppercase;
  letter-spacing: 0;
  margin-bottom: 3px;
}
.person-role {
  font-size: var(--fs-tiny);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 10px;
}
.person figcaption p.person-bio {
  font-size: var(--fs-body-sm);
  color: var(--grey);
  line-height: 1.6;
}
/* The photograph sits over its own placeholder and removes itself if the file
   is missing, so an unsupplied portrait falls back to the hatched box rather
   than to a browser broken-image icon. */
.person-ph img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}
.person-bio { margin-bottom: 12px; }
.person-li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  text-decoration: none;
}
.person-li:hover { color: var(--teal-dim); text-decoration: underline; }
@media (max-width: 1100px) { .people { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* The photograph sits over its own placeholder and removes itself if the file
   is missing, so an unsupplied portrait falls back to the hatched box rather
   than to a browser broken-image icon. */
.person-ph img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}
.person-bio { margin-bottom: 12px; }
.person-li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  text-decoration: none;
}
.person-li:hover { color: var(--teal-dim); text-decoration: underline; }
@media (max-width: 1100px) { .people { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* The photograph sits over its own placeholder and removes itself if the file
   is missing, so an unsupplied portrait falls back to the hatched box rather
   than to a browser broken-image icon. */
.person-ph img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}
.person-bio { margin-bottom: 12px; }
.person-li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  text-decoration: none;
}
.person-li:hover { color: var(--teal-dim); text-decoration: underline; }
@media (max-width: 1100px) { .people { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* The photograph sits over its own placeholder and removes itself if the file
   is missing, so an unsupplied portrait falls back to the hatched box rather
   than to a browser broken-image icon. */
.person-ph img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
}
.person-bio { margin-bottom: 12px; }
.person-li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  text-decoration: none;
}
.person-li:hover { color: var(--teal-dim); text-decoration: underline; }
@media (max-width: 1100px) { .people { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 860px) { .people { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .people { grid-template-columns: 1fr; } }

/* --- Map statistics ----------------------------------------- */
.map-block > .wrap--flat { display: block; }
.map-block > .wrap + .wrap { margin-top: clamp(34px, 4vw, 52px); }
.map-stats {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  border-top: 1px solid var(--line-dark);
}
.map-stats li {
  padding: 20px 22px 20px 0;
  border-bottom: 1px solid var(--line-dark);
}
.map-stats li + li { padding-left: 22px; border-left: 1px solid var(--line-dark); }
.map-stats .n {
  display: block;
  font-size: clamp(1.5rem, 3vw, 2.4rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--teal-bright);
  margin-bottom: 8px;
}
.map-stats .k {
  display: block;
  font-size: var(--fs-tiny);
  line-height: 1.4;
  color: #AEB7BC;
}
@media (max-width: 860px) {
  .map-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .map-stats li:nth-child(odd) { padding-left: 0; border-left: 0; }
  .map-stats li:nth-child(even) { padding-left: 22px; border-left: 1px solid var(--line-dark); }
}

/* --- Partner block ------------------------------------------ */
.partner {
  border-top: 3px solid var(--teal);
  padding-top: clamp(20px, 2.4vw, 28px);
  max-width: 82ch;
}
.partner h3 {
  font-size: var(--fs-h3);
  text-transform: uppercase;
  letter-spacing: 0;
  margin: 6px 0 14px;
}
.partner p { font-size: var(--fs-body-sm); color: #D0D6D9; line-height: 1.65; }
.partner p + p { margin-top: 1em; }


/* Team sits between two dark bands, so it is light. Four dark bands running
   into each other made How We Work, the team, the map and the certifications
   read as one section a screen and a half long. */
.people-band { padding: var(--band-y) 0; background: var(--surface-alt); }

/* ============================================================
   64  WORKED MAP, ANIMATED
   Light trails run out from Perth once, when the section
   scrolls into view. .is-in is added by the same reveal
   observer the rest of the site uses and is never removed, so
   this plays once per page load and then holds its end state.

   Every animation uses fill-mode forwards, which matters under
   prefers-reduced-motion: the global block clamps duration to
   0.001s, so the trails and pins land instantly instead of
   never appearing at all.
   ============================================================ */

.js .wm-routes .wm-trail,
.js .wm-routes .wm-comet,
.js .wm-pins .wm-pin { opacity: 0; }

.wm-trail {
  stroke: #00E0AC;
  stroke-width: 0.9;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
.wm-comet {
  stroke: #BFFFEC;
  stroke-width: 1.5;
  stroke-dasharray: 0.05 1;
  stroke-dashoffset: 1.05;
}

/* The trail draws and settles to a faint line. The comet head runs the same
   path a touch faster and leaves nothing behind. */
@keyframes wm-draw {
  0%   { opacity: 0;    stroke-dashoffset: 1; }
  8%   { opacity: 0.85; }
  100% { opacity: 0.28; stroke-dashoffset: 0; }
}
@keyframes wm-comet {
  0%   { opacity: 0;   stroke-dashoffset: 1.05; }
  10%  { opacity: 0.95; }
  88%  { opacity: 0.95; }
  100% { opacity: 0;   stroke-dashoffset: 0; }
}
@keyframes wm-land {
  0%   { opacity: 0; }
  60%  { opacity: 1; }
  100% { opacity: 1; }
}
@keyframes wm-halo {
  0%   { r: 2.6; opacity: 0.9; }
  100% { r: 13;  opacity: 0; }
}

.map-block.is-in .wm-trail {
  animation: wm-draw 2.4s cubic-bezier(0.36, 0.24, 0.2, 1) var(--d, 0s) forwards;
}
.map-block.is-in .wm-comet {
  animation: wm-comet 2.25s cubic-bezier(0.36, 0.24, 0.2, 1) var(--d, 0s) forwards;
}
.map-block.is-in .wm-pin {
  animation: wm-land 0.55s ease-out var(--d, 0s) forwards;
}

@media (prefers-reduced-motion: reduce) {
  .wm-routes .wm-trail { opacity: 0.28 !important; stroke-dashoffset: 0 !important; }
  .wm-routes .wm-comet { opacity: 0 !important; }
  .wm-pins .wm-pin { opacity: 1 !important; }
  .wm-halo { opacity: 0 !important; }
  .wm-home circle { animation: none !important; }
}
@media print {
  .wm-routes .wm-trail { opacity: 0.4 !important; stroke-dashoffset: 0 !important; }
  .wm-routes .wm-comet { display: none !important; }
  .wm-pins .wm-pin { opacity: 1 !important; }
}

/* ============================================================
   65  ONWARD NAV, TIGHTER BAND
   The next-page nav sits in a full content band on every
   capability page, so a 140px navigation block was carrying
   115px of padding above and below it and reading as a hole
   before the footer. The track record page already used a
   tighter rule. This brings the rest into line.
   ============================================================ */
section.cap-body:has(> .wrap > .onward:last-child) {
  padding-top: var(--band-y-sm);
  padding-bottom: var(--band-y-sm);
}

/* ============================================================
   66  CAREERS, THE TWO-STREAM FORK
   The pair sat in a grid capped at 1000px inside a 1176px band,
   so two cards floated left of centre with a column of empty
   space beside them and read as an afterthought rather than as
   the choice the page is asking the reader to make.

   A modal was considered and rejected. Two audience routes are
   navigation, and a modal costs the deep link, adds a click,
   traps focus, and behaves badly on a phone. The honest fix is
   to let the fork occupy the band it is in.
   ============================================================ */
.routes--boxed {
  max-width: none;
  gap: clamp(18px, 2vw, 28px);
  align-items: stretch;
}
.routes--boxed .route {
  display: flex;
  flex-direction: column;
}
.routes--boxed .route h3 {
  font-size: var(--fs-h3);
  letter-spacing: -0.005em;
}
.routes--boxed .route p {
  max-width: 52ch;
  flex: 1 1 auto;
  margin-top: 10px;
}
/* The arrow is the affordance. It moves on hover so the card reads as a
   destination rather than as a panel that happens to be underlined. */
.routes--boxed a.route--link .arrow {
  margin-top: 20px;
  font-weight: 500;
  transition: transform var(--dur-fast) var(--ease);
}
.routes--boxed a.route--link:hover .arrow { transform: translateX(4px); }
@media (max-width: 700px) { .routes--boxed { gap: 16px; } }

/* The fork is one row of two cards, so it takes the tighter band scale for
   the same reason the onward nav does. */
section.cap-body:has(> .wrap > .routes--boxed:only-child) {
  padding-top: var(--band-y-sm);
  padding-bottom: var(--band-y-sm);
}

/* ============================================================
   67  MOBILE LENGTH
   Two changes that shorten a phone scroll without narrowing
   any body copy. Card grids carrying paragraphs are left in one
   column on purpose: two columns at 390px gives roughly 25
   characters a line, which trades scrolling for unreadability.
   ============================================================ */

/* Eight portraits at one a row is the single longest block on the
   site. Name, title and a link do not need a full-width column. */
@media (max-width: 520px) {
  .people { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  .person figcaption { padding-top: 12px; margin-top: 11px; }
}

/* The band scale bottoms out at 64px on a phone, which is generous for a
   layout that is already one column. Whitespace only, no content moves. */
@media (max-width: 560px) {
  :root { --band-y: 48px; }
}

/* The values grid on About was pinned to two columns with an inline style, so
   it stayed two columns on a phone and each card ran at about twenty
   characters a line. Two on a tablet, one on a phone. */
.cap-grid--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 640px) { .cap-grid--pair { grid-template-columns: minmax(0, 1fr); } }


/* ============================================================
   68  REV 2.5 PHONE TWEAKS
   ============================================================ */

/* Addresses open in maps. Underlined only on hover so the footer does not
   turn into a block of links, and the whole two-line address is the target
   rather than a fiddly one-word hit area on a phone. */
.addr-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid transparent;
}
.addr-link:hover, .addr-link:focus-visible { color: var(--teal-bright); }
.detail-card .addr-link:hover, .detail-card .addr-link:focus-visible { color: var(--teal-ink); }

/* The enquiry form was behind a Get in touch button that sat directly under a
   phone number and an email address, so it offered a third route to the same
   thing. Button gone, form shown. */
.contact-step-2 { display: block; }


/* ============================================================
   69  CASE STUDY LIBRARY, REV 2.5
   ============================================================ */

/* Several scopes predate the management buy-out and were delivered as Proserv
   Australia. The note says so once, at the foot of the write-up, rather than
   qualifying every sentence in it. */
.cs-attrib {
  margin-top: clamp(28px, 3vw, 40px);
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--grey);
}


/* A ledger entry that has a long version elsewhere says so at the foot of the
   panel rather than repeating it. */
.acc-more {
  margin: clamp(20px, 2.4vw, 30px) 0 0;
  font-size: var(--fs-body-sm);
}
.acc-more a {
  color: var(--teal-ink);
  text-decoration: none;
  border-bottom: 1px solid rgba(0, 175, 134, .38);
  padding-bottom: 2px;
}
.acc-more a:hover, .acc-more a:focus-visible { border-bottom-color: var(--teal); }


/* ============================================================
   70  BODY PROSE LINKS
   ============================================================ */

/* Cross-links inside body copy were inheriting body colour with no underline,
   so a reader had no way of knowing they were links. Colour comes from two
   custom properties rather than from a pile of overrides, because the dark
   bands nest and specificity fights are how this breaks later. A band sets
   the pair, everything inside it inherits.

   Breadcrumbs, buttons, address links and the accordion read-more already
   have their own treatment. */
main p:not(.acc-more)
  > a:not(.btn):not(.addr-link):not(.arrow) {
  color: var(--link-ink, var(--teal-ink));
  text-decoration: none;
  border-bottom: 1px solid var(--link-rule, rgba(0, 175, 134, .38));
  padding-bottom: 1px;
}
main p:not(.acc-more)
  > a:not(.btn):not(.addr-link):not(.arrow):hover,
main p:not(.acc-more)
  > a:not(.btn):not(.addr-link):not(.arrow):focus-visible {
  border-bottom-color: var(--link-ink, var(--teal));
}

/* Teal-ink is a light-background colour, 5.4:1 on white. On anthracite it
   disappears, so every dark band swaps in the bright teal. */
.tr-head, .hero, .page-hero, .cta-band, .cap-band, .map-block,
.contact-band, .detail-card, .band--black, .on-dark, .capabilities,
.sec-block.start-small, .bento-cell--dark {
  --link-ink: var(--teal-bright);
  --link-rule: rgba(51, 214, 172, .45);
}


/* ============================================================
   71  CATALOGUE ENQUIRY
   ============================================================ */

/* The tile is a button now, so the browser default has to go before the
   drawing-title-block styling can survive. */
button.ct-tile {
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  appearance: none;
}
button.ct-tile:focus-visible {
  outline: 2px solid var(--teal-bright);
  outline-offset: 2px;
}

/* The affordance. Nothing on the tile said it was clickable, so the prompt
   appears in the space the drift already leaves under the discipline. */
.ct-ask {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--teal-bright);
  opacity: 0;
  transform: translateY(3px);
  transition: opacity var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.ct-tile:hover .ct-ask,
.ct-tile:focus-visible .ct-ask { opacity: 1; transform: none; }

/* The wall pauses for the mouse already. It has to pause for the keyboard as
   well, or tabbing through drags the focused tile off the screen. */
.ct-stage:focus-within .ct-track { animation-play-state: paused; }

/* --- the dialog ---------------------------------------------------------- */
.ask {
  /* The global reset zeroes margin on everything, which also kills the user
     agent's `margin: auto` on a modal dialog and pins it to the top left. */
  margin: auto;
  width: min(560px, calc(100vw - 32px));
  max-height: calc(100dvh - 32px);
  padding: 0;
  border: 1px solid var(--line);
  background: #fff;
  color: var(--ink);
  box-shadow: 0 30px 80px rgba(19, 22, 25, .35);
}
.ask::backdrop { background: rgba(19, 22, 25, .72); }
.ask-inner { padding: clamp(24px, 4vw, 40px); }
.ask-inner h2 { margin: 6px 0 0; font-size: clamp(22px, 2.4vw, 28px); }
.ask-lede { margin: 14px 0 0; color: var(--grey); font-size: var(--fs-body-sm); line-height: 1.55; }
.ask-form { margin-top: clamp(20px, 2.6vw, 28px); }

.ask-x { position: absolute; top: 0; right: 0; }
.ask-x button {
  width: 44px; height: 44px;
  border: 0; background: none; cursor: pointer;
  font-size: 24px; line-height: 1; color: var(--grey);
}
.ask-x button:hover { color: var(--ink); }

.ask-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 16px; }
@media (max-width: 520px) { .ask-grid { grid-template-columns: minmax(0, 1fr); } }

.ask .fld { margin: 0 0 16px; }
.ask .fld label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 7px;
}
.ask .fld .opt { color: var(--grey); text-transform: none; letter-spacing: 0; }
.ask .fld input, .ask .fld textarea {
  width: 100%;
  padding: 11px 13px;
  font: inherit;
  font-size: var(--fs-body-sm);
  color: var(--ink);
  background: var(--surface-alt);
  border: 1px solid var(--line);
  border-radius: 0;
}
.ask .fld input:focus, .ask .fld textarea:focus {
  outline: 2px solid var(--teal-ink);
  outline-offset: -1px;
  background: #fff;
}
.ask .btn { margin-top: 4px; }
.ask-err {
  margin: 0 0 14px;
  padding: 10px 13px;
  font-size: var(--fs-body-sm);
  color: #8A2317;
  background: #FDF0EE;
  border-left: 3px solid #C0392B;
}
.ask-fine { margin: 16px 0 0; font-size: var(--fs-small); color: var(--grey); }
.ask-fine a { color: var(--teal-ink); }
.ask-done h2 { margin-top: 6px; }
.ask-done .btn { margin-top: 22px; }


/* --- 71.1  enquiry nature, urgency and the reference --------------------- */

/* The select has to match the text inputs, which means overriding the native
   control completely and drawing the chevron. */
.ask .fld select {
  width: 100%;
  padding: 11px 38px 11px 13px;
  font: inherit;
  font-size: var(--fs-body-sm);
  color: var(--ink);
  background-color: var(--surface-alt);
  border: 1px solid var(--line);
  border-radius: 0;
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1.5 6 6.5 11 1.5' fill='none' stroke='%2300795A' stroke-width='1.6'/></svg>");
  background-repeat: no-repeat;
  background-position: right 13px center;
}
.ask .fld select:focus {
  outline: 2px solid var(--teal-ink);
  outline-offset: -1px;
  background-color: #fff;
}
.ask .fld select:invalid { color: var(--grey); }

.ask-urgent {
  margin: -4px 0 16px;
  padding: 11px 13px;
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  color: var(--ink);
  background: rgba(0, 175, 134, 0.09);
  border-left: 3px solid var(--teal);
}
.ask-urgent a { color: var(--teal-ink); font-weight: 500; white-space: nowrap; }

/* The reference is read out over the phone, so it is set in the mono face at
   a size that survives a bad line and a noisy deck. */
.ask-ref {
  margin: 22px 0 0;
  padding: 14px 16px;
  background: var(--surface-alt);
  border-left: 3px solid var(--teal);
}
.ask-ref span {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 5px;
}
.ask-ref b {
  font-family: var(--font-mono);
  font-size: 19px;
  letter-spacing: 0.06em;
  color: var(--ink);
}
.ask-ref--page {
  display: inline-block;
  text-align: left;
  margin: 0 0 26px;
  background: rgba(255, 255, 255, 0.06);
}
.ask-ref--page b { color: #fff; }
/* The eyebrow kept the light-background teal on a dark band, which left it at
   1.4:1 against the hero. */
.ask-ref--page span { color: var(--teal-bright); }


/* --- 71.2  the reference on the form ------------------------------------- */

/* Shown before anything is sent so the reader can write it down, and posted
   with the form so the team quote the same string. Read only, but selectable,
   because the first thing anyone does with a reference is copy it. */
.ask-refbox {
  margin: 0 0 20px;
  padding: 13px 15px;
  background: var(--surface-alt);
  border-left: 3px solid var(--teal);
}
.ask-refbox > label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  margin-bottom: 7px;
}
.ask-refbox > div { display: flex; gap: 8px; align-items: stretch; }
.ask-refbox input {
  flex: 1 1 auto;
  min-width: 0;
  padding: 8px 11px;
  font-family: var(--font-mono);
  font-size: 17px;
  letter-spacing: 0.06em;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 0;
  cursor: default;
}
.ask-refbox input:focus { outline: 2px solid var(--teal-ink); outline-offset: -1px; }
.ask-copy {
  flex: 0 0 auto;
  padding: 0 15px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-ink);
  background: none;
  border: 1px solid var(--teal);
  cursor: pointer;
}
.ask-copy:hover { background: var(--teal); color: #fff; }
.ask-copy:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 2px; }
.ask-refbox p {
  margin: 9px 0 0;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--grey);
}
@media (max-width: 420px) {
  .ask-refbox input { font-size: 16px; }
  .ask-copy { padding: 0 12px; }
}


/* --- 72  404 ------------------------------------------------------------- */

/* The not-found page reuses the capability card as a link, so it needs the
   anchor reset the div version never wanted. */
a.cap-card { text-decoration: none; color: inherit; display: block; transition: border-color var(--dur-fast) var(--ease); }
a.cap-card:hover { border-color: var(--teal); }
a.cap-card:focus-visible { outline: 2px solid var(--teal-ink); outline-offset: 2px; }
a.cap-card h3 { color: var(--teal-ink); }


/* --- 73  HERO CALL TO ACTION --------------------------------------------- */

/* The hero carried a headline and a lede and nothing to act on, so a reader
   who arrived ready to talk had to go hunting in the navigation. Two routes:
   one for someone who wants to start, one for the larger number who want
   evidence first. */
.hero-cta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: clamp(24px, 3vw, 34px);
  max-width: none;
}
/* The hero constrains its children to the graded panel on the left. The row
   itself must not be constrained or the second button drops to a new line
   before it needs to. */
.hero-content .wrap > .hero-cta { max-width: none; }

@media (max-width: 420px) {
  /* Side by side these two shrink below a comfortable tap target, so on a
     narrow phone they stack and go full width. */
  .hero-cta { gap: 10px; }
  .hero-cta .btn { width: 100%; justify-content: center; }
}

/* A short phone screen. 140px of top padding is a quarter of a 568px viewport
   and it pushed the buttons under the fold, which is the one thing this
   section was added to avoid. */
@media (max-height: 720px) and (max-width: 899px) {
  .hero-content { min-height: 0; padding-top: 96px; padding-bottom: 36px; }
  .hero-cta { margin-top: 20px; }
}

/* Shorter again, an original iPhone SE and the like. The type comes down a
   step so the pair of buttons still lands inside the first screen. */
@media (max-height: 620px) and (max-width: 899px) {
  .hero-content { padding-top: 70px; padding-bottom: 24px; }
  .hero h1 { font-size: 1.8rem; }
  .hero .lede { font-size: 0.94rem; }
  .hero-cta { margin-top: 14px; }
}


/* ============================================================
   74  COOKIE CONSENT
   ============================================================ */

/* A bar across the foot rather than a modal. Nothing here is important enough
   to block the page on, and a reader who ignores it is not consenting, which
   is the correct outcome. */
.cc {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 900;
  background: var(--anthracite-deep);
  border-top: 2px solid var(--teal);
  color: #D7DCDF;
  box-shadow: 0 -14px 40px rgba(19, 22, 25, .28);
}
.cc-inner {
  max-width: var(--wrap, 1280px);
  margin: 0 auto;
  padding: clamp(14px, 2vw, 20px) clamp(18px, 4vw, 40px);
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 40px);
}
.cc-title {
  margin: 0 0 4px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-bright);
}
.cc-copy p:last-child {
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.5;
  max-width: 78ch;
}
.cc-copy a { color: var(--teal-bright); }
.cc-actions { display: flex; gap: 10px; flex: 0 0 auto; margin-left: auto; }
.cc .btn { white-space: nowrap; }
.cc .btn--ghost { color: #fff; border-color: rgba(255, 255, 255, .42); }
.cc .btn--ghost:hover { border-color: var(--teal); background: var(--teal); color: #fff; }

@media (max-width: 760px) {
  .cc-inner { flex-direction: column; align-items: stretch; gap: 14px; }
  .cc-actions { margin-left: 0; }
  .cc-actions .btn { flex: 1 1 0; justify-content: center; }
}


/* --- 74.1  the choose panel ---------------------------------------------- */

.cc-toggle {
  margin-top: 9px;
  padding: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--teal-bright);
  background: none;
  border: 0;
  border-bottom: 1px solid rgba(51, 214, 172, .45);
  cursor: pointer;
}
.cc-toggle:hover { border-bottom-color: var(--teal-bright); }
.cc-toggle:focus-visible { outline: 2px solid var(--teal-bright); outline-offset: 3px; }

.cc-choices { border-top: 1px solid rgba(255, 255, 255, .14); }
.cc-inner--choices { align-items: flex-end; padding-top: clamp(14px, 1.8vw, 20px); }
.cc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; flex: 1 1 auto; }
@media (min-width: 761px) { .cc-list { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; } }
.cc-list label {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: #fff;
  cursor: pointer;
}
.cc-list li:first-child label { cursor: default; }
.cc-list input { width: 17px; height: 17px; accent-color: var(--teal); cursor: inherit; }
.cc-list span {
  display: block;
  margin-top: 5px;
  padding-left: 26px;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: #A2ABB0;
}


/* --- 75  TESTING CENTRE ENVELOPE ----------------------------------------- */

/* The floor metrics at the top of this section describe the building. These
   describe what can be put through it, so they sit with the pressure copy
   rather than folded into the same strip, where the two sets would dilute
   each other. Inherits the standard stacked metrics list; only the spacing
   changes, because it sits between two subheadings rather than alone. */
.tf-envelope { margin: 20px 0 4px; }


/* ============================================================
   77  REV 3.5 — DESIGNER FEEDBACK
   ============================================================ */

/* White cards on the anthracite band read as patches rather than a set.
   Outlined, light type, equal heights, tighter padding. */
.capabilities .cap-card--ghost {
  background: none;
  border: 1px solid rgba(255, 255, 255, 0.2);
  min-height: 0;
  padding: clamp(22px, 2.4vw, 30px);
}
.capabilities .cap-card--ghost h3 { color: var(--teal-bright); margin-bottom: 12px; }
.capabilities .cap-card--ghost p {
  color: #B9C2C7;
  font-size: var(--fs-body-sm);
  line-height: 1.65;
}
.capabilities .cap-card--ghost:hover {
  border-color: var(--teal);
  transform: none;
  box-shadow: none;
}

/* Three metrics were sitting in a four-column grid, which is where the empty
   panel at the end of the row came from. */
.map-stats { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 760px) {
  .map-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* The two legend swatches were near-identical greens, and neither matched
   anything on the map: the home base and the site pins were both white dots,
   and what actually signals a completed scope is the shaded country. So the
   key now shows the two marks that genuinely differ — a white marker at Perth
   and the shading itself. */
.map-legend i { width: 11px; height: 12px; }
.map-legend i.sw-area {
  width: 16px;
  height: 11px;
  clip-path: none;
  background: rgba(0, 175, 134, 0.55);
  border: 1px solid rgba(0, 175, 134, 0.95);
}

/* The note about the turning model now sits under the animation it describes,
   so the short rule that floated above the longer block has gone. */
.tale-fig--mark figcaption {
  margin-top: 12px;
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--grey);
}

/* Outline buttons were losing the chopped corner: clip-path cuts the corner
   but a border cannot follow the diagonal, so the cut read as a gap. This
   draws the missing edge. Half of it falls outside the clip, so it is set at
   two pixels to render as one. */
.btn--ghost { --btn-line: var(--teal); border-color: var(--btn-line); }
.btn--ghost::before {
  content: '';
  position: absolute;
  top: 4px;
  right: -2.1px;
  width: 14.2px;
  height: 2px;
  background: var(--btn-line);
  transform: rotate(45deg);
  transform-origin: center;
  pointer-events: none;
}
.cap-band .btn--ghost, .hero .btn--ghost, .cc .btn--ghost,
.capabilities .btn--ghost { --btn-line: rgba(255, 255, 255, 0.42); }
.btn--ghost:hover { --btn-line: var(--teal); }
.btn--pending::before { content: none; }

/* Same defect on the catalogue filter chips, which are the other bordered
   control with a cut corner. Their corner is 8px rather than 10px, so the
   diagonal is correspondingly shorter. */
.ct-chip { --btn-line: rgba(255, 255, 255, 0.18); border-color: var(--btn-line); }
.ct-chip:hover { --btn-line: var(--line-teal); }
.ct-chip[aria-pressed="true"] { --btn-line: var(--teal); }
.ct-chip::before {
  content: '';
  position: absolute;
  top: 3px;
  right: -1.7px;
  width: 11.3px;
  height: 2px;
  background: var(--btn-line);
  transform: rotate(45deg);
  transform-origin: center;
  pointer-events: none;
}
.ct-chip { position: relative; }

/* The MANSAM note sat at 82ch in a full-width band, leaving the right half of
   the section empty — the dead run the designer marked. Split across the same
   4/7 rhythm the map above uses, and the band closes up. */
.partner--split {
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.partner--split h3 { margin-top: 6px; }
.partner-lede { font-size: var(--fs-body); color: #D7DCDF; }
.partner-body p:first-child { margin-top: 0; }
@media (max-width: 860px) {
  .partner--split { grid-template-columns: 1fr; gap: 18px; }
}

/* And the run between the metrics and that note was doing nothing. */
.map-block > .wrap--flat + .wrap--flat { margin-top: clamp(26px, 3vw, 40px); }
.map-stats li { padding-top: 18px; padding-bottom: 18px; }

/* The How We Work intro ran two long paragraphs down a narrow left column and
   left the right half of the band empty. Heading on the left, copy on the
   right, on the same 4/7 rhythm as the map section. */
.rule-head--split {
  /* .rule-head caps at 46ch and --wide at 62ch, which is right for a single
     column and wrong for a split one. */
  max-width: none;
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.rule-head--split > div > p { max-width: 68ch; }
.rule-head--split > div > p:first-child { margin-top: 0; }
.rule-head--split > div > p + p { margin-top: 1.1em; }
@media (max-width: 860px) {
  .rule-head--split { grid-template-columns: 1fr; gap: 16px; }
}

/* ============================================================
   79  REV 3.6 — CATALOGUE DIALOG ARTWORK
   ============================================================ */

/* Only the seven diamond wire saws have a render today. The rest of the
   catalogue opens exactly as before rather than showing an empty frame, so
   the slot is hidden unless site.js finds a file for that reference. */
.ask-fig {
  margin: 0 0 clamp(14px, 2vw, 20px);
  padding: clamp(10px, 1.6vw, 18px);
  background: var(--surface-alt);
  border: 1px solid var(--line);
  clip-path: polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
}
.ask-fig[hidden] { display: none; }
.ask-fig img {
  display: block;
  width: 100%;
  max-height: 210px;
  object-fit: contain;
}

/* ============================================================
   80  REV 3.6 — HOW WE WORK, AS STEPS

   The two long paragraphs and the split heading were doing the job of a
   diagram. Six marks, one line of copy, then the four value cards.
   ============================================================ */

.hw-steps {
  list-style: none;
  margin: clamp(26px, 3.5vw, 44px) 0 clamp(30px, 4vw, 50px);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 18px);
  counter-reset: hw;
}
.hw-steps li {
  position: relative;
  padding: clamp(16px, 2vw, 22px) clamp(10px, 1.2vw, 16px);
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #D7DCDF;
  text-align: center;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
}
/* The steps run left to right, so a hairline between them reads as sequence
   rather than as six unrelated boxes. */
.hw-steps li + li::before {
  content: '';
  position: absolute;
  left: calc(-1 * clamp(10px, 1.4vw, 18px) - 1px);
  top: 50%;
  width: clamp(10px, 1.4vw, 18px);
  height: 1px;
  background: rgba(255, 255, 255, 0.22);
}
/* Rev 3.6b: the six pictograms are gone. Four of them could have sat on any
   engineering company's website and one of them repeated the company mark, so
   the row now uses the hexagon numeral already used by the accordions, and
   spends the space it saved on a line of copy per step. */
.hw-num {
  display: grid;
  place-items: center;
  margin: 0 auto clamp(10px, 1.3vw, 14px);
  width: 34px;
  height: 39px;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  background: rgba(0, 175, 134, 0.24);
  color: var(--teal-bright);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.04em;
}
.hw-step { display: block; }
.hw-note {
  display: block;
  margin: clamp(8px, 1vw, 11px) auto 0;
  max-width: 24ch;
  font-size: 12.5px;
  line-height: 1.45;
  letter-spacing: 0;
  text-transform: none;
  color: #A2ABB0;
}

@media (max-width: 1100px) {
  .hw-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .hw-steps li + li::before { display: none; }
}
@media (max-width: 620px) {
  .hw-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .hw-note { font-size: 12px; }
}

/* Rev 3.6: the completeness note under the record. */
.rec-more {
  margin-top: clamp(22px, 3vw, 34px);
  padding-top: 16px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  line-height: 1.55;
  color: var(--grey);
}


/* Rev 3.6b: the three options open the operations support page, so the list
   sits closer than a full specification table would. */
.spec-list--tight > div { padding-block: clamp(10px, 1.2vw, 14px); }
.spec-list--tight dt { white-space: nowrap; }
@media (max-width: 560px) {
  .spec-list--tight dt { white-space: normal; }
}


/* ============================================================
   OPERATIONS SUPPORT, the opening section.
   The heading spans the band, the intro sits beside the photograph, and the
   three routes an operator can take run across the full width. Putting them
   in a narrow column made a two-line answer wrap to four.
   ============================================================ */
.ops-intro {
  display: grid;
  grid-template-columns: minmax(0, 6fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: start;
}
.ops-intro > div > p { margin: 0; }
.ops-intro > div > p + p { margin-top: 1.1em; }

/* EDU photographs stacked beside the copy rather than paired beneath it. */
.edu-figs--stack { grid-template-columns: minmax(0, 1fr); margin-top: 0; }

/* The three routes stack beside the photograph rather than running across
   underneath it. Three across left the copy column short and the routes
   stranded below the image.

   No markers. The house bullet is a 9px teal hexagon and three of them stacked
   beside three teal rules turned a plain argument into decoration. The rows are
   separated by hairlines instead, and the third route is the only one set at
   full contrast, so the eye lands on it because it is the one the page is
   about, not because it has been flagged. */
.ops-routes {
  list-style: none;
  margin: clamp(22px, 2.6vw, 32px) 0 0;
  padding: 0;
  /* Matches the reading measure the paragraphs are held to, so when the grid
     collapses the rules do not run wider than the copy above them. */
  max-width: 72ch;
  border-top: 1px solid var(--line);
}
/* The shared bullet rule carries two :not() classes, so an override needs
   four classes to outrank it. Three of them counted, and the hexagons
   stayed. */
.cap-body ul.ops-routes:not(.metrics):not(.benefits) li::before { content: none; }
.cap-body ul.ops-routes:not(.metrics):not(.benefits) li {
  padding-left: 0;
  max-width: none;
  margin-top: 0;
}
.ops-routes li {
  /* The shared list rule indents 26px for the hexagon and caps the measure at
     a reading width. Neither applies here: there is no marker, and the rules
     have to line up with the paragraph above and with each other. */
  padding: clamp(13px, 1.5vw, 18px) 0;
  border-bottom: 1px solid var(--line);
}
/* All three terms carry the same teal-ink the site already uses for term
   labels in .spec-list. An earlier version put the teal on the third route
   only, to mark the one Blakemere does. That invented a colour code the site
   does not otherwise use, and the sentence directly below already says "the
   third is our work", so the colour was saying it twice and reading as an
   accident instead of an emphasis. */
.ops-routes b {
  display: block;
  margin-bottom: 5px;
  font-size: var(--fs-tiny);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
}
.ops-routes span {
  display: block;
  font-size: var(--fs-body-sm);
  line-height: 1.55;
  color: var(--grey);
}

.ops-third { margin-top: clamp(30px, 3.4vw, 46px); max-width: 68ch; }

/* Seven short items read better in two columns than as one long stack. */
.ops-outcomes { columns: 2; column-gap: clamp(28px, 4vw, 64px); }
.ops-outcomes li { break-inside: avoid; }

@media (max-width: 900px) {
  .ops-intro { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 760px) {
  .ops-outcomes { columns: 1; }
}


/* The open bore shear section runs copy across the top and the two
   photographs side by side beneath it, rather than the usual image-and-copy
   split. .wrap is the grid in a rental feature, so the flat variant has to opt
   out of it, and the copy needs a reading measure it would otherwise lose at
   full width. */
.rental-feature > .wrap--flat { display: block; }
/* Rev 3.7: the open bore shear comparison stacks instead of pairing.
   Side by side and full width it ran the two photographs at 571px against
   505px for every other photograph on the page, and left the right half of
   the band empty with a hole beneath it. Stacked in the photograph column of
   the standard feature grid, the two figures land at the same 505 by 347 as
   the rest of the page and the copy fills the other half.

   .fig-pair and .obs-copy are gone. Both existed only for this section. */
.fig-stack {
  display: grid;
  gap: clamp(20px, 2.4vw, 30px);
  align-content: start;
}
.fig-stack > .figure { margin: 0; }
.fig-stack > .figure > img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  background: var(--surface-sunk);
}
.fig-stack .fig-cap { margin-top: 10px; }


/* ==========================================================================
   81  REV 3.7 — BAND RHYTHM, THE MARK, THE GENERAL EDU SECTION

   Three things in this block.

   Band rhythm. About and Sectors both ran four dark sections end to end from
   the world map down, so the bottom half of each page read as one slab rather
   than as sections. Two sections on each page move to a light ground. The
   dark styling on both pages hung off .capabilities and .sec-block.start-small,
   which are background hooks as much as layout hooks, so the light case needs
   its own class rather than an override of theirs.

   The mark. The animated logo sat under the accordions in a column of its own
   with an explanatory caption. It now fills the empty half of the row beside
   the lineage paragraph, which is where the eye already goes, and the caption
   has gone with it.

   The EDU section. It was written around one delivered job, numbers and
   photographs included. It is now the general offering, and the numbers and
   the job stay in the case study where they can be attributed.
   ========================================================================== */

/* --- About: the mark, raised ---------------------------------------------- */
.lineage-head {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  gap: clamp(26px, 4vw, 68px);
  align-items: center;
}
/* The mark is square. Left to fill a four-column track it stands taller than
   the paragraph beside it and drags a band of white above the copy, so it is
   capped and pushed to the right edge of its track. */
.lineage-head .tale-fig--mark {
  margin: 0 0 0 auto;
  width: 100%;
  max-width: 310px;
}
@media (max-width: 860px) {
  .lineage-head { grid-template-columns: 1fr; gap: clamp(18px, 4vw, 28px); }
  .lineage-head .tale-fig--mark { max-width: 260px; }
}
/* With the media column gone the accordions take the full measure. Their
   bodies already cap at 72ch, so nothing runs long. */
.tale-grid { display: block; }

/* The band behind the story is now white, so the plate the mark sits on has
   to be the grey, or it disappears. */
.tale { background: var(--surface); }
.tale-fig--mark { background: var(--surface-alt); }

/* Country names carry the same teal as the map legend's "countries with
   completed scopes" swatch, so the sentence and the shading read as one
   statement. 6.0:1 on the anthracite ground. */
.map-block .geo { color: var(--teal-bright); }

/* --- A capability band on a light ground ---------------------------------- */
.cap-light      { padding: var(--band-y) 0; background: var(--surface); }
.cap-light--alt { background: var(--surface-alt); }
/* .proven-grid .iso-item and .proven-grid .cert-owner were written
   unconditionally for the dark band, so both need answering here. */
.cap-light .iso-item {
  background: var(--surface-alt);
  border-left-color: var(--teal);
  color: var(--ink);
}
.cap-light .iso-item p         { color: var(--grey); }
.cap-light .iso-item .iso-code { color: var(--teal-ink); }
.cap-light .cert-owner         { color: var(--teal-ink); }
.cap-light .award-grid--inset  { border-top-color: var(--line); }
/* The DNV marks are white discs. On a white band they need an edge. */
.cap-light .cert-badges-row img { border: 1px solid var(--line); }

/* --- Sectors: two bands off the dark -------------------------------------- */
.sec-block.on-alt { background: var(--surface-alt); }
.sec-block.start-small {
  background: var(--surface);
  color: var(--ink);
  --link-ink: var(--teal-ink);
  --link-rule: rgba(0, 175, 134, .38);
}
.sec-block.start-small h2 { color: var(--black); }
.sec-block.start-small .sec-lead,
.sec-block.start-small .sec-copy li { color: var(--grey); }

/* --- Operations support: two EDU photographs instead of three ------------- */
.edu-figs--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 760px) {
  .edu-figs--pair { grid-template-columns: 1fr; }
}

/* --- Subsea tooling grid: every category opens the enquiry dialog --------- */
/* The whole card is the hit area, matching the home page catalogue wall. The
   button inside it is what makes that reachable from a keyboard and what
   gives the control its accessible name. */
.kit-card { cursor: pointer; }
.kit-card p:not(.spec) { margin-bottom: 14px; }
.kit-ask {
  appearance: none;
  -webkit-appearance: none;
  background: none;
  border: 0;
  padding: 0;
  margin: auto 20px 20px;           /* auto holds it to the foot of the card */
  align-self: flex-start;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-family: inherit;
  font-size: var(--fs-tiny);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--ls-head);
  color: var(--teal-ink);
  cursor: pointer;
}
.kit-ask > span[aria-hidden] { transition: transform var(--dur-fast) var(--ease); }
.kit-card:hover .kit-ask > span[aria-hidden] { transform: translateX(4px); }
.kit-ask:focus-visible { outline: 2px solid var(--teal); outline-offset: 4px; }
@media (max-width: 560px) {
  .kit-ask { margin: auto 14px 14px; }
}

/* --- Two contrast failures found in the rev 3.7 sweep --------------------- */
/* Both pre-date this revision. The tool reference beside a scope ran at
   3.6:1 on white and the selected case study chip at 4.0:1 on teal, against
   4.5:1 for text this size. Neither is a design change: the reference keeps
   its size and the chip keeps its fill, the ink just gets darker. */
.rec-eq        { color: var(--grey); }        /* 3.62:1 -> 5.9:1  */
.cs-chip.is-on { color: var(--black); }       /* 3.95:1 -> 6.6:1  */
/* The home page enquiry form. --grey-light is documented at 4.6:1 "on
   anthracite", but measured against --anthracite (#3D4952) it is 3.95:1, and
   these are 11px labels on a form. Raised on this band only, rather than
   moving the token and repainting every dark surface on the site. */
.contact-band .field label,
.contact-band .form-note { color: #C3CACE; }   /* 3.95:1 -> 5.6:1 */
/* The contact page puts the same form on a white panel inside the same band,
   where #C3CACE is 1.7:1. That case is restored here rather than by narrowing
   the rule above, because the panel is the exception and reads as one. */
.contact-band .contact-panel .field label,
.contact-band .contact-panel .form-note { color: var(--grey); }
/* Same exception for links: the band sets --link-ink to the dark-ground teal. */
.contact-band .contact-panel { --link-ink: var(--teal-ink); }

/* --- 82. Supply chain note (rev 3.8) -------------------------------------
   Fabrication and machining go to Western Australian vendors, not to our own
   shop. The correction removed the one-roof claim from ten pages; this is the
   positive statement that replaces it. Full-bleed prose inside an existing
   band, deliberately plain so it reads as a fact rather than a pull quote. */
/* Sits between the six-step row and the four value cards, both of which run
   the full width of the band. At 72ch it hung off the left edge with half the
   band empty beside it, so it runs full width too and splits its prose into
   two columns on the same rhythm as .cap-grid--pair below it. */
.supply-note {
  margin: clamp(28px, 3.4vw, 46px) 0 clamp(30px, 3.6vw, 48px);
  padding-top: clamp(20px, 2.4vw, 28px);
  border-top: 1px solid var(--line);
}
.supply-note h3 {
  font-size: var(--fs-h4);
  line-height: 1.2;
  margin: 0 0 clamp(14px, 1.8vw, 22px);
  color: var(--black);
}
.supply-cols {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(18px, 2.6vw, 44px);
  align-items: start;
}
.supply-note p { margin: 0; color: var(--grey); }
@media (max-width: 640px) {
  .supply-cols { grid-template-columns: minmax(0, 1fr); gap: 14px; }
}
/* about.html puts How We Work on the dark anthracite band (.capabilities), so
   the default grey ink fails there. Both surfaces are covered rather than the
   one in use today, in case the block is reused on a light band later. */
.on-dark .supply-note h3,
.capabilities .supply-note h3 { color: #fff; }
.on-dark .supply-note p,
.capabilities .supply-note p  { color: #C7CDD0; }
.capabilities .supply-note { border-top-color: rgba(215,220,223,.22); }

/* --- 83. Rev 3.9 ---------------------------------------------------------- */
/* operations-support: a short lead-in between the fork paragraph and the list
   of delivered solutions. Sized down from .ops-third so the two do not read as
   one run-on paragraph. */
.ops-examples {
  margin-top: clamp(18px, 2vw, 26px);
  margin-bottom: clamp(14px, 1.6vw, 20px);
  max-width: 68ch;
  color: var(--grey);
}
.on-dark .ops-examples { color: #C7CDD0; }

/* track-record: the page now opens with what the record covers, then the
   filter instruction. The intro carries the weight; the instruction is a UI
   label and steps back. */
/* .tr-head .wrap is a grid with a clamped row gap, right between the heading
   and the lede and far too much between two paragraphs. Both paragraphs sit in
   one grid child so the gap applies once and they space themselves. */
.tr-ledes { margin: 0; }
.tr-lede--intro { max-width: 66ch; margin-top: 0; }
.tr-lede--intro + .tr-lede {
  margin-top: 14px;
  font-size: var(--fs-body-sm);
  color: #AEB7BC;
}

/* --- 84. Careers values block (rev 3.9) ----------------------------------
   Was a .band-intro (copy left, photograph right) with the four value cards
   in a capped 1000px grid underneath. Two faults: the cards stopped 200px
   short of the photograph's right edge, and the copy column was 170px shorter
   than the photograph, so the block opened on a hole. Rebuilt as a full-width
   heading over a single row, cards left and photograph right, where the two
   column heights land within about 20px of each other. */
.routes--full { max-width: none; }

.values-head { max-width: 62ch; margin-bottom: clamp(26px, 3.2vw, 42px); }
.values-head > h2 {
  font-size: var(--fs-h2);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 24px;
  padding-bottom: 18px;
  position: relative;
  max-width: 44ch;
}
.values-head > h2::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal-bright);
}

.values-split {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}
.values-split .routes { margin-top: 0; }
.values-split .split-img {
  width: 100%;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  display: block;
}
@media (max-width: 900px) {
  .values-split { grid-template-columns: 1fr; }
  /* Stacked, a 16:11 crop at full wrap width runs to nearly 580px and the
     photograph swamps the four cards it is meant to sit beside. Capped. */
  .values-split .split-img { aspect-ratio: 16 / 9; max-height: 420px; }
}


/* --- 85. The name-origin quote (rev 4.3) ---------------------------------
   The "Where did the name come from?" accordion is Linden speaking now, so it
   takes the .pull-quote component the testimonial on the home page uses. It
   sits inside an accordion body rather than its own band, so it drops the
   centring and gives the portrait beneath it room. */
.name-quote { margin: 0 0 clamp(20px, 2.4vw, 30px); max-width: 60ch; }
.name-quote p { font-size: var(--fs-body); line-height: 1.6; }
.acc-body .tale-portrait { margin: 0; }

/* Portrait beside the quote rather than floating under it. The quote keeps a
   readable measure and the picture fills the space that measure leaves. */
/* .acc-body is capped at 72ch, which is right for the prose accordions and
   wrong for this one: it squeezed a two-column block into half the column and
   left the picture at 130px with 530px of empty page beside it. */
.acc-body--wide { max-width: none; }

.name-origin {
  display: grid;
  grid-template-columns: clamp(200px, 21vw, 290px) minmax(0, 58ch);
  gap: clamp(24px, 3vw, 48px);
  align-items: start;
}
.name-origin .name-quote { margin: 0; max-width: none; }
/* .tale-portrait is a float sized at clamp(130px, 34%, 190px), built to sit
   inside flowing text. In a grid the percentage resolves against the column it
   is meant to be sizing, so it collapsed to the 130px floor. The grid column
   owns the width here. */
.name-origin .tale-portrait { float: none; width: auto; margin: 0; }
.name-origin .tale-ph--portrait { width: 100%; height: auto; }
/* Name and logo band on the grey. The mark's plate flips to white so it
   still reads as a plate. */
.tale--alt { background: var(--surface-alt); }
.tale--alt .tale-fig--mark { background: var(--surface); }

/* People at work, in place of the portrait grid */
.people-strip {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 22px);
  margin-top: clamp(28px, 3.5vw, 44px);
}
.people-strip img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: 6px; }
@media (max-width: 860px) {
  .people-strip { grid-template-columns: 1fr; }
}

/* The logo copy sits one level below .acc-body, out of reach of its
   `> * + *` spacing rule, so it carries the same rhythm itself. */
.name-origin .logo-copy > * + * { margin-top: 1em; }
@media (max-width: 860px) {
  .name-origin { grid-template-columns: 1fr; gap: 22px; }
  .name-origin .tale-portrait { width: min(220px, 60%); }
  .name-origin .tale-fig--mark { width: min(220px, 60%); }
}

/* --- 86. Built to order, not stock (rev 4.4) -----------------------------
   The DWS9000 sits in a row with saws that are held in the yard and it is not
   one of them. Labelling it felt like a warning sticker, so the card ends on
   an invitation instead and the copy carries the fact. */
.kit-ask-link { margin-top: 14px; }
.cap-card .kit-ask-link { align-self: start; }
/* The cards are white inside the dark .capabilities band, so their links take
   the light-ground teal, not the band's bright teal (1.85:1 on white). */
.capabilities .cap-card .arrow { color: var(--teal-ink); }
/* Dark-band heading accents use the brand teal rather than the bright teal,
   as on About (#17). Same rule as #17 adds; drop one copy once both merge. */
.capabilities h2 .accent--soft { color: var(--teal); }
/* Rentals: the saw cards sit on a light band and the cut selector gets its own
   dark band, so the page does not open on two screens of dark grey. */
.cut-band { padding: var(--band-y) 0; }
.cut-tool .selector { margin-top: 0; }
.cut-layout .btn { margin-top: 26px; }

/* --- 87. ZeroStab on Bespoke Engineering (rev 4.5) -----------------------
   Treatment B5: the award graphic in a contained, notched card inside the
   page width, so the asset's navy never runs full width against anthracite.
   #04104A is the asset's own field colour, so the letterboxing is invisible.
   contain, never cover: cover crops the Government of Western Australia
   lock-up off the top, and that mark is not ours to cut. */
.zs img { display: block; width: 100%; height: auto; }
/* The site scopes every p + p rule to a named container, so paragraphs in a
   new wrapper run together with no gap. */
.zs p + p { margin-top: 1.1em; }
.zs-lede { font-size: 1.0625rem; }
.zs-card { background: #04104A; margin-top: clamp(20px, 2.4vw, 32px);
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%); }
.zs-card img { max-height: 280px; object-fit: contain; object-position: center; }
.zs-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 3.4vw, 56px); margin-top: clamp(24px, 2.6vw, 38px);
  align-items: start; }
.zs-award-line { font-size: var(--fs-body-sm); color: var(--grey);
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); }
@media (max-width: 860px) {
  .zs-cols { grid-template-columns: 1fr; }
}

/* Home page band rhythm. The hero, its strip and the dark capabilities band
   ran as one dark block, then the logos and fleet bands ran as one grey
   block. The home capabilities band sits on white instead, and the light
   bands below it alternate grey, white, grey. The dark .capabilities band
   on about.html and rentals.html is unchanged. */
.cap-home { padding: var(--band-y) 0; background: var(--surface); }
.cap-home .cap-copy h2 { color: var(--ink); }
.cap-home .cap-copy p { color: var(--grey); }
.logos-section--plain { background: var(--surface); }
/* Heading accents on the two dark home bands use the bright teal. */
.catalogue .accent, .contact-band .accent { color: var(--teal-bright); }
/* ==========================================================================
   BESPOKE ENGINEERING PAGE REVIEW
   ========================================================================== */

/* Light button for secondary links such as datasheets. Teal-ink on
   surface-sunk is 4.7:1; hover matches the solid button. */
.btn--soft { background: var(--surface-sunk); color: var(--teal-ink); }
.btn--soft:hover { background: var(--teal); color: var(--black); }
/* On a grey band the grey button disappears, so it turns white (5.4:1). */
.band--alt .btn--soft { background: var(--surface); }
.band--alt .btn--soft:hover { background: var(--teal); }

/* Dark-band heading accents use the brand teal, as on About and Rentals: 3.95:1
   on anthracite. The contact band is covered by the rule About added; the
   .on-dark bands need their own, which outranks .on-dark .accent. */
.on-dark h2 .accent--soft { color: var(--teal); }

/* "Other Case Studies" continues Intervention Tooling in Practice on the same
   white band, so it drops its top padding and its cards take the grey fill
   they would otherwise get from a grey band. */
.proof-more { padding-top: 0; }
.proof-more .xref-grid--boxed .xref { background: var(--surface-alt); }

/* The manifold render sits on a white ground. On a grey band, multiply lets
   the band show through the white without visibly changing the render. */
.band--alt .manifold-img { mix-blend-mode: multiply; }

/* "Other Case Studies" heads the continuation band. It takes the section
   heading treatment (uppercase, teal rule) one step down in size, so it reads
   as a sub-heading of Intervention Tooling in Practice, not a stray label. */
.proof-more .xref-head {
  font-size: clamp(1.25rem, 2vw, 1.7rem);
  text-transform: uppercase;
  letter-spacing: var(--ls-display);
  margin-bottom: 30px;
  padding-bottom: 16px;
  position: relative;
}
.proof-more .xref-head::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 56px; height: 3px;
  background: var(--teal);
}

/* Feature headings are capped at 24ch, which broke "How a Bespoke Scope
   Arrives" over two lines with room to spare. This one uses the column width,
   so it sits on one line on desktop and still wraps on narrow screens. */
.rental-feature .rf-copy > h2.h2--full { max-width: none; }

/* --- 88. Form error states ------------------------------------------------
   Set by site.js on the enquiry and careers forms. The home form sits on the
   dark contact band; the contact page and careers forms sit on white panels,
   so the light-ground colours are the default and the dark band overrides
   them. Text reds: #A8322B is 6.4:1 on white, #FFB3A7 is 5.3:1 on
   --anthracite. Same red family as .ask-err and the careers size readout. */
.field-error {
  margin: 7px 0 0;
  font-size: var(--fs-body-sm);
  line-height: 1.4;
  color: #A8322B;
}
.field.is-invalid input,
.field.is-invalid textarea,
.field.is-invalid select { border-color: #C0392B; }
.enq-set.is-invalid .enq-option label { border-color: #C0392B; }
.enq-set > .field-error { text-align: center; margin-top: 4px; }
.contact-panel .enq-set > .field-error,
.eoi-form .enq-set > .field-error { text-align: left; }

.form-error {
  margin: 22px 0 0;
  padding: 10px 13px;
  font-size: var(--fs-body-sm);
  color: #8A2317;
  background: #FDF0EE;
  border-left: 3px solid #C0392B;
}

.contact-band .field-error { color: #FFB3A7; }
.contact-band .field.is-invalid input,
.contact-band .field.is-invalid textarea,
.contact-band .enq-set.is-invalid .enq-option label { border-color: #E8796B; }
.contact-band .contact-panel .field-error { color: #A8322B; }
.contact-band .contact-panel .field.is-invalid input,
.contact-band .contact-panel .field.is-invalid textarea,
.contact-band .contact-panel .enq-set.is-invalid .enq-option label { border-color: #C0392B; }

/* Sending: the button is disabled and reads "Sending…" until the reply. */
form[aria-busy="true"] .contact-submit .btn { opacity: 0.7; cursor: progress; }

/* --- 89. Mobile CTA bar ---------------------------------------------------
   Built and shown by site.js. Phones only: a touch screen as the main input
   and 600px wide or less. That leaves out tablets (an iPad mini is 744px
   upright), desktops, and a desktop window dragged narrow, where the header
   Contact button is always in reach. Sits under the cookie bar (z-index
   900) and the header (120), and gives way to either while they are open. Hidden state
   uses visibility so its links leave the tab order. Teal-bright on
   --anthracite-deep is about 6:1; --black on --teal is 6.5:1. */
.m-cta { display: none; }
@media (max-width: 600px) and (hover: none) and (pointer: coarse) {
  .m-cta {
    display: flex;
    gap: 10px;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 110;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--anthracite-deep);
    border-top: 2px solid var(--teal);
    box-shadow: 0 -10px 28px rgba(19, 22, 25, .25);
    transform: translateY(110%);
    visibility: hidden;
    transition: transform .25s ease, visibility 0s linear .25s;
  }
  .m-cta.is-shown {
    transform: none;
    visibility: visible;
    transition: transform .25s ease, visibility 0s;
  }
  #cookieBar:not([hidden]) ~ .m-cta,
  body[data-nav-open="true"] .m-cta { visibility: hidden; transform: translateY(110%); }

  .m-cta a {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 46px;
    font-size: var(--fs-small);
    font-weight: 500;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    text-decoration: none;
    border-radius: 3px;
  }
  .m-cta-call {
    color: var(--teal-bright);
    border: 1.5px solid var(--teal);
  }
  .m-cta-call svg { width: 18px; height: 18px; }
  .m-cta-enquire {
    color: var(--black);
    background: var(--teal);
    border: 1.5px solid var(--teal);
  }
  .m-cta a:focus-visible { outline: 2px solid var(--teal-bright); outline-offset: 2px; }
}
@media (max-width: 600px) and (hover: none) and (pointer: coarse) and (prefers-reduced-motion: reduce) {
  .m-cta, .m-cta.is-shown { transition: none; }
}

/* --- 90. Phone fixes: drawer, banner dots, form text, tap targets ---------
   From a phone-width audit of all 40 pages, 08 October 2026. */

/* Drawer. Closed, it sits just off the right edge, and its shadow still fell
   on the page as a grey band down every light section. The shadow now comes
   with the open state only. Closed, it is also hidden outright so its links
   leave the tab order and the accessibility tree; visibility waits for the
   slide-out to finish. Open, it covered the menu button, and five pages have
   no scrim, so there was nothing on screen to close it with. The button now
   sits above the drawer and shows as a cross. */
@media (max-width: 960px) {
  .nav-links {
    box-shadow: none;
    transition: transform 0.34s var(--ease-out), box-shadow 0.34s var(--ease-out),
                visibility 0s linear 0.34s;
  }
  .nav-links[data-open="true"] {
    box-shadow: -24px 0 60px rgba(0, 0, 0, 0.4);
    transition: transform 0.34s var(--ease-out), box-shadow 0.34s var(--ease-out);
  }
  .js .nav-links:not([data-open="true"]) { visibility: hidden; }
  .nav-toggle { z-index: 111; }
}

/* Home banner dots. They were pinned 26px above the banner's foot while the
   copy above them set the banner's height, so nothing kept them clear of the
   buttons: an 11px overlap at 320x568, touching at 375x667, 9px at best.
   They now sit in the flow under the buttons, each a 44px tap target with
   the same 9px dot drawn inside it. On a short screen the copy box also
   holds the first screen's height, so the longer second slide no longer
   pushes the page down by up to 60px each time it comes round. 77px is the
   drawer-width header; 58px is the row of dots. */
@media (max-width: 899px) {
  .hero--carousel { display: flex; flex-direction: column; }
  .hero--carousel .hero-content { flex: 1 0 auto; padding-bottom: 4px; }
  .hero--carousel .hero-dots {
    position: relative;
    bottom: auto;
    gap: 0;
    padding-bottom: 14px;
  }
  .hero-dot,
  .hero-dot:hover,
  .hero-dot.is-active {
    position: relative;
    width: 44px; height: 44px;
    border: 0;
    background: none;
    transform: none;
  }
  .hero-dot::before {
    content: '';
    position: absolute;
    left: 50%; top: 50%;
    width: 9px; height: 9px;
    margin: -4.5px 0 0 -4.5px;
    box-sizing: border-box;
    border-radius: 50%;
    border: 1.5px solid rgba(255, 255, 255, 0.6);
    transition: background 0.25s, border-color 0.25s, transform 0.25s;
  }
  .hero-dot.is-active::before {
    background: var(--teal);
    border-color: var(--teal);
    transform: scale(1.15);
  }
}
@media (max-width: 899px) and (max-height: 720px) {
  .hero--carousel .hero-content {
    min-height: calc(100vh - 135px);
    min-height: calc(100svh - 135px);
  }
}

/* Form text. iOS Safari zooms the page when a field under 16px takes focus,
   and the enquiry, careers, record and selector fields were 13-14.5px. The
   :is() carries the input selector's weight to select and textarea too, so
   this outranks the per-form rules without !important. */
@media (hover: none) and (pointer: coarse) {
  :root :is(
    input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]):not([type="submit"]):not([type="button"]):not([type="hidden"]),
    select,
    textarea
  ) { font-size: 16px; }
}

/* Tap targets, touch screens only. Filter chips are clipped to their cut
   corner, and a clip-path clips taps too, so they grow to 44px for real.
   Carousel bars stay 3px to look at inside a 44px button. Text links keep
   their layout and get a larger invisible hit area from ::before. Footer
   links go to 44px rows, which adds about 12px per link. */
@media (hover: none) and (pointer: coarse) {
  .ct-chip, .rec-chip, .cs-chip {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .carousel-dot {
    height: 44px;
    padding: 20px 0 21px;
    background-clip: content-box;
  }
  .crumb a,
  .sec-more, .kit-ask, .arrow, .addr-link, .sec-eyebrow-link,
  .rec-reset, .rec-case {
    position: relative;
  }
  .crumb a::before,
  .sec-more::before, .kit-ask::before, .arrow::before,
  .addr-link::before, .sec-eyebrow-link::before,
  .rec-reset::before, .rec-case::before {
    content: '';
    position: absolute;
    inset: -12px -6px;
  }
  .rec-reset::before { inset: -13px -9px; }
  .foot-col { gap: 0; }
  .foot-col a {
    display: flex;
    align-items: center;
    min-height: 44px;
  }
}

/* --- 91. Phone layouts: drawer groups, Rentals saw cards, About values ----
   Drawer groups. The chevron was drawn on the label link, and the first tap
   on About, Sectors or Capabilities was swallowed to "open" a group that was
   already open, so the label seemed dead and the chevron did nothing. site.js
   now adds an arrow button beside each label: the label goes to its page and
   the arrow shows or hides the pages under it. Groups start closed except
   the one holding the current page, which also shortens the drawer. Gated
   on .js so without the script the groups stay open. */
.nav-sub-toggle { display: none; }
@media (max-width: 960px) {
  .nav-item.has-dropdown {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 48px;
  }
  .nav-item.has-dropdown > a {
    grid-column: 1;
    padding-right: 4px;
    background-image: none;
  }
  .nav-item.has-dropdown > .dropdown { grid-column: 1 / -1; }
  .js .nav-item.has-dropdown:not([data-open="true"]) > .dropdown { display: none; }
  .nav-sub-toggle {
    display: block;
    grid-column: 2;
    grid-row: 1;
    position: relative;
    min-height: 44px;
    padding: 0;
    background: none;
    border: 0;
    border-bottom: 1px solid rgba(255, 255, 255, 0.09);
    color: rgba(255, 255, 255, 0.7);
    cursor: pointer;
  }
  .nav-sub-toggle::before {
    content: '';
    position: absolute;
    left: 50%; top: 50%;
    width: 8px; height: 8px;
    margin: -6px 0 0 -4px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(45deg);
    transition: transform var(--dur-fast) var(--ease), margin var(--dur-fast) var(--ease);
  }
  .nav-sub-toggle[aria-expanded="true"] { color: var(--teal-bright); }
  .nav-sub-toggle[aria-expanded="true"]::before {
    margin-top: -2px;
    transform: rotate(-135deg);
  }
  .nav-sub-toggle:focus-visible { outline: 2px solid var(--teal-bright); outline-offset: -2px; }
}

/* Rentals saw cards. Stacked one per row on a phone, each card was a full
   width render plate plus copy, close to a screen apiece and about seven
   screens for the fleet. The render now sits as a thumbnail beside the
   model and cut range, and the copy runs full width beneath. */
@media (max-width: 560px) {
  .cut-band .cap-card {
    display: grid;
    grid-template-columns: 120px minmax(0, 1fr);
    column-gap: 16px;
    align-content: start;
    min-height: 0;
    padding: 18px 18px 16px;
  }
  .cut-band .cap-card > * { grid-column: 1 / -1; }
  .cut-band .cap-card .product-photo {
    grid-column: 1;
    grid-row: 1 / span 2;
    align-self: center;
    margin: 0;
    padding: 4px;
    aspect-ratio: 4 / 3;
  }
  .cut-band .cap-card h3 { grid-column: 2; align-self: end; margin-bottom: 4px; }
  .cut-band .cap-card .spec { grid-column: 2; align-self: start; margin-top: 0; }
  .cut-band .cap-card .spec + p { margin-top: 14px; }
}
/* Each saw card has a description and an "Ideal for" line as two paragraphs
   with no gap between them, so they read as one run-on block. All widths. */
.cut-band .cap-card p:not(.spec) + p { margin-top: 8px; }

/* About values. Every .cap-card holds a 232px minimum so a row of tiles
   lines up. Stacked one per row there is no row to line up, and the shorter
   values (Agile, Competitive) were left with a block of empty card. */
@media (max-width: 640px) {
  .tale-values .cap-card { min-height: 0; }
}

/* --- 92. Decommissioning renders on phones ----------------------------------
   The three tool renders (Cutting, Plugging, Buoyancy Removal) are square and
   held at 1:1 by img.kit-render, but Cutting and Plugging sit in a 16:11
   .photo-ph frame. Stacked on a phone the 335px square overflowed the 230px
   frame by about 50px top and bottom, over the heading below. The frame now
   takes the render's own height. Buoyancy Removal is a copy-split, which
   stacks copy first, so its render landed under the paragraph while the
   other two sit above their headings; it now leads like the others. */
@media (max-width: 900px) {
  .rental-feature .photo-ph:has(> img.kit-render) {
    aspect-ratio: auto;
    min-height: 0;
  }
  .copy-split > .wrap > div:has(> img.kit-render) { order: -1; }
}

/* --- 93. Datasheets (datasheets.html) --------------------------------------
   One row per datasheet: name and a line of copy on the left, the PDF and
   the product page on the right. Grouped by product family, each group under
   the shared .rule-head. The PDFs are the same files the product pages link
   to, so replacing a PDF in public/datasheets/ updates both at once; adding
   or removing a datasheet means editing this page as well. */
.ds-group + .ds-group { margin-top: clamp(48px, 6vw, 88px); }
.ds-group .rule-head { margin-bottom: 8px; }
.ds-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--line); }
.ds-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 12px 32px;
  align-items: center;
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}
.ds-copy h3 { margin: 0; }
.ds-copy p { margin: 4px 0 0; color: var(--grey); font-size: var(--fs-body-sm); }
.ds-links { display: flex; align-items: center; gap: 24px; justify-content: flex-end; }
.ds-links .btn { white-space: nowrap; }
.ds-type {
  margin-left: 8px;
  font-family: var(--font-mono);
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-eyebrow);
  opacity: .75;
}
@media (max-width: 720px) {
  .ds-row { grid-template-columns: 1fr; }
  .ds-links { justify-content: flex-start; flex-wrap: wrap; gap: 12px 24px; }
}

/* --- 94. Onward strip direction -----------------------------------------
   The strip pairs a way back with a way on. Back sits on the left and next
   on the right, in reading order, on every page that carries one. The arrows
   say which is which; on phones the two stack, so both stay left-aligned. */
.onward > a:first-child:not(:last-child) .k::before,
.onward > a:first-child:not(:last-child) .eyebrow::before { content: '\2190\00a0'; }
.onward > a:last-child:not(:first-child) .k::after,
.onward > a:last-child:not(:first-child) .eyebrow::after { content: '\00a0\2192'; }
@media (min-width: 701px) {
  .onward > a:last-child:not(:first-child) { text-align: right; }
}
