/* ============================================================================
   mapthis.site — MAIN STYLESHEET
   ----------------------------------------------------------------------------
   Requires tokens.css to be loaded FIRST. Nothing in this file declares a
   colour, size or spacing value directly — everything reads from a token.
   If you find yourself typing a hex code in here, the token set is missing
   something: add it to tokens.css instead.

   Order matters, do not shuffle:
     01 reset          06 header / nav
     02 base elements  07 hero
     03 accessibility  08 sections & components
     04 layout         09 footer
     05 wordmark       10 utilities + print
   ========================================================================= */


/* ============================================================================
   01 — RESET
   Deliberately minimal. A heavy reset just means re-declaring defaults that
   were already fine.
   ========================================================================= */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--s4));
}

body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }

ul[class], ol[class] { list-style: none; padding: 0; margin: 0; }

img, svg, video, canvas { display: block; max-width: 100%; height: auto; }

input, button, textarea, select { font: inherit; color: inherit; }

button { background: none; border: 0; padding: 0; cursor: pointer; }

table { border-collapse: collapse; width: 100%; }


/* ============================================================================
   02 — BASE ELEMENTS
   ========================================================================= */
body {
  background: var(--page);
  color: var(--body);
  font-family: var(--font-body);
  font-size: var(--text-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--heading);
  text-wrap: balance;        /* stops a lone word dropping to its own line */
}
h1 { font-size: var(--text-display); font-weight: 700; line-height: var(--lh-tight); letter-spacing: -.03em;  max-width: var(--measure-h1); }
h2 { font-size: var(--text-h2);      font-weight: 600; line-height: var(--lh-head);  letter-spacing: -.022em; }
h3 { font-size: var(--text-h3);      font-weight: 600; line-height: 1.3;             letter-spacing: -.015em; }
h4 { font-size: var(--text-h4);      font-weight: 600; line-height: 1.4;             letter-spacing: -.01em;  }

p { max-width: var(--measure); text-wrap: pretty; }
p + p { margin-top: var(--s4); }

a { color: var(--accent-text); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

strong, b { font-weight: 600; color: var(--heading); }

hr { border: 0; border-top: 1px solid var(--border); margin: var(--s7) 0; }

code, kbd, samp {
  font-family: var(--font-mono);
  font-size: .86em;
  background: var(--surface);
  color: var(--heading);
  padding: .1em .4em;
  border-radius: var(--r1);
}

blockquote {
  border-left: 3px solid var(--accent);
  padding-left: var(--s5);
  font-size: var(--text-lead);
  line-height: var(--lh-lead);
  color: var(--heading);
}

::selection { background: var(--accent); color: var(--on-accent); }


/* ============================================================================
   03 — ACCESSIBILITY
   Not optional. Indian government and PSU tenders increasingly ask about
   accessibility compliance, and retrofitting it costs ten times more.
   ========================================================================= */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r1);
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  left: var(--s4);
  top: calc(var(--s4) * -4);
  z-index: calc(var(--z-menu) + 1);
  background: var(--accent);
  color: var(--on-accent);
  padding: var(--s3) var(--s4);
  border-radius: var(--r2);
  font-weight: 500;
  text-decoration: none;
  transition: top var(--t-fast) var(--ease);
}
.skip-link:focus { top: var(--s4); }

/* Visually hidden but still read aloud. For labels a sighted user infers
   from layout but a screen reader cannot. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

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


/* ============================================================================
   04 — LAYOUT
   ========================================================================= */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--wide   { max-width: var(--container-wide); }
.container--narrow { max-width: 760px; }

.section { padding-block: var(--s9); }
.section--tight { padding-block: var(--s7); }
.section--surface { background: var(--surface); }
.section--dark { background: var(--page); }  /* kept so old markup still renders */
.section--panel {
  background: var(--surface);
  border-block: 1px solid var(--border);
}

/* Vertical rhythm without margin collapse surprises. */
.stack > * + * { margin-top: var(--s4); }
.stack--lg > * + * { margin-top: var(--s6); }
.stack--sm > * + * { margin-top: var(--s2); }

/* Horizontal group that wraps gracefully. */
.cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  align-items: center;
}

.grid { display: grid; gap: var(--s5); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(270px, 100%), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }

/* Content column + sidebar that collapses on its own, no media query. */
.grid--sidebar {
  grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr));
}


/* ============================================================================
   05 — WORDMARK (text fallback)
   SUPERSEDED by the outlined SVG logo in section 11 — use that.
   Kept only for contexts where an SVG cannot go: plain-text email templates,
   a CMS field, a third-party embed. Renders with a dotless i plus a CSS dot,
   so it needs the webfont to be correct.
   ========================================================================= */
.wordmark {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 19px;
  letter-spacing: -.02em;
  line-height: 1;
  white-space: nowrap;
  display: inline-block;
  color: var(--heading);
  text-decoration: none;
}
.wordmark__accent { color: var(--accent); }
.wordmark__i { position: relative; }
.wordmark__i::after {
  content: "";
  position: absolute;
  left: 50%;
  bottom: .80em;
  width: .155em;
  height: .155em;
  border-radius: 50%;
  background: currentColor;
  transform: translateX(-50%);
}


/* ============================================================================
   06 — HEADER / NAV
   ========================================================================= */
.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: color-mix(in srgb, var(--page) 88%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid var(--border);
}
@supports not (backdrop-filter: blur(1px)) {
  .header { background: var(--page); }
}

.header__inner {
  min-height: var(--header-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s5);
}

.nav { display: flex; align-items: center; gap: var(--s6); }
.nav__list { display: flex; align-items: center; gap: var(--s5); }
.nav__link {
  color: var(--body);
  text-decoration: none;
  font-size: 15px;
  font-weight: 500;
  padding-block: var(--s2);
  position: relative;
}
.nav__link:hover { color: var(--heading); }
.nav__link[aria-current="page"] { color: var(--heading); }
.nav__link[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: var(--accent);
  border-radius: var(--rf);
}

.nav__toggle { display: none; }

@media (max-width: 860px) {
  .nav__toggle {
    display: grid;
    place-items: center;
    width: 42px; height: 42px;
    border-radius: var(--r2);
    border: 1px solid var(--border-strong);
    color: var(--heading);
  }
  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    z-index: var(--z-menu);
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--page);
    border-bottom: 1px solid var(--border);
    padding: var(--s4) var(--gutter) var(--s6);
    transform: translateY(-120%);
    visibility: hidden;
    transition: transform var(--t-base) var(--ease), visibility var(--t-base);
  }
  .nav[data-open="true"] { transform: translateY(0); visibility: visible; }
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__link {
    padding-block: var(--s4);
    border-bottom: 1px solid var(--border);
    font-size: 17px;
  }
  .nav__link[aria-current="page"]::after { display: none; }
  .nav .btn { margin-top: var(--s4); text-align: center; }
}


/* ============================================================================
   07 — HERO
   ========================================================================= */
.hero { padding-block: var(--s9) var(--s8); }
.hero__eyebrow { margin-bottom: var(--s4); }
.hero h1 { margin-bottom: var(--s5); }
.hero .lead { margin-bottom: var(--s6); }

/* Hero over a photograph. The scrim is mandatory — never place the wordmark
   or headline on an unscrimmed image. */
.hero--photo {
  position: relative;
  isolation: isolate;
  min-height: 560px;
  display: flex;
  align-items: flex-end;
  border-radius: var(--r4);
  overflow: hidden;
}
.hero--photo > img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -2;
}
.hero--photo::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim);
  z-index: -1;
}
.hero--photo .hero__content { padding: var(--s8) var(--s7); max-width: 720px; }

@media (max-width: 700px) {
  .hero--photo { min-height: 460px; }
  .hero--photo::before { background: var(--scrim-v); }
  .hero--photo .hero__content { padding: var(--s6) var(--s5); }
}


/* ============================================================================
   08 — COMPONENTS
   ========================================================================= */

/* ---- eyebrow ----------------------------------------------------------- */
.eyebrow {
  display: block;
  font-size: var(--text-eyebrow);
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent-text);
}

/* ---- lead -------------------------------------------------------------- */
.lead {
  font-size: var(--text-lead);
  line-height: var(--lh-lead);
  max-width: var(--measure-lead);
}

/* ---- buttons ----------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.2;
  padding: 12px 22px;
  border-radius: var(--r2);
  border: 1px solid transparent;
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.btn--primary { background: var(--accent); color: var(--on-accent); }
.btn--primary:hover { background: var(--accent-hover); }

.btn--secondary {
  background: transparent;
  color: var(--heading);
  border-color: var(--border-strong);
}
.btn--secondary:hover { border-color: var(--heading); }

.btn--ghost {
  background: transparent;
  color: var(--accent-text);
  padding-inline: 0;
}
.btn--ghost:hover { text-decoration: underline; text-underline-offset: 4px; }

.btn--lg { font-size: 16px; padding: 15px 28px; }
.btn--block { display: flex; width: 100%; }

/* ---- cards ------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s5);
}
.card--link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease),
              transform var(--t-base) var(--ease);
}
.card--link:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-2);
  transform: translateY(-2px);
}
.card__mark { width: 44px; height: 44px; margin-bottom: var(--s4); }
.card h3 { margin-bottom: var(--s2); }
.card p  { font-size: 15px; margin-bottom: 0; }

/* ---- media / figure ---------------------------------------------------- */
.figure { margin: 0; }
.figure img { border-radius: var(--r3); width: 100%; }
.figure figcaption {
  margin-top: var(--s3);
  font-size: var(--text-small);
  color: var(--muted);
}

/* ---- stat -------------------------------------------------------------- */
.stat__value {
  display: block;
  font-family: var(--font-display);
  font-size: 34px;
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -.025em;
  color: var(--heading);
}
.stat__label { font-size: var(--text-small); color: var(--muted); }

/* ---- badge ------------------------------------------------------------- */
.badge {
  display: inline-block;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  padding: 4px 10px;
  border-radius: var(--rf);
  background: var(--accent-soft);
  color: var(--accent-text);
}

/* ---- breadcrumb -------------------------------------------------------- */
.breadcrumb { display: flex; flex-wrap: wrap; gap: var(--s2); font-size: var(--text-small); }
.breadcrumb li { color: var(--muted); }
.breadcrumb li + li::before { content: "/"; margin-right: var(--s2); color: var(--border-strong); }
.breadcrumb a { color: var(--muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--heading); text-decoration: underline; }

/* ---- forms ------------------------------------------------------------- */
.field { display: flex; flex-direction: column; gap: 6px; }
.field > label { font-size: 13px; font-weight: 500; color: var(--heading); }
.field input,
.field textarea,
.field select {
  font-size: 15px;
  padding: 11px 13px;
  border-radius: var(--r2);
  border: 1px solid var(--border-strong);
  background: var(--page);
  color: var(--heading);
  width: 100%;
  transition: border-color var(--t-fast) var(--ease);
}
.field textarea { min-height: 130px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--muted); }
.field__hint  { font-size: 13px; color: var(--muted); }
.field__error { font-size: 13px; color: var(--warning); font-weight: 500; }
.field--error input,
.field--error textarea,
.field--error select { border-color: var(--warning); }

/* State messages. Note: errors are AMBER, never red — red is the brand
   colour, and a user must be able to tell a broken field from a heading. */
.alert {
  padding: var(--s4);
  border-radius: var(--r2);
  border: 1px solid;
  font-size: 15px;
}
.alert--warning { border-color: var(--warning); color: var(--warning); background: transparent; }
.alert--success { border-color: var(--success); color: var(--success); background: transparent; }

/* ---- table ------------------------------------------------------------- */
.table { font-size: 15px; }
.table th, .table td { text-align: left; padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border); }
.table th {
  font-size: 11px;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}
.table--scroll { overflow-x: auto; }   /* wrap wide tables, never the page */

/* ---- prose: long-form body copy ---------------------------------------- */
.prose > * + * { margin-top: var(--s4); }
.prose h2 { margin-top: var(--s7); }
.prose h3 { margin-top: var(--s6); }
.prose ul, .prose ol { padding-left: var(--s5); max-width: var(--measure); }
.prose li + li { margin-top: var(--s2); }
.prose img { border-radius: var(--r3); margin-block: var(--s6); }

/* ---- product marks ----------------------------------------------------- */
/* The concept SVGs use currentColor for structure and --mark-accent for the
   highlight, so one file works in any context. */
.mark { width: 48px; height: 48px; color: var(--heading); }
.mark--accent { --mark-accent: var(--accent); }


/* ============================================================================
   09 — FOOTER
   ========================================================================= */
.footer {
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding-block: var(--s8) var(--s6);
  font-size: var(--text-small);
}
.footer__grid {
  display: grid;
  gap: var(--s6);
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  margin-bottom: var(--s7);
}
.footer h4 {
  font-family: var(--font-body);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s3);
}
.footer a { color: var(--body); text-decoration: none; display: inline-block; padding-block: 3px; }
.footer a:hover { color: var(--heading); text-decoration: underline; }
.footer__bottom {
  border-top: 1px solid var(--border);
  padding-top: var(--s5);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  justify-content: space-between;
  color: var(--muted);
}


/* ============================================================================
   10 — UTILITIES
   Kept deliberately short. A utility class per property turns CSS into
   inline styles with extra steps.
   ========================================================================= */
.u-muted      { color: var(--muted); }
.u-heading    { color: var(--heading); }
.u-center     { text-align: center; }
.u-center-x   { margin-inline: auto; }
.u-measure    { max-width: var(--measure); }
.u-nowrap     { white-space: nowrap; }
.u-mt-0       { margin-top: 0; }
.u-mb-0       { margin-bottom: 0; }
.u-hide       { display: none; }
@media (max-width: 700px) { .u-hide-mobile  { display: none; } }
@media (min-width: 701px) { .u-hide-desktop { display: none; } }


/* ============================================================================
   PRINT
   Quotations and tender documents get printed in this industry. A site that
   prints badly looks careless in exactly the room where it matters.
   ========================================================================= */
@media print {
  :root { --page:#fff; --surface:#fff; --heading:#000; --body:#222; --muted:#555;
          --border:#ccc; --border-strong:#999; --accent:#B3202A; --accent-text:#B3202A; }
  .header, .footer, .nav, .theme-toggle, .skip-link { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  h1, h2, h3, h4 { color: #000; }
  a { color: #000; text-decoration: underline; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #555; }
  .section { padding-block: var(--s5); }
  .card { border: 1px solid #ccc; background: #fff; break-inside: avoid; }
  h2, h3 { break-after: avoid; }
  img { break-inside: avoid; }
}


/* ============================================================================
   11 — LOGO (outlined SVG)
   ----------------------------------------------------------------------------
   Inline the SVG (includes/logo.php) rather than using <img>: inlined it
   inherits currentColor and the custom properties, and costs one fewer
   request. The dark-pair rules below are for the logo sitting on photography
   or inside a .section--dark band, not for a dark site theme.
   ========================================================================= */
.logo {
  display: block;
  height: 22px;
  width: auto;
  color: var(--heading);     /* drives .logo__ink via currentColor */
  overflow: visible;
}
.logo__ink    { fill: currentColor; }
.logo__accent { fill: var(--accent); }

.logo--lg     { height: 34px; }
.logo--footer { height: 20px; }

/* On photography the logo is always the dark pair, over a scrim. */
.on-photo .logo,
.hero-photo .logo { color: var(--heading); }
.on-photo .logo__accent,
.hero-photo .logo__accent { fill: var(--accent-text); }

/* A link wrapping the logo must not inherit link underlines. */
a:has(> .logo), .logo-link { display: inline-block; text-decoration: none; line-height: 0; }


/* ============================================================================
   12 — PAGE PATTERNS
   Components that appear on the homepage and will be reused across the site.
   ========================================================================= */

/* ---- section header: eyebrow + heading + optional intro ----------------- */
.section-head { max-width: 62ch; margin-bottom: var(--s7); }
.section-head h2 { margin-bottom: var(--s3); }
.section-head p { margin-bottom: 0; }

/* ---- hero -------------------------------------------------------------- */
.hero-photo {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  min-height: 620px;
  /* Reserve the space before the image lands, so nothing jumps.
     Layout shift is a ranked Core Web Vital, not a nicety. */
  aspect-ratio: 2264 / 1552;
  max-height: 78vh;
  overflow: hidden;
  background: var(--page) var(--hero-lqip, none) center/cover no-repeat;
}
.hero-photo__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 62% center;   /* keeps the operator off the text column */
  z-index: -2;
}
.hero-photo::before {
  content: ""; position: absolute; inset: 0;
  background: var(--scrim); z-index: -1;
}
.hero-photo__content {
  padding: var(--s9) 0 var(--s8);
  max-width: 640px;
  color: #D4DDD8;
}
.hero-photo__content h1 { margin-bottom: var(--s5); }
.hero-photo__content .lead { color: #C9D3DF; margin-bottom: var(--s6); }
.hero-photo .btn--secondary { border-color: rgba(230,236,244,.34); }
.hero-photo .btn--secondary:hover { border-color: var(--heading); }

@media (max-width: 760px) {
  .hero-photo { min-height: 520px; aspect-ratio: auto; }
  .hero-photo::before { background: var(--scrim-v); }
  .hero-photo__content { padding-block: var(--s8) var(--s6); }
}

/* ---- metric tiles ------------------------------------------------------ */
.metric {
  padding: var(--s5) 0;
  border-top: 2px solid var(--accent);
}
.metric__value {
  display: block;
  font-family: var(--font-display);
  font-size: 19px; font-weight: 600; letter-spacing: -.015em;
  color: var(--heading);
  margin-bottom: var(--s2);
}
.metric p { font-size: var(--text-small); color: var(--muted); margin: 0; }

/* ---- numbered steps ---------------------------------------------------- */
.step__n {
  display: inline-grid; place-items: center;
  width: 34px; height: 34px;
  border-radius: var(--rf);
  background: var(--accent); color: var(--on-accent);
  font-family: var(--font-display); font-weight: 700; font-size: 14px;
  margin-bottom: var(--s4);
}
.step h3 { margin-bottom: var(--s2); }
.step p { font-size: 15px; margin: 0; }

/* ---- service cards ----------------------------------------------------- */
.service {
  display: flex; flex-direction: column;
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  overflow: hidden;
  text-decoration: none; color: inherit;
  transition: border-color var(--t-base) var(--ease),
              box-shadow var(--t-base) var(--ease),
              transform var(--t-base) var(--ease);
}
a.service:hover {
  border-color: var(--border-strong);
  box-shadow: var(--shadow-2);
  transform: translateY(-2px);
}
/* the plate at the top of a card — one fixed ratio so a row of cards lines up */
.service__img { display: block; background: var(--surface-2); aspect-ratio: 16 / 9; overflow: hidden; }
.service__img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.service__img--mark { display: grid; place-items: center; }
.service__img--mark img { width: 48px; height: 48px; object-fit: contain; opacity: .7; }
.service__body { display: flex; flex-direction: column; flex: 1; padding: var(--s5); }
.service__mark { width: 40px; height: 40px; margin-bottom: var(--s4); }
.service h3 { margin-bottom: var(--s2); }
.service p { font-size: 15px; margin-bottom: var(--s4); }
.service__foot { margin-top: auto; display: flex; align-items: center; gap: var(--s3); }
.service__go { font-size: 14px; font-weight: 500; color: var(--accent-text); }

/* A planned service is not a link. It must look unmistakably different from
   a live one, or a visitor clicks it, nothing happens, and they lose trust. */
.service--soon {
  background: var(--surface);
  border-style: dashed;
  box-shadow: none;
}
.service--soon .service__mark { opacity: .45; }
.service--soon h3 { color: var(--body); }

.tag {
  display: inline-block;
  font-size: 10.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  padding: 3px 9px; border-radius: var(--rf);
}
.tag--live    { background: var(--accent); color: var(--on-accent); }
.tag--soon    { background: var(--surface-2); color: var(--muted); }
.tag--planned { background: transparent; color: var(--muted); border: 1px solid var(--border-strong); }

/* ---- deliverables list ------------------------------------------------- */
.ticks { padding: 0; margin: 0; list-style: none; }
.ticks li {
  position: relative;
  padding-left: var(--s5);
  margin-bottom: var(--s3);
  font-size: 15.5px;
}
.ticks li::before {
  content: "";
  position: absolute; left: 0; top: .55em;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--accent);
}

/* ---- call-to-action band ----------------------------------------------- */
.cta-band {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r4);
  padding: var(--s8) var(--s7);
  display: grid;
  gap: var(--s6);
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  align-items: center;
}
.cta-band h2 { margin-bottom: var(--s3); }
.cta-band p  { color: var(--body); margin: 0; }
@media (max-width: 640px) { .cta-band { padding: var(--s6) var(--s5); } }

/* ---- editorial note: marks unverified placeholder content --------------- */
/* Delete this rule and every .todo element before the site goes live. */
.todo {
  display: inline-block;
  font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  background: #3A2E07; color: #FBBF24;
  padding: 2px 8px; border-radius: var(--r1);
  margin-left: var(--s2);
}


/* ============================================================================
   13 — SERVICES HUB
   ========================================================================= */

.service__tech {
  font-size: 13px !important;
  color: var(--muted);
  margin-bottom: var(--s4) !important;
  padding-top: var(--s3);
  border-top: 1px solid var(--border);
}

/* ---- filter bar -------------------------------------------------------- */
.filters {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  padding: var(--s5) 0 var(--s6);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--s7);
}
.filter-row { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }
.filter-row > .filter-label {
  font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted);
  min-width: 78px;
}

.chip {
  font-size: 14px;
  font-weight: 500;
  padding: 8px 15px;
  border-radius: var(--rf);
  border: 1px solid var(--border-strong);
  color: var(--body);
  background: var(--page);
  transition: background var(--t-fast) var(--ease),
              border-color var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease);
}
.chip:hover { border-color: var(--heading); color: var(--heading); }
.chip[aria-pressed="true"] {
  background: var(--heading);
  border-color: var(--heading);
  color: var(--page);
}
.chip__count {
  font-variant-numeric: tabular-nums;
  opacity: .6;
  margin-left: 5px;
  font-size: 12.5px;
}
/* A filter that would return nothing is disabled rather than hidden: a chip
   that vanishes as you click around makes the set feel unstable. */
.chip[disabled] { opacity: .4; cursor: not-allowed; }
.chip[disabled]:hover { border-color: var(--border-strong); color: var(--body); }

.filter-status {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
  font-size: var(--text-small);
  color: var(--muted);
}
.filter-status button {
  font-size: var(--text-small);
  color: var(--accent-text);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---- empty state ------------------------------------------------------- */
.empty {
  padding: var(--s8) var(--s5);
  text-align: center;
  border: 1px dashed var(--border-strong);
  border-radius: var(--r3);
  color: var(--muted);
}
.empty h3 { color: var(--heading); margin-bottom: var(--s2); }
.empty p { margin: 0 auto; max-width: 46ch; }

/* Cards hidden by a filter. Kept in the DOM so the page does not reflow from
   scratch and so a crawler still sees every service. */
.service[hidden] { display: none; }

/* ---- service detail page ----------------------------------------------- */
.page-head {
  padding-block: var(--s8) var(--s7);
  border-bottom: 1px solid var(--border);
}
.page-head .breadcrumb { margin-bottom: var(--s5); }
.page-head h1 { margin-bottom: var(--s5); max-width: 20ch; }

.spec-table th { width: 38%; color: var(--muted); font-weight: 500;
                 text-transform: none; letter-spacing: 0; font-size: 14px; }
.spec-table td { color: var(--heading); }

.kit-figure {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s6);
  display: grid;
  place-items: center;
}
.kit-figure img { max-height: 420px; width: auto; }

/* ---- sector label on a service card ------------------------------------ */
.service__sector {
  display: block;
  font-size: 11px; font-weight: 600; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s2);
}

/* ---- compact hero for a services-led homepage -------------------------- */
.hero-photo--compact { min-height: 480px; aspect-ratio: auto; max-height: 56vh; }
.hero-photo--compact .hero-photo__content { padding-block: var(--s8) var(--s7); }
@media (max-width: 760px) { .hero-photo--compact { min-height: 420px; } }


/* ============================================================================
   14 — GUIDED WALKTHROUGH
   ----------------------------------------------------------------------------
   One idea per step, Next to advance. Built as progressive enhancement: every
   step is in the HTML and visible without JavaScript, so a crawler reads the
   whole story and a visitor with scripting off simply scrolls it. JS turns the
   same markup into a stepper.
   ========================================================================= */
.walk { max-width: 980px; margin-inline: auto; }

.walk__rail {
  display: flex;
  gap: 6px;
  margin-bottom: var(--s5);
  align-items: center;
}
.walk__tick {
  height: 3px;
  flex: 1 1 0;
  border-radius: var(--rf);
  background: var(--border-strong);
  transition: background var(--t-base) var(--ease);
}
.walk__tick[aria-current="step"] { background: var(--accent); }
.walk__tick.is-done { background: var(--heading); }

.walk__frame {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r4);
  padding: var(--s8) var(--s7);
  /* A fixed floor stops the card resizing between steps, which otherwise
     throws the Next button around under the reader's cursor. */
  min-height: 420px;
  display: flex;
  flex-direction: column;
}
@media (max-width: 700px) {
  .walk__frame { padding: var(--s6) var(--s5); min-height: 0; }
}

.walk__step { display: flex; flex-direction: column; gap: var(--s4); flex: 1; }
.walk__step[hidden] { display: none; }

.walk__n {
  font-family: var(--font-mono);
  font-size: 12.5px;
  letter-spacing: .1em;
  color: var(--muted);
}
.walk__step h3 {
  font-size: clamp(24px, 3.2vw, 33px);
  line-height: 1.15;
  letter-spacing: -.028em;
  max-width: 20ch;
}
.walk__step > p { font-size: 17px; max-width: 56ch; margin: 0; }

/* the one number that carries each step */
.walk__figure {
  margin-top: auto;
  padding-top: var(--s5);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--s7);
}
.walk__fig-v {
  display: block;
  font-family: var(--font-display);
  font-size: 34px; font-weight: 700; line-height: 1.05; letter-spacing: -.03em;
  color: var(--accent-text);
}
.walk__fig-l { font-size: 13.5px; color: var(--muted); max-width: 26ch; display: block; margin-top: 4px; }

.walk__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  margin-top: var(--s5);
}
.walk__count { font-size: var(--text-small); color: var(--muted); font-variant-numeric: tabular-nums; }
.walk__skip { font-size: var(--text-small); color: var(--muted); text-decoration: underline;
              text-underline-offset: 3px; }
.walk__skip:hover { color: var(--heading); }

/* Without JS the rail and nav are meaningless, so they stay hidden until the
   script confirms it is running. */
.walk__rail, .walk__nav { display: none; }
.walk.is-live .walk__rail { display: flex; }
.walk.is-live .walk__nav  { display: flex; }
.walk.is-live .walk__frame > .walk__step + .walk__step { border-top: 0; padding-top: 0; }

/* Stacked fallback: steps read as a list, separated. */
.walk:not(.is-live) .walk__step + .walk__step {
  border-top: 1px solid var(--border);
  padding-top: var(--s6);
  margin-top: var(--s6);
}
.walk:not(.is-live) .walk__frame { min-height: 0; }

/* final step */
.walk__book { display: flex; flex-direction: column; gap: var(--s5); }
.walk__book .cluster { gap: var(--s3); }

/* ---- comparison table inside a step ------------------------------------ */
.compare { font-size: 15px; width: 100%; }
.compare th, .compare td { padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border); text-align: left; }
.compare thead th { font-size: 11px; letter-spacing: .07em; text-transform: uppercase; color: var(--muted); }
.compare tbody th { font-weight: 500; color: var(--body); text-transform: none; letter-spacing: 0; font-size: 15px; }
.compare .is-ours { color: var(--accent-text); font-weight: 600; }
.compare tbody tr:last-child th, .compare tbody tr:last-child td { border-bottom: 0; }


/* ============================================================================
   15 — BOOKING
   ========================================================================= */
.choices { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(min(270px, 100%), 1fr)); }

/* Radio-driven cards: the input stays in the DOM for keyboard and screen
   readers, the label is the visible target. No JS needed to switch. */
.choice input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.choice label {
  display: block;
  background: var(--page);
  border: 1px solid var(--border-strong);
  border-radius: var(--r3);
  padding: var(--s5);
  cursor: pointer;
  height: 100%;
  transition: border-color var(--t-fast) var(--ease), box-shadow var(--t-fast) var(--ease);
}
.choice label:hover { border-color: var(--heading); }
.choice input:checked + label {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 1px var(--accent);
}
.choice input:focus-visible + label { outline: 2px solid var(--accent); outline-offset: 2px; }
.choice h3 { margin-bottom: var(--s2); }
.choice p { font-size: 15px; margin: 0; }
.choice .meta { display: block; margin-top: var(--s3); font-size: 13px; color: var(--muted); }

/* Fields belonging to one booking type only.
   Default is VISIBLE, and :has() hides them for the other type. That way a
   browser without :has() support shows an extra field rather than hiding a
   required one — fail open, never closed. */
.only-survey { display: flex; }
form:has(#type-meeting:checked) .only-survey { display: none; }

.form-grid { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
.form-grid .span-2 { grid-column: 1 / -1; }
.required { color: var(--accent); }


/* ============================================================================
   16 — PLATES
   ----------------------------------------------------------------------------
   The point-cloud and software images are dark-field: black at the edges,
   luminous in the middle. On this page they should not sit inside a box with
   a visible border — they should emerge out of the field. These rules make
   that happen, and are the main reason the site is dark at all.
   ========================================================================= */

.plate { position: relative; display: block; }
.plate img { display: block; width: 100%; }

/* A point-cloud plate is already black at its edges, so fading the edges to
   transparent makes it read as part of the page rather than a pasted photo. */
.plate--cloud img {
  -webkit-mask-image: radial-gradient(120% 100% at 50% 50%, #000 58%, transparent 100%);
          mask-image: radial-gradient(120% 100% at 50% 50%, #000 58%, transparent 100%);
}

/* A screenshot must keep its rectangle — it is a window, not a cloud. */
.plate--ui img {
  border: 1px solid var(--border);
  border-radius: var(--r3);
  box-shadow: var(--shadow-3);
}

/* A photograph gets a soft inner edge so it does not end on a hard line. */
.plate--photo img { border-radius: var(--r3); }
.plate--photo::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: var(--r3);
  box-shadow: inset 0 0 0 1px rgba(230,236,244,.08);
  pointer-events: none;
}

.plate__cap {
  display: block;
  margin-top: var(--s3);
  font-size: var(--text-small);
  color: var(--muted);
}
.plate__cap b { color: var(--body); font-weight: 500; }

/* ---- full-bleed band --------------------------------------------------- */
.band {
  position: relative;
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
}
.band img { width: 100%; display: block; }
.band--cloud img {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
}
.band__over {
  position: absolute;
  inset: auto 0 0 0;
  padding: var(--s7) 0 var(--s6);
  background: var(--scrim-v);
}

/* ---- editorial split: text beside a plate ------------------------------ */
.split {
  display: grid;
  gap: var(--s7);
  align-items: center;
  grid-template-columns: repeat(auto-fit, minmax(min(380px, 100%), 1fr));
}
.split--reverse > *:first-child { order: 2; }
@media (max-width: 820px) { .split--reverse > *:first-child { order: 0; } }

/* ---- hero over video --------------------------------------------------- */
.hero-v {
  position: relative;
  isolation: isolate;
  min-height: 86vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--page);
}
.hero-v__media {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  z-index: -2;
  opacity: .78;
}
.hero-v::before {
  content: "";
  position: absolute; inset: 0; z-index: -1;
  background: var(--scrim-v), var(--scrim);
}
.hero-v__content { padding-block: var(--s9) var(--s8); max-width: 760px; }
.hero-v h1 { margin-bottom: var(--s5); }
.hero-v .lead { color: #C9D3DF; margin-bottom: var(--s6); }

/* A line of hard numbers under the hero, in the mono face, to signal that
   this is an instrument company rather than a brochure. */
.facts {
  display: flex; flex-wrap: wrap; gap: var(--s7);
  padding-top: var(--s6); margin-top: var(--s7);
  border-top: 1px solid var(--border);
}
.facts dt {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--faint); margin-bottom: 6px;
}
.facts dd {
  margin: 0; font-family: var(--font-display); font-weight: 700;
  font-size: 28px; letter-spacing: -.025em; color: var(--heading);
}
.facts dd small { display: block; font-family: var(--font-body); font-weight: 400;
                  font-size: 13px; color: var(--muted); letter-spacing: 0; margin-top: 4px; }


/* ============================================================================
   17 — HOMEPAGE FLOW
   ----------------------------------------------------------------------------
   The page runs: hero -> what we do (simple) -> one uninterrupted story about
   the flagship service -> next step. Earlier it cut from forestry to mining
   and back three times, which is what made it feel disjointed.
   ========================================================================= */

/* ---- proof strip: hard numbers immediately after the hero -------------- */
.proofbar {
  border-block: 1px solid var(--border);
  background: var(--surface);
}
.proofbar__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4) var(--s8);
  padding-block: var(--s5);
  align-items: baseline;
}
.proofbar dt {
  font-family: var(--font-mono);
  font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--faint);
}
.proofbar dd {
  margin: 0 0 2px;
  font-family: var(--font-display); font-weight: 700;
  font-size: 22px; letter-spacing: -.02em; color: var(--heading);
}
.proofbar dd span { color: var(--accent-text); }
.proofbar__note { margin-left: auto; font-size: var(--text-small); color: var(--muted); max-width: 32ch; }
@media (max-width: 820px) { .proofbar__note { margin-left: 0; } }

/* ---- the flagship card leads the grid ---------------------------------- */
.service--featured { border-color: var(--border-strong); background: var(--surface-2); }
@media (min-width: 900px) {
  .grid--services { grid-template-columns: repeat(3, 1fr); }
  .service--featured { grid-column: span 2; }
  .service--featured .service__mark { width: 52px; height: 52px; }
  .service--featured h3 { font-size: 24px; }
  .service--featured p { font-size: 16px; max-width: 54ch; }
}

/* ---- compact mid-page call to action ----------------------------------- */
.cta-inline {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s6);
  padding: var(--s6);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--r3);
  background: var(--surface);
}
.cta-inline p { margin: 0; max-width: 54ch; }
.cta-inline .cluster { margin-left: auto; }
@media (max-width: 760px) { .cta-inline .cluster { margin-left: 0; } }

/* ---- story chapter marker ---------------------------------------------- */
.chapter {
  display: flex; align-items: center; gap: var(--s4);
  margin-bottom: var(--s6);
}
.chapter__n {
  font-family: var(--font-mono); font-size: 12px; letter-spacing: .1em;
  color: var(--accent-text);
}
.chapter__rule { flex: 1; height: 1px; background: var(--border); }
.chapter__label {
  font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--faint);
}


/* ============================================================================
   18 — WALKTHROUGH WITH PLATES
   ----------------------------------------------------------------------------
   A step can carry an image beside its text. The frame keeps a fixed floor so
   the Next button does not jump between steps of different heights.
   ========================================================================= */
.walk__frame { min-height: 480px; }

.walk__step--media {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--s7);
  align-items: center;
}
.walk__step--media .walk__text { display: flex; flex-direction: column; gap: var(--s4); }
.walk__media { margin: 0; min-width: 0; }
.walk__media img { width: 100%; }

@media (max-width: 860px) {
  .walk__step--media { grid-template-columns: 1fr; gap: var(--s5); }
  .walk__frame { min-height: 0; }
}

/* ---- a plate used as a process step ------------------------------------ */
.procstep { display: flex; flex-direction: column; gap: var(--s3); }
.procstep__n {
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .1em;
  color: var(--accent-text);
}
.procstep h3 { margin: 0; font-size: 18px; }
.procstep p { margin: 0; font-size: 14.5px; color: var(--muted); }

/* ---- product shot on its own black field ------------------------------- */
.kit-plate {
  background: #000;
  border: 1px solid var(--border);
  border-radius: var(--r4);
  padding: var(--s6);
  display: grid; place-items: center;
}
.kit-plate img { max-height: 520px; width: auto; }


/* ============================================================================
   19 — WALKTHROUGH: FIXED PLATE BOX
   ----------------------------------------------------------------------------
   Every step's image occupies an identical box. Without this the frame jumps
   between a 4:3 photograph, a portrait and a 16:9 screenshot, and the Next
   button moves under the reader's cursor between clicks.
   ========================================================================= */
.walk__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--r3);
  background: #000;
}
.walk__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
/* Screenshots must not be cropped — a cut-off UI reads as a mistake. */
.walk__media--fit { background: #0A0C0E; }
.walk__media--fit img { object-fit: contain; }

.walk__media .plate__cap {
  position: absolute; left: 0; right: 0; bottom: 0;
  margin: 0; padding: var(--s4);
  background: linear-gradient(180deg, transparent, rgba(5,7,9,.9));
  color: var(--body);
}
.walk__media { position: relative; }

/* ---- the headline claim ------------------------------------------------ */
.claim {
  font-family: var(--font-display);
  font-size: clamp(46px, 7vw, 86px);
  font-weight: 700;
  line-height: .95;
  letter-spacing: -.04em;
  color: var(--accent-text);
  display: block;
}
.claim sup { font-size: .32em; vertical-align: super; margin-left: .06em; }
.claim__sub { display: block; margin-top: var(--s3); font-size: 17px; color: var(--heading); }

.footnote {
  margin-top: var(--s5);
  padding-top: var(--s3);
  border-top: 1px solid var(--border);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--faint);
  max-width: 62ch;
}
.footnote sup { color: var(--accent-text); }


/* ============================================================================
   20 — TECHNICAL DIAGRAMS
   ----------------------------------------------------------------------------
   Inline SVG, not images: the labels stay as real text so they are selectable,
   indexable and translatable, and the whole thing inherits the theme.
   ========================================================================= */
.diagram {
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s5);
}
.diagram svg { width: 100%; height: auto; display: block; }

.dg-bore    { fill: none; stroke: var(--heading); stroke-width: 2.5; }
.dg-env     { fill: none; stroke: var(--accent-text); stroke-width: 1.8; stroke-dasharray: 6 4; }
.dg-ohe     { fill: none; stroke: var(--success); stroke-width: 1.6; stroke-dasharray: 3 3; }
.dg-rail    { stroke: var(--border-strong); stroke-width: 2; }
.dg-ground  { fill: var(--surface-2); }
.dg-bad     { fill: var(--accent); fill-opacity: .55; stroke: var(--accent); stroke-width: 1.5; }
.dg-design  { fill: none; stroke: var(--faint); stroke-width: 1.8; stroke-dasharray: 5 4; }
.dg-actual  { fill: none; stroke: var(--heading); stroke-width: 2.2; }
.dg-dim     { stroke: var(--muted); stroke-width: 1; }
.dg-t       { font-family: var(--font-mono); font-size: 11px; fill: var(--muted); }
.dg-t--hi   { fill: var(--accent-text); }
.dg-t--head { font-family: var(--font-body); font-size: 12px; font-weight: 600; fill: var(--heading); }

.diagram figcaption {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--border);
  font-size: var(--text-small);
  color: var(--muted);
}
.diagram figcaption b { color: var(--heading); font-weight: 600; display: block; margin-bottom: 4px; }

.legend { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); margin-top: var(--s4); font-size: 12.5px; color: var(--muted); }
.legend span { display: inline-flex; align-items: center; gap: 7px; }
.legend i { width: 18px; height: 0; border-top-width: 2px; border-top-style: solid; display: inline-block; }


/* ============================================================================
   21 — MEASUREMENT OVERLAYS
   ----------------------------------------------------------------------------
   An SVG traced over the real scan, not a diagram beside it. The overlay
   viewBox matches the image exactly and preserveAspectRatio="none" keeps the
   two locked together at any width. Labels stay real text.
   ========================================================================= */
.ov { position: relative; margin: 0; border-radius: var(--r3); overflow: hidden; }
.ov img { display: block; width: 100%; height: auto; }
.ov svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }

.ov-rail   { fill: none; stroke: #7FE3FF; stroke-width: 2.4; stroke-linecap: round; opacity: .95; }
.ov-centre { fill: none; stroke: var(--accent); stroke-width: 2.4; stroke-dasharray: 10 7; }
.ov-env    { fill: rgba(229,0,18,.10); stroke: var(--accent); stroke-width: 2.2; }
.ov-ohe    { fill: none; stroke: #3DDC84; stroke-width: 2; stroke-dasharray: 6 5; }
.ov-dim    { stroke: #FFFFFF; stroke-width: 1.6; }
.ov-tick   { stroke: #FFFFFF; stroke-width: 1.6; opacity: .8; }
.ov-t {
  font-family: var(--font-mono); font-size: 15px; fill: #FFFFFF;
  paint-order: stroke; stroke: rgba(0,0,0,.75); stroke-width: 4px; stroke-linejoin: round;
}
.ov-t--acc { fill: #FF8578; }
.ov-t--ohe { fill: #6BE8A4; }

.ov figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: var(--s6) var(--s5) var(--s4);
  background: linear-gradient(180deg, transparent, rgba(5,7,9,.92));
  font-size: var(--text-small); color: #D4DDD8;
}
.ov figcaption b { color: #fff; font-weight: 600; }
@media (max-width: 700px) { .ov-t { font-size: 20px; } }


/* ============================================================================
   22 — CONTACT & MAP
   ----------------------------------------------------------------------------
   The map loads only when someone asks for it. An embedded Google map on page
   load pulls several hundred KB and sets third-party cookies before the
   visitor has done anything — on a 4G connection that is the slowest thing on
   the page, and it is a privacy cost nobody agreed to.
   ========================================================================= */
.map {
  position: relative;
  border: 1px solid var(--border);
  border-radius: var(--r3);
  overflow: hidden;
  background: var(--surface-2);
  aspect-ratio: 16 / 10;
}
.map iframe { display: block; width: 100%; height: 100%; border: 0; }

.map__ask {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--s4); text-align: center; padding: var(--s5);
  /* a faint grid, so the placeholder reads as a map rather than a blank box */
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 44px 44px;
  background-position: center;
}
.map__ask p { margin: 0; font-size: var(--text-small); color: var(--muted); max-width: 34ch; }
.map__pin { color: var(--accent); }

.addr { font-style: normal; line-height: 1.75; }
.addr strong { display: block; color: var(--heading); margin-bottom: var(--s2); }

.contact-grid { display: grid; gap: var(--s6); grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
.contact-item dt {
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin-bottom: var(--s2);
}
.contact-item dd { margin: 0; font-size: 16px; color: var(--heading); }
.contact-item dd a { color: var(--accent-text); }


/* ============================================================================
   23 — HERO DOLLY
   ----------------------------------------------------------------------------
   Two copies of the same image, each slowly scaling from the tunnel's vanishing
   point and crossfading half a cycle apart. That reads as continuous forward
   travel into the bore; a single image on `alternate` would visibly reverse out
   again. Same src, so it is one download.
   ========================================================================= */
.hero-v__media--dolly {
  transform-origin: 49% 34%;   /* the vanishing point of this plate */
  will-change: transform, opacity;
  animation: dolly 18s linear infinite;
}
.hero-v__media--dolly.is-b { animation-delay: -9s; }

/* Peak opacity matches the base .hero-v__media (.78) so the headline keeps its
   contrast — the keyframes must not quietly brighten the plate to full. */
@keyframes dolly {
  0%   { transform: scale(1);   opacity: 0; }
  12%  { opacity: .78; }
  88%  { opacity: .78; }
  100% { transform: scale(1.5); opacity: 0; }
}

/* Motion is decoration here, so it goes entirely when it is not wanted. */
@media (prefers-reduced-motion: reduce) {
  .hero-v__media--dolly { animation: none; opacity: 1; transform: none; }
  .hero-v__media--dolly.is-b { display: none; }
}

/* ============================================================================
   24 — SECTION BACKGROUND GRAPHIC
   ========================================================================= */
.has-bg { position: relative; isolation: isolate; overflow: hidden; }
.bg-art {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  z-index: -1;
  opacity: .5;
  /* fades out behind the text so nothing competes with reading */
  -webkit-mask-image: radial-gradient(120% 90% at 50% 50%, transparent 0%, #000 62%);
          mask-image: radial-gradient(120% 90% at 50% 50%, transparent 0%, #000 62%);
}
.bg-line   { fill: none; stroke: var(--border-strong); stroke-width: 1.2; }
.bg-trav   { fill: none; stroke: var(--accent); stroke-width: 1.6; stroke-dasharray: 7 5; opacity: .9; }
.bg-stn    { fill: var(--page); stroke: var(--accent-text); stroke-width: 1.6; }
.bg-stn--g { fill: var(--page); stroke: var(--success); stroke-width: 1.6; }
.bg-t      { font-family: var(--font-mono); font-size: 11px; fill: var(--faint); }


/* ============================================================================
   25 — UNDERGROUND MINE SECTION (animated hero graphic)
   ----------------------------------------------------------------------------
   A vertical section through a mine — surface, decline, levels, orebody,
   stopes — with a scan pulse travelling the decline and along a level. SVG and
   CSS only: no library, no canvas, a few KB, and it scales to any screen.
   ========================================================================= */
.mine { width: 100%; height: auto; display: block; }

.mine-rock    { fill: var(--surface); }
.mine-sky     { fill: none; stroke: var(--border-strong); stroke-width: 2; }
.mine-drive   { fill: none; stroke: var(--border-strong); stroke-width: 9; stroke-linecap: round; }
.mine-drive-i { fill: none; stroke: var(--page);          stroke-width: 5; stroke-linecap: round; }
.mine-ore     { fill: var(--accent); opacity: .16; }
.mine-ore-e   { fill: none; stroke: var(--accent); stroke-width: 1.4; opacity: .55; stroke-dasharray: 6 5; }
.mine-stope   { fill: var(--accent); opacity: .30; stroke: var(--accent-text); stroke-width: 1.6; }
.mine-label   { font-family: var(--font-mono); font-size: 13px; fill: var(--muted); }
.mine-label--hi { fill: var(--accent-text); }

/* the scan: a bright segment running the route */
.mine-scan {
  fill: none;
  stroke: var(--accent-text);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-dasharray: 150 3000;
  filter: drop-shadow(0 0 6px rgba(255,92,77,.65));
  animation: mine-run 11s linear infinite;
}
@keyframes mine-run { from { stroke-dashoffset: 3150; } to { stroke-dashoffset: 0; } }

/* stope voids breathe, so the eye finds them */
.mine-stope { animation: mine-pulse 4.5s ease-in-out infinite; }
.mine-stope:nth-of-type(2) { animation-delay: -2.2s; }
@keyframes mine-pulse { 0%,100% { opacity: .22; } 50% { opacity: .46; } }

@media (prefers-reduced-motion: reduce) {
  .mine-scan  { animation: none; stroke-dasharray: none; opacity: .9; }
  .mine-stope { animation: none; opacity: .34; }
}

/* hero that holds a graphic rather than a photograph */
.hero-art {
  position: relative;
  padding-block: var(--s8) var(--s7);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.hero-art__grid {
  display: grid;
  gap: var(--s7);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center;
}
@media (max-width: 900px) {
  .hero-art__grid { grid-template-columns: 1fr; }
  .hero-art { padding-block: var(--s7) var(--s6); }
}

/* extra parts for the mine section */
.mine-cut   { fill: var(--page); stroke: var(--border-strong); stroke-width: 1.6; }
.mine-steel { fill: none; stroke: var(--border-strong); stroke-width: 2.2; }
.mine-vent  { fill: none; stroke: var(--border-strong); stroke-width: 3.5; stroke-dasharray: 9 7; }
.mine-loop  { fill: none; stroke: var(--border-strong); stroke-width: 5; opacity: .75; }


/* ============================================================================
   26 — NAVIGATION WITH A SERVICES MENU
   ----------------------------------------------------------------------------
   A disclosure, not a hover menu: it opens on click and closes on Escape or an
   outside click. Hover-only menus are unusable by keyboard and unreliable on
   touch, where the first tap becomes a hover and nothing happens.
   ========================================================================= */
.nav__item { position: relative; }

.nav__btn {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 15px; font-weight: 500;
  color: var(--body); padding-block: var(--s2);
}
.nav__btn:hover, .nav__btn[aria-expanded="true"] { color: var(--heading); }
.nav__btn svg { transition: transform var(--t-fast) var(--ease); }
.nav__btn[aria-expanded="true"] svg { transform: rotate(180deg); }

.menu {
  position: absolute; top: calc(100% + var(--s3)); left: -(var(--s4));
  min-width: 300px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  box-shadow: var(--shadow-3);
  padding: var(--s2);
  z-index: var(--z-menu);
}
.menu[hidden] { display: none; }
.menu a {
  display: block; padding: var(--s3) var(--s4);
  border-radius: var(--r2); text-decoration: none; color: var(--heading);
  font-size: 15px; font-weight: 500; line-height: 1.3;
}
.menu a:hover { background: var(--surface-2); }
.menu a small { display: block; margin-top: 3px; font-size: 12.5px; font-weight: 400; color: var(--muted); }
.menu__all { border-top: 1px solid var(--border); margin-top: var(--s2); padding-top: var(--s2); }
.menu__all a { color: var(--accent-text); font-size: 14px; }

@media (max-width: 860px) {
  /* On the mobile sheet the menu is just a nested list — nothing to open. */
  .nav__btn { display: none; }
  .menu { position: static; display: block; min-width: 0; background: none;
          border: 0; box-shadow: none; padding: 0; }
  .menu[hidden] { display: block; }
  .menu a { padding: var(--s3) 0 var(--s3) var(--s4); border-bottom: 1px solid var(--border); border-radius: 0; }
  .menu a small { display: none; }
}

/* ============================================================================
   27 — AVAILABILITY
   ========================================================================= */
.soon-strip {
  display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5);
  align-items: center;
  padding: var(--s5);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r3);
  background: var(--surface);
}
.soon-strip__label {
  font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
}
.soon-strip ul { display: flex; flex-wrap: wrap; gap: var(--s3) var(--s5); margin: 0; padding: 0; list-style: none; }
.soon-strip li { font-size: 15px; color: var(--body); }
.soon-strip li::before { content: "◦ "; color: var(--muted); }

/* what a service replaces — the before/after line on a card */
.swap { display: grid; gap: 4px; font-size: 15px !important; margin-bottom: var(--s4) !important; }
.swap__was {
  color: var(--muted); text-decoration: line-through;
  text-decoration-color: var(--border-strong); text-decoration-thickness: 1px;
}
.swap__now { color: var(--heading); font-weight: 500; }

/* QA table: a failed section has to be unmissable */
.tag--fail { background: var(--warning); color: #221701; }
.qa--fail td { background: rgba(251,191,36,.07); }
.qa td { font-variant-numeric: tabular-nums; }


/* ============================================================================
   28 — SCREENSHOT FRAME
   ----------------------------------------------------------------------------
   The software UI is light and this site is dark. Putting the screenshot in a
   window frame makes the lightness read as "this is a screenshot" rather than
   as a design inconsistency.
   ========================================================================= */
.shot {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--r3);
  overflow: hidden;
  background: var(--surface-2);
  box-shadow: var(--shadow-3);
}
.shot__bar {
  display: flex; align-items: center; gap: 7px;
  padding: 10px var(--s4);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.shot__bar i { width: 10px; height: 10px; border-radius: 50%; background: var(--border-strong); }
.shot__bar span {
  margin-left: var(--s3);
  font-family: var(--font-mono); font-size: 11.5px; color: var(--muted);
}
.shot img { display: block; width: 100%; }
.shot figcaption {
  padding: var(--s3) var(--s4) var(--s4);
  font-size: var(--text-small); color: var(--muted);
  border-top: 1px solid var(--border);
}
.shot figcaption b { color: var(--heading); font-weight: 600; }


/* ============================================================================
   30 — DEPTH PROFILE (hero graphic)
   ----------------------------------------------------------------------------
   The output, drawn: one bar per section hanging from ground level, a dashed
   line at the specified depth, and the sections that fall short in amber.
   Replaces an earlier long-section attempt — in a longitudinal section the
   trench spans the whole width, so it always read as a black band.
   ========================================================================= */
.pf { width: 100%; height: auto; display: block; }
.pf-ground { stroke: var(--border-strong); stroke-width: 3; }
.pf-axis   { stroke: var(--border-strong); stroke-width: 1; }
.pf-tick   { stroke: var(--faint); stroke-width: 1; }
.pf-bar    { fill: #C6D1DF; }
.pf-bad    { fill: var(--warning); }
.pf-short  { fill: none; stroke: var(--warning); stroke-width: 1.2; }
.pf-spec   { stroke: var(--accent-text); stroke-width: 3; stroke-dasharray: 12 10; }
.pf-brk    { stroke: var(--warning); stroke-width: 2; fill: none; }
.pf-t      { font-family: var(--font-mono); font-size: 12px; fill: var(--muted); }
.pf-t--f   { fill: var(--faint); }
.pf-t--acc { fill: var(--accent-text); font-size: 13px; }
.pf-t--w   { fill: var(--warning); font-size: 15px; font-weight: 700; }

.pf-sweep { stroke: var(--accent); stroke-width: 2.5; opacity: .9;
            filter: drop-shadow(0 0 6px rgba(229,0,18,.8));
            animation: pf-run 7s linear infinite; }
@keyframes pf-run { from { transform: translateX(0); } to { transform: translateX(990px); } }
.pf-bad { animation: pf-pulse 2.6s ease-in-out infinite; }
@keyframes pf-pulse { 0%,100% { opacity: .82; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .pf-sweep { animation: none; opacity: .45; }
  .pf-bad   { animation: none; opacity: 1; }
}


/* ============================================================================
   31 — SMALL SCREENS
   ----------------------------------------------------------------------------
   The layout is fluid already; these are the guards that stop one long word,
   one wide table or one oversized graphic from forcing the whole page to
   scroll sideways — the single most common mobile fault.
   ========================================================================= */
/* No `overflow-x: hidden` here. It is the usual reflex for sideways scroll,
   but on <html> or <body> it makes the element its own scroll container and
   the sticky header stops sticking — and worse, it hides the fault instead of
   fixing it. Every page is measured at 320/360/390/768/1024px and none of them
   overflows, so there is nothing to hide. */
body { overflow-wrap: break-word; }

/* Anything that genuinely must be wide scrolls inside itself. */
.table--scroll { -webkit-overflow-scrolling: touch; }
.table--scroll table { min-width: 460px; }

pre, code { overflow-wrap: anywhere; }

@media (max-width: 560px) {
  :root { --gutter: var(--s4); --s9: 64px; --s8: 48px; }

  /* Headlines set for a desktop column are too tight at 360px. */
  h1 { font-size: clamp(28px, 8.4vw, 40px); max-width: none; }
  h2 { font-size: clamp(22px, 6.4vw, 28px); }
  .lead { font-size: 17px; }
  body { font-size: 16px; }

  /* Stacked buttons, full width, so neither is a small target. */
  .cluster .btn { width: 100%; justify-content: center; }
  .cluster { gap: var(--s3); }

  .hero-v { min-height: 76vh; }
  .hero-v__content { padding-block: var(--s8) var(--s7); }
  .facts { gap: var(--s5); }
  .facts dd { font-size: 24px; }

  .cta-band, .cta-inline { padding: var(--s5); }
  .cta-inline .cluster { width: 100%; }

  .shot__bar span { display: none; }
  .proofbar__row { gap: var(--s4) var(--s5); }
}

/* ----------------------------------------------------------------------------
   TAP TARGETS
   Measured at 390px with every interactive element's client rect, not guessed.
   The rule is padding, never `display`, so none of this changes how the links
   sit in a line of text — the hit area grows, the layout does not move.
   ------------------------------------------------------------------------- */
@media (max-width: 860px) {

  /* The progress rail paints as a 3px bar but is a row of buttons. Padding
     gives each one a real hit area; background-clip keeps the paint at 3px. */
  .walk__rail { margin-bottom: var(--s2); }
  .walk__tick {
    height: 3px;
    box-sizing: content-box;
    padding-block: 14px;
    background-clip: content-box;
    border: 0;
  }

  /* Footer link lists: 30px tall before, which is under every published
     minimum. Inline links in the bottom line are left alone. */
  .footer__grid a { padding-block: 10px; }
  .breadcrumb a   { padding-block: 8px; }
  .logo-link      { padding-block: 10px; display: inline-block; }

  /* Form controls at a size a thumb can hit, and at a font size iOS will not
     zoom the page to read (anything under 16px triggers the zoom). */
  input, select, textarea, button { font-size: 16px; }
  .field input, .field select, .field textarea { min-height: 46px; }
}

/* ----------------------------------------------------------------------------
   FILTERS ON A PHONE
   Measured at 390px: the two chip groups wrapped to eleven rows and pushed the
   first service card 1,150px down the page. Somebody arriving on a phone had to
   scroll past the whole filing system before seeing a single thing we do.

   So on narrow screens each group becomes one horizontally scrolling row. The
   chips stay exactly as they are, the filters stay visible and usable, and the
   first card moves up to where it belongs.
   ------------------------------------------------------------------------- */
@media (max-width: 700px) {
  .filters { gap: var(--s3); padding-bottom: var(--s5); margin-bottom: var(--s6); }
  /* min-width:0 on both: a flex item defaults to min-width:auto, which means
     it refuses to shrink below its content and the scroll row pushes the page
     wider instead of scrolling inside itself. Measured body.scrollWidth was
     1213px at a 390px viewport before this line. */
  .filters > .filter-row {
    flex-direction: column;
    /* flex-wrap stays `wrap` from the base rule unless it is turned off here,
       and `column wrap` lets an over-wide item open a SECOND COLUMN sized to
       its own content — which is how a row that was supposed to scroll inside
       itself ended up making the page 1213px wide at a 390px viewport. */
    flex-wrap: nowrap;
    align-items: stretch;
    gap: var(--s2);
    min-width: 0;
  }
  .filter-row > .filter-label { min-width: 0; }

  .filters [role="group"].filter-row {
    min-width: 0;
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* Bleed to the screen edge so the row visibly continues past it — a row
       that stops flush at the gutter reads as finished. */
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    padding-block: 2px;
  }
  .filters [role="group"].filter-row::-webkit-scrollbar { display: none; }
  .filters .chip { flex: 0 0 auto; scroll-snap-align: start; }
}
