/* Apex Thermocon v6 - "the catalogue, online".
   ---------------------------------------------------------------------------
   Design brief, drawn from the competitor audit (see v6/DESIGN.md):
     - product-first architecture: every product gets a page, every page leads
       with its specification and its part numbers (Marlin, JMS, Swagelok)
     - card grids for divisions and products, generous whitespace, one accent
       on a near-monochrome ground (Oliver Valves, Conax, Okazaki)
     - approvals and certificate numbers carry the trust, because unlike the
       big brands we have no client logo wall to show and will not invent one
     - no hero carousel: the pattern the weaker competitors lean on hardest
   Motion and materials follow .claude/skills/apple-design; the rules are
   restated where they bite. Radius rule for v6: 10px cards, 8px controls,
   6px inputs. Nothing is a pill; that was v3's signature and this is not v3. */

@font-face {
  font-family: "Space Grotesk";
  src: url("fonts/SpaceGrotesk-var.woff2") format("woff2");
  font-weight: 300 700;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("fonts/JetBrainsMono-var.woff2") format("woff2");
  font-weight: 100 800;
  font-display: swap;
}

:root {
  --paper: #f4f6f9;
  --paper-2: #eaeef4;
  --surface: #ffffff;
  --ink: #10141b;
  --ink-2: #56607241;      /* placeholder, overridden below */
  --ink-2: #566072;
  --ink-3: #7d8798;
  --line: #dfe4ec;
  --line-2: #eaeef4;
  --accent: #1e50e0;
  --accent-2: #2b5cf0;
  --accent-ink: #12318c;
  --accent-wash: #eef2fe;

  --shadow-1: 0 1px 2px rgba(16, 22, 40, 0.04), 0 4px 14px rgba(16, 22, 40, 0.05);
  --shadow-2: 0 2px 6px rgba(16, 22, 40, 0.06), 0 18px 44px rgba(16, 22, 40, 0.10);

  --r-card: 10px;
  --r-ctl: 8px;
  --r-input: 6px;

  --sans: "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in: cubic-bezier(0.7, 0, 0.84, 0);
  --press: 100ms ease-out;

  --bar: 62px;
  --gutter: clamp(1.15rem, 4vw, 2.75rem);
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

/* The UA hides [hidden] with display:none, which ANY author display rule
   beats. .ms-opt is display:flex, so filtered-out options stayed on screen
   while their .hidden property read true. Make the attribute win. */
[hidden] { display: none !important; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.6;
  letter-spacing: 0;
  font-optical-sizing: auto;
  -webkit-tap-highlight-color: transparent;
}

/* apple-design 15: tracking and leading are size specific. One value across
   the scale is always wrong somewhere. */
h1, h2, h3, h4 { margin: 0; text-wrap: balance; font-optical-sizing: auto; }
h1 { font-size: clamp(2.1rem, 4.6vw, 3.5rem); line-height: 1.02; letter-spacing: -0.038em; font-weight: 700; }
h2 { font-size: clamp(1.55rem, 2.9vw, 2.3rem); line-height: 1.08; letter-spacing: -0.028em; font-weight: 700; }
h3 { font-size: 1.06rem; line-height: 1.25; letter-spacing: -0.014em; font-weight: 600; }
h4 { font-size: 0.95rem; line-height: 1.35; letter-spacing: -0.008em; font-weight: 600; }
p { margin: 0; }
img { max-width: 100%; height: auto; display: block; }
a { color: var(--accent); text-underline-offset: 3px; }
a, button { touch-action: manipulation; }
::selection { background: rgba(43, 92, 240, 0.2); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

.skip-link {
  position: absolute; left: 1rem; top: -3rem; z-index: 90;
  background: var(--ink); color: #fff; padding: 0.5rem 1rem;
  border-radius: var(--r-ctl); transition: top 160ms var(--ease);
}
.skip-link:focus-visible { top: 0.75rem; }

.wrap { max-width: 1280px; margin-inline: auto; padding-inline: var(--gutter); }

.eyebrow {
  font-family: var(--mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.14em;      /* small type opens up */
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.9rem;
}

/* ============================================================ header + mega */

.site-header {
  position: sticky; top: 0; z-index: 60;
  background: color-mix(in srgb, #ffffff 68%, transparent);
  backdrop-filter: blur(16px) saturate(170%);
  -webkit-backdrop-filter: blur(16px) saturate(170%);
  transition: background-color 260ms var(--ease), backdrop-filter 260ms var(--ease);
}
/* apple-design 12: a scroll edge, not a permanent divider. */
.site-header::after {
  content: ""; position: absolute; inset: 100% 0 auto 0; height: 16px;
  background: linear-gradient(rgba(16, 22, 40, 0.08), rgba(16, 22, 40, 0));
  opacity: 0; pointer-events: none; transition: opacity 260ms var(--ease);
}
.site-header.is-scrolled {
  background: color-mix(in srgb, #ffffff 84%, transparent);
  backdrop-filter: blur(24px) saturate(185%);
  -webkit-backdrop-filter: blur(24px) saturate(185%);
}
.site-header.is-scrolled::after { opacity: 1; }

.site-header > .wrap {
  display: flex; align-items: center; gap: 1.25rem; height: var(--bar);
}
.wordmark {
  display: inline-flex; align-items: center; gap: 0.6rem;
  font-size: 0.94rem; font-weight: 500; letter-spacing: 0.05em;
  color: var(--ink); text-decoration: none; white-space: nowrap;
}
.wordmark img { width: 32px; height: 32px; }
.wordmark b { color: var(--accent); font-weight: 700; }

.site-nav { display: flex; align-items: center; gap: 0.15rem; margin-left: auto; }
.site-nav a, .nav-products {
  font: inherit; font-size: 0.92rem; font-weight: 500;
  color: var(--ink-2); text-decoration: none;
  background: none; border: 0; cursor: pointer;
  padding: 0.45rem 0.8rem; border-radius: var(--r-ctl);
  display: inline-flex; align-items: center; gap: 0.4rem;
  transition: color 160ms var(--ease), background-color 160ms var(--ease);
}
.site-nav a:hover, .nav-products:hover { color: var(--ink); background: rgba(16, 20, 27, 0.05); }
.site-nav a[aria-current="page"] { color: var(--accent); background: var(--accent-wash); }
.nav-products svg { transition: transform 260ms var(--ease); }
.nav-products[aria-expanded="true"] { color: var(--accent); background: var(--accent-wash); }
.nav-products[aria-expanded="true"] svg { transform: rotate(180deg); }

.header-cta { display: flex; align-items: center; gap: 0.6rem; }

.mega {
  position: absolute; inset: 100% 0 auto 0;
  background: color-mix(in srgb, #ffffff 92%, transparent);
  backdrop-filter: blur(26px) saturate(180%);
  -webkit-backdrop-filter: blur(26px) saturate(180%);
  border-top: 1px solid var(--line-2);
  box-shadow: var(--shadow-2);
  /* apple-design 7: grows from the control that opened it. */
  transform-origin: var(--mega-origin, 50%) top;
  will-change: transform, opacity, filter;
}
.mega-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 2rem; padding-block: 2rem 1.5rem;
}
.mega-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem;
  text-decoration: none; color: var(--ink);
  padding-bottom: 0.6rem; margin-bottom: 0.7rem;
  border-bottom: 1px solid var(--line);
}
.mega-head span { font-weight: 600; font-size: 0.95rem; }
.mega-head small {
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.06em;
  color: var(--ink-3); white-space: nowrap;
}
.mega-head:hover span { color: var(--accent); }
.mega-col ul { list-style: none; margin: 0; padding: 0; }
.mega-col li + li { margin-top: 0.1rem; }
.mega-col a {
  display: block; padding: 0.3rem 0.5rem; margin-inline: -0.5rem;
  font-size: 0.875rem; color: var(--ink-2); text-decoration: none;
  border-radius: var(--r-input); line-height: 1.35;
  transition: color 140ms var(--ease), background-color 140ms var(--ease);
}
.mega-col a:hover { color: var(--accent); background: var(--accent-wash); }
.mega-foot {
  display: flex; flex-wrap: wrap; gap: 1.5rem;
  border-top: 1px solid var(--line-2); padding-block: 0.9rem 1.1rem;
}
.mega-foot a { font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.03em; }

.nav-toggle {
  display: none; background: none; border: 1px solid var(--line);
  border-radius: var(--r-ctl); padding: 0.42rem 0.6rem; cursor: pointer; color: var(--ink);
}
.nav-toggle svg { display: block; }

@media (max-width: 979px) {
  .site-nav { display: none; }
  .nav-toggle { display: block; }
  .mega-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1.5rem; }
}
@media (max-width: 639px) {
  .header-cta .btn-sm { display: none; }
  .mega-grid { grid-template-columns: 1fr; }
  .mega { max-height: calc(100dvh - var(--bar)); overflow-y: auto; }
}

/* ================================================================= buttons */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  font: inherit; font-size: 0.94rem; font-weight: 500;
  padding: 0.72rem 1.3rem; border-radius: var(--r-ctl);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  border: 1px solid transparent;
  transition: transform 180ms var(--ease), background-color 180ms var(--ease),
              border-color 180ms var(--ease), color 180ms var(--ease),
              box-shadow 180ms var(--ease);
}
.btn-sm { padding: 0.48rem 0.95rem; font-size: 0.87rem; }
.btn-primary {
  background: var(--accent-2); color: #fff; border-color: var(--accent-2);
  box-shadow: 0 1px 2px rgba(30, 80, 224, 0.3), 0 8px 20px rgba(30, 80, 224, 0.22);
}
.btn-primary:hover { background: var(--accent); border-color: var(--accent); }
.btn-ghost { background: var(--surface); color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); }
.header-cta .btn-sm { background: var(--ink); color: #fff; border-color: var(--ink); }
.header-cta .btn-sm:hover { background: var(--accent); border-color: var(--accent); }
.btn:hover { transform: translateY(-1px); }
/* apple-design 1: the press is the feedback, and it is instant. */
.btn:active, .btn.is-pressed { transform: translateY(0) scale(0.975); transition-duration: var(--press); }
.magnetic { will-change: transform; }

/* ==================================================================== hero */

.hero {
  position: relative; overflow: hidden;
  background: linear-gradient(180deg, #fbfcfe 0%, var(--paper) 62%);
  border-bottom: 1px solid var(--line-2);
}
.hero-grid {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(30, 80, 224, 0.055) 1px, transparent 1px),
    linear-gradient(90deg, rgba(30, 80, 224, 0.055) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(900px 520px at 62% 30%, #000 10%, transparent 76%);
  -webkit-mask-image: radial-gradient(900px 520px at 62% 30%, #000 10%, transparent 76%);
}
.hero > .wrap { position: relative; padding-block: clamp(3.5rem, 9vw, 6.5rem) clamp(2.5rem, 6vw, 4rem); }
.hero h1 { max-width: 16ch; }
.hero h1 em { font-style: normal; color: var(--accent); }
.hero-lead {
  margin-top: 1.5rem; max-width: 56ch;
  font-size: clamp(1.02rem, 1.35vw, 1.16rem); color: var(--ink-2);
}
.hero-cta { margin-top: 2.2rem; display: flex; flex-wrap: wrap; gap: 0.75rem; }

.hero-stats {
  margin: clamp(2.5rem, 6vw, 4rem) 0 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden;
}
.hero-stats > div { background: var(--surface); padding: 1.15rem 1.25rem; }
.hero-stats dt {
  font-family: var(--mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--ink-3);
}
.hero-stats dd {
  margin: 0.4rem 0 0; font-family: var(--mono); font-weight: 600;
  font-size: clamp(1.15rem, 2vw, 1.6rem); letter-spacing: -0.02em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.hero-stats sup { font-size: 0.5em; }
@media (max-width: 719px) { .hero-stats { grid-template-columns: repeat(2, 1fr); } }

.market-strip { border-top: 1px solid var(--line-2); background: color-mix(in srgb, #fff 55%, transparent); }
.market-strip .wrap {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.5rem;
  padding-block: 1rem;
}
.market-strip p {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-3);
}
.markets { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.markets span {
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.02em;
  padding: 0.3rem 0.7rem; border: 1px solid var(--line);
  border-radius: var(--r-input); background: var(--surface); color: var(--ink-2);
}
.markets-lg span { font-size: 0.8rem; padding: 0.4rem 0.85rem; }
.markets-lg { margin-top: 1.5rem; }

/* ================================================================ sections */

.section { padding-block: clamp(3.5rem, 8vw, 6rem); }
.section-tight { padding-block: clamp(1rem, 3vw, 2rem) clamp(3.5rem, 8vw, 6rem); }
.section-alt { background: var(--paper-2); border-block: 1px solid var(--line-2); }
.sec-head { max-width: 62ch; margin-bottom: clamp(1.75rem, 4vw, 2.75rem); }
.sec-head p { margin-top: 0.85rem; color: var(--ink-2); font-size: 1.02rem; }
.sec-more { margin-top: 2rem; font-size: 0.95rem; }

.page-head { padding-block: clamp(1.5rem, 4vw, 2.5rem) clamp(2rem, 5vw, 3rem); }
.page-head h1 { max-width: 20ch; }
.page-lead { margin-top: 1.1rem; max-width: 68ch; color: var(--ink-2); font-size: 1.06rem; }
.page-facts {
  margin-top: 1.4rem; font-family: var(--mono); font-size: 0.8rem;
  letter-spacing: 0.02em; color: var(--ink-2);
}
.page-facts b { color: var(--accent); font-weight: 600; }
.page-facts span { color: var(--line); margin-inline: 0.4rem; }

.crumbs { font-family: var(--mono); font-size: 0.72rem; color: var(--ink-3); padding-top: 1.5rem; }
.crumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 0.45rem; margin: 0; padding: 0; }
.crumbs li + li::before { content: "/"; margin-right: 0.45rem; color: var(--line); }
.crumbs a { color: var(--ink-3); text-decoration: none; }
.crumbs a:hover { color: var(--accent); text-decoration: underline; }

/* ========================================================== division cards */

.dcs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.dc {
  display: grid; grid-template-rows: auto 1fr auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden;
  text-decoration: none; color: var(--ink);
  transition: border-color 220ms var(--ease), transform 220ms var(--ease),
              box-shadow 220ms var(--ease);
}
.dc:hover { border-color: rgba(30, 80, 224, 0.4); transform: translateY(-2px); box-shadow: var(--shadow-2); }
.dc:active, .dc.is-pressed { transform: translateY(0) scale(0.994); transition-duration: var(--press); }
.dc-ph { display: block; aspect-ratio: 21 / 9; background: #fbfcfe; border-bottom: 1px solid var(--line-2); overflow: hidden; }
.dc-ph img { width: 100%; height: 100%; object-fit: contain; padding: 1.25rem; mix-blend-mode: multiply; transition: transform 500ms var(--ease); }
.dc:hover .dc-ph img { transform: scale(1.035); }
.dc-body { display: block; padding: 1.35rem 1.4rem 0.5rem; }
.dc-name { display: block; font-size: 1.14rem; font-weight: 600; letter-spacing: -0.016em; }
.dc-lead { display: block; margin-top: 0.5rem; color: var(--ink-2); font-size: 0.92rem; }
.dc-count {
  display: block; padding: 0.9rem 1.4rem 1.3rem;
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.05em; color: var(--accent);
}
@media (max-width: 859px) { .dcs { grid-template-columns: 1fr; } }

/* =========================================================== product cards */

.pcs { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
.pc {
  display: grid; grid-template-rows: auto 1fr auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden;
  text-decoration: none; color: var(--ink);
  transition: border-color 200ms var(--ease), transform 200ms var(--ease),
              box-shadow 200ms var(--ease);
}
.pc:hover { border-color: rgba(30, 80, 224, 0.4); transform: translateY(-2px); box-shadow: var(--shadow-2); }
.pc:active, .pc.is-pressed { transform: translateY(0) scale(0.99); transition-duration: var(--press); }
.pc-ph { display: block; aspect-ratio: 4 / 3; background: #fbfcfe; border-bottom: 1px solid var(--line-2); overflow: hidden; }
.pc-ph img { width: 100%; height: 100%; object-fit: contain; padding: 1rem; mix-blend-mode: multiply; transition: transform 450ms var(--ease); }
.pc:hover .pc-ph img { transform: scale(1.04); }
.pc-fig {
  display: flex; flex-direction: column; justify-content: center;
  aspect-ratio: 4 / 3; padding: 1.4rem;
  background:
    radial-gradient(420px 200px at 20% 0%, rgba(30, 80, 224, 0.07), transparent 70%),
    #fbfcfe;
  border-bottom: 1px solid var(--line-2);
}
.pc-fig b {
  font-family: var(--mono); font-weight: 600; font-size: clamp(1.3rem, 2.4vw, 1.85rem);
  letter-spacing: -0.03em; color: var(--accent); font-variant-numeric: tabular-nums;
}
.pc-fig small { margin-top: 0.4rem; font-size: 0.74rem; color: var(--ink-3); letter-spacing: 0.02em; }
.pc-body { display: block; padding: 1.15rem 1.2rem 0.4rem; }
.pc-name { display: block; font-size: 1rem; font-weight: 600; letter-spacing: -0.012em; }
.pc-tag { display: block; margin-top: 0.35rem; color: var(--ink-2); font-size: 0.875rem; line-height: 1.45; }
.pc-meta {
  display: block; padding: 0.85rem 1.2rem 1.15rem;
  font-family: var(--mono); font-size: 0.69rem; letter-spacing: 0.05em; color: var(--ink-3);
}
.pc:hover .pc-meta { color: var(--accent); }
@media (max-width: 979px) { .pcs { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 599px) { .pcs { grid-template-columns: 1fr; } }

/* ======================================================== product page */

.product-layout {
  display: grid; grid-template-columns: 232px minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 4rem);
  padding-bottom: clamp(3rem, 7vw, 5rem);
  align-items: start;
}
/* A grid column's default min-width is auto, so a max-content table inside it
   pushes the column wider than the viewport instead of scrolling in its rail.
   Every track that can hold a table is pinned to minmax(0, ...). */
.product-layout > * { min-width: 0; }
.side { position: sticky; top: calc(var(--bar) + 1.5rem); }
.side-head {
  font-family: var(--mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
  padding-bottom: 0.7rem; border-bottom: 1px solid var(--line); margin-bottom: 0.5rem;
}
.side-list { list-style: none; margin: 0 0 1.25rem; padding: 0; }
.side-list a {
  display: block; padding: 0.4rem 0.6rem; margin-inline: -0.6rem;
  font-size: 0.875rem; line-height: 1.35; color: var(--ink-2);
  text-decoration: none; border-radius: var(--r-input);
  transition: color 140ms var(--ease), background-color 140ms var(--ease);
}
.side-list a:hover { color: var(--accent); background: var(--accent-wash); }
.side-list a[aria-current="page"] { color: var(--accent); background: var(--accent-wash); font-weight: 600; }
.side-cta { width: 100%; background: var(--surface); border-color: var(--line); color: var(--ink); }
.side-cta:hover { border-color: var(--accent); color: var(--accent); }
@media (max-width: 899px) {
  .product-layout { grid-template-columns: minmax(0, 1fr); }
  .side { position: static; }
  .side-list { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 1rem; }
  .side-list a { border: 1px solid var(--line); background: var(--surface); margin: 0; padding: 0.35rem 0.7rem; }
  .side-cta { width: auto; }
}

.product > * + * { margin-top: clamp(2rem, 4.5vw, 3rem); }
.product-head { margin-top: 0 !important; }
.product-head h1 { max-width: 18ch; }
.product-tag { margin-top: 0.8rem; font-size: 1.1rem; color: var(--accent); letter-spacing: -0.01em; }
.product .lead { font-size: 1.06rem; color: var(--ink-2); max-width: 72ch; }
.product .prose { color: var(--ink-2); max-width: 72ch; }
.product h2 {
  font-size: 1.22rem; letter-spacing: -0.016em; font-weight: 600;
  padding-bottom: 0.7rem; margin-bottom: 1.1rem; border-bottom: 1px solid var(--line);
}

.hero-plate {
  margin: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: clamp(1.25rem, 3vw, 2rem);
}
.hero-plate img { max-height: 300px; width: auto; margin-inline: auto; mix-blend-mode: multiply; }
.hero-figure {
  margin: 0; padding: clamp(1.5rem, 3.5vw, 2.25rem);
  background:
    radial-gradient(520px 240px at 12% 0%, rgba(30, 80, 224, 0.09), transparent 72%),
    var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-card);
  display: flex; flex-direction: column;
}
.hero-figure b {
  font-family: var(--mono); font-weight: 600; font-size: clamp(1.9rem, 4vw, 2.9rem);
  letter-spacing: -0.035em; color: var(--accent); font-variant-numeric: tabular-nums;
}
.hero-figure small { margin-top: 0.45rem; color: var(--ink-3); font-size: 0.84rem; }

/* spec table: the thing procurement actually reads */
.spec-table {
  margin: 0; border: 1px solid var(--line); border-radius: var(--r-card);
  overflow: hidden; background: var(--surface);
}
.spec-row {
  display: grid; grid-template-columns: 180px minmax(0, 1fr);
  gap: 1.25rem; padding: 0.85rem 1.15rem;
  border-bottom: 1px solid var(--line-2);
}
.spec-row:last-child { border-bottom: 0; }
.spec-row:nth-child(odd) { background: #fcfdff; }
.spec-row dt {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-3);
  padding-top: 0.18rem;
}
.spec-row dd { margin: 0; font-size: 0.94rem; line-height: 1.55; }
@media (max-width: 599px) {
  .spec-row { grid-template-columns: 1fr; gap: 0.3rem; }
}

.feature-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.feature-list li {
  position: relative; padding-left: 1.6rem; color: var(--ink-2);
  font-size: 0.94rem; line-height: 1.55;
}
.feature-list li::before {
  content: ""; position: absolute; left: 0.25rem; top: 0.62rem;
  width: 6px; height: 6px; border-radius: 1px; background: var(--accent);
}

.onreq ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.onreq li {
  padding: 0.75rem 1rem; background: var(--accent-wash);
  border: 1px solid rgba(30, 80, 224, 0.18); border-radius: var(--r-input);
  font-size: 0.9rem; color: var(--accent-ink);
}

/* ============================================================ part tables */

.parts-intro { margin-bottom: 1.25rem; color: var(--ink-2); font-size: 0.94rem; }
.parts { margin: 0 0 1.5rem; }
.parts figcaption {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: 0.5rem; margin-bottom: 0.6rem;
}
.pt-cap {
  font-family: var(--mono); font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-2);
}
.pt-count { font-family: var(--mono); font-size: 0.68rem; color: var(--ink-3); }
.pt-rail, .pn-rail {
  overflow-x: auto; overflow-y: hidden;
  border: 1px solid var(--line); border-radius: var(--r-card);
  background: var(--surface); scrollbar-width: thin;
}
/* apple-design 2 + 9: main.js tracks 1:1, rubber-bands and projects the flick.
   No scroll-snap here: our own projection owns the landing point, and CSS snap
   re-snaps the container the instant the rubber-band transform lands. */
[data-drag-scroll] { cursor: grab; overscroll-behavior-x: contain; }
[data-drag-scroll].is-dragging { cursor: grabbing; user-select: none; }
[data-drag-scroll].is-dragging a { pointer-events: none; }
[data-drag-scroll] > * { will-change: transform; }
.pt-rail:focus-visible, .pn-rail:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.pt { width: 100%; min-width: max-content; border-collapse: collapse; font-size: 0.88rem; }
.pt th {
  text-align: left; font-family: var(--mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase; color: var(--ink-3);
  padding: 0.65rem 1.1rem; background: var(--paper-2);
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
.pt td {
  padding: 0.6rem 1.1rem; border-bottom: 1px solid var(--line-2);
  vertical-align: top; white-space: nowrap;
}
.pt tbody tr:last-child td { border-bottom: 0; }
.pt tbody tr:hover td { background: #fafbff; }
.pt .pn {
  font-family: var(--mono); font-weight: 500; letter-spacing: 0.01em;
  color: var(--accent); font-variant-numeric: tabular-nums;
}
.pt-legend {
  margin-top: 0.7rem; font-size: 0.82rem; line-height: 1.55;
  color: var(--ink-3); max-width: 78ch;
}

/* ========================================================= ordering guide */

.ordering { }
.ordering-sub { margin-top: -0.4rem; margin-bottom: 1rem; color: var(--ink-2); font-size: 0.94rem; }
.ordering-code {
  font-family: var(--mono); font-weight: 600;
  font-size: clamp(1rem, 2.4vw, 1.5rem); letter-spacing: 0.01em;
  color: var(--accent); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-card);
  padding: 1rem 1.2rem; overflow-x: auto; white-space: nowrap;
}
.ok {
  margin: 0.9rem 0 0; display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: 0.6rem;
}
.ok-row {
  display: grid; grid-template-columns: 3.2rem minmax(0, 1fr); gap: 0.8rem;
  align-items: baseline; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-input); padding: 0.8rem 0.95rem;
}
.ok-row dt { font-family: var(--mono); font-size: 0.78rem; font-weight: 600; color: var(--accent); }
.ok-row dd { margin: 0; font-size: 0.87rem; line-height: 1.5; color: var(--ink-2); }

/* ==================================================== part number builder */

.builder {
  background:
    radial-gradient(700px 320px at 8% 0%, rgba(30, 80, 224, 0.08), transparent 70%),
    var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-card);
  padding: clamp(1.35rem, 3.5vw, 2rem);
}
.builder h2 { border: 0; padding: 0; margin-bottom: 0.6rem; }
.builder-head p { color: var(--ink-2); font-size: 0.94rem; max-width: 60ch; }
.builder-out {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem;
  margin: 1.35rem 0 1.5rem; padding: 0.95rem 1.1rem;
  background: var(--ink); border-radius: var(--r-ctl);
}
.bo-code {
  flex: 1 1 auto; min-width: 0;
  font-family: var(--mono); font-weight: 600;
  font-size: clamp(0.95rem, 2.2vw, 1.35rem); letter-spacing: 0.01em;
  color: #eaf0ff; overflow-x: auto; white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.bo-code .seg { transition: color 200ms var(--ease); }
.bo-code .seg.just-set { color: #7fa4ff; }
.bo-copy {
  font: inherit; font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: #cfdcff; cursor: pointer;
  background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.18);
  border-radius: var(--r-input); padding: 0.4rem 0.75rem;
  transition: background-color 160ms var(--ease), color 160ms var(--ease), transform 160ms var(--ease);
}
.bo-copy:hover { background: rgba(255, 255, 255, 0.18); color: #fff; }
.bo-copy:active { transform: scale(0.95); transition-duration: var(--press); }
.bo-copy.done { background: #2f9e5f; border-color: #2f9e5f; color: #fff; }

.bfields { display: grid; gap: 1.15rem; }
.blabel {
  font-size: 0.86rem; color: var(--ink-2); margin-bottom: 0.5rem;
  display: flex; align-items: baseline; gap: 0.55rem;
}
.bkey {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.08em; color: var(--accent);
  background: var(--accent-wash); border-radius: 4px; padding: 0.1rem 0.4rem;
}
.boptions { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.bo {
  font: inherit; font-size: 0.86rem; cursor: pointer;
  background: var(--surface); color: var(--ink-2);
  border: 1px solid var(--line); border-radius: var(--r-input);
  padding: 0.45rem 0.85rem;
  transition: border-color 160ms var(--ease), color 160ms var(--ease),
              background-color 160ms var(--ease), transform 160ms var(--ease);
}
.bo:hover { border-color: var(--accent); color: var(--accent); }
.bo:active, .bo.is-pressed { transform: scale(0.96); transition-duration: var(--press); }
.bo[aria-checked="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 500;
}

/* ================================================= part number index page */

.pn-search {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: 0.85rem; margin-bottom: 1.1rem;
}
.pn-search label {
  font-family: var(--mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.pn-search input {
  font: inherit; font-size: 0.95rem; width: 100%;
  padding: 0.65rem 0.9rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-input); color: var(--ink);
}
.pn-search input:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent); }
.pn-count {
  font-family: var(--mono); font-size: 0.72rem; color: var(--ink-3);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}
.pn-rail { max-height: 70dvh; overflow-y: auto; }
.pt-index thead th { position: sticky; top: 0; z-index: 1; }
.pt-index td:nth-child(2), .pt-index td:nth-child(3) { white-space: normal; }
.pn-empty { margin-top: 1.5rem; color: var(--ink-2); }
@media (max-width: 639px) {
  .pn-search { grid-template-columns: 1fr; gap: 0.5rem; }
}

/* ======================================================= misc components */

.chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chips span {
  font-family: var(--mono); font-size: 0.8rem; letter-spacing: 0.01em;
  padding: 0.45rem 0.85rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-input); color: var(--ink-2);
}

.two-up {
  display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(1.75rem, 5vw, 4rem); align-items: start;
}
.two-up-lead { margin-top: 1rem; color: var(--ink-2); }
@media (max-width: 859px) { .two-up { grid-template-columns: 1fr; } }

.code-demo {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: clamp(1.35rem, 3vw, 2rem);
}
.cd-label {
  font-family: var(--mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
}
.cd-code {
  margin-top: 0.9rem; font-family: var(--mono); font-weight: 600;
  font-size: clamp(1rem, 2.2vw, 1.35rem); letter-spacing: 0.01em;
  color: var(--ink); overflow-x: auto; white-space: nowrap;
}
.cd-code em { font-style: normal; color: var(--accent); }
.cd-note { margin-top: 0.9rem; font-size: 0.88rem; color: var(--ink-3); }

.aps { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); gap: 0.85rem; }
.ap {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 1.2rem 1.25rem;
}
.ap-name { font-weight: 600; font-size: 0.98rem; letter-spacing: -0.01em; }
.ap-by { margin-top: 0.3rem; font-size: 0.84rem; color: var(--ink-3); }
.ap-ref {
  margin-top: 0.75rem; font-family: var(--mono); font-size: 0.72rem;
  letter-spacing: 0.02em; color: var(--accent); word-break: break-word;
}
.ap-rows { display: grid; gap: 0.7rem; }
.ap-row {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 6fr) minmax(0, 3fr);
  gap: clamp(1rem, 3vw, 2rem); align-items: start;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 1.2rem 1.35rem;
}
.ap-desc { color: var(--ink-2); font-size: 0.9rem; }
@media (max-width: 899px) { .ap-row { grid-template-columns: 1fr; gap: 0.5rem; } }

.people, .sts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); gap: 0.9rem; }
.person, .st {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 1.5rem;
}
.person .role {
  margin-top: 0.3rem; font-family: var(--mono); font-size: 0.68rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent);
}
.person p:last-child, .st p { margin-top: 0.8rem; color: var(--ink-2); font-size: 0.92rem; }

.machines { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr)); gap: 0.55rem; }
.machines li {
  position: relative; padding: 0.75rem 1rem 0.75rem 2.2rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-input); font-size: 0.9rem;
}
.machines li::before {
  content: ""; position: absolute; left: 1rem; top: 1.18rem;
  width: 6px; height: 6px; border-radius: 1px; background: var(--accent);
}
.checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.7rem; }
.checks li {
  padding: 1rem 1.15rem; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-input);
  color: var(--ink-2); font-size: 0.94rem;
}
.serves { list-style: none; margin: 0 0 1rem; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.serves li {
  font-size: 0.88rem; padding: 0.45rem 0.9rem; background: var(--accent-wash);
  border: 1px solid rgba(30, 80, 224, 0.18); border-radius: var(--r-input);
  color: var(--accent-ink);
}

.ics { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
.ic {
  display: grid; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden; text-decoration: none; color: var(--ink);
  transition: border-color 200ms var(--ease), transform 200ms var(--ease), box-shadow 200ms var(--ease);
}
.ic:hover { border-color: rgba(30, 80, 224, 0.4); transform: translateY(-2px); box-shadow: var(--shadow-2); }
.ic-ph { display: block; aspect-ratio: 16 / 9; overflow: hidden; }
.ic-ph img { width: 100%; height: 100%; object-fit: cover; filter: saturate(0.85); transition: transform 500ms var(--ease); }
.ic:hover .ic-ph img { transform: scale(1.04); }
.ic-body { display: block; padding: 1.3rem 1.4rem 1.5rem; }
.ic-name { display: block; font-size: 1.14rem; font-weight: 600; letter-spacing: -0.016em; }
.ic-lead { display: block; margin-top: 0.5rem; color: var(--ink-2); font-size: 0.92rem; }
@media (max-width: 859px) { .ics { grid-template-columns: 1fr; } }

/* ===================================================================== cta */

.cta {
  background:
    radial-gradient(700px 300px at 15% 0%, rgba(30, 80, 224, 0.1), transparent 70%),
    var(--paper-2);
  border-block: 1px solid var(--line-2);
}
.cta .wrap {
  padding-block: clamp(2.75rem, 7vw, 4.5rem);
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: 1.75rem;
}
.cta h2 { max-width: 20ch; }
.cta p { margin-top: 0.7rem; color: var(--ink-2); max-width: 46ch; }

/* ================================================================= contact */

.contact-grid {
  display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
  gap: clamp(2rem, 5vw, 4rem); align-items: start;
  padding-bottom: clamp(3rem, 7vw, 5rem);
}
@media (max-width: 859px) { .contact-grid { grid-template-columns: 1fr; } }
.facts { list-style: none; margin: 0; padding: 0; }
.facts li { padding: 1rem 0; border-bottom: 1px solid var(--line); font-size: 0.95rem; }
.facts .k {
  display: block; margin-bottom: 0.3rem;
  font-family: var(--mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.field { display: flex; flex-direction: column; gap: 0.45rem; margin-bottom: 1.25rem; }
.field label { font-size: 0.92rem; font-weight: 500; }
.field .hint { color: var(--ink-3); font-weight: 400; }
.field input, .field textarea, .field select {
  font: inherit; color: var(--ink); background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-input);
  padding: 0.7rem 0.9rem; width: 100%;
}
.field textarea { resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: #98a1b2; }
.field input:focus-visible, .field textarea:focus-visible, .field select:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 0; border-color: var(--accent);
}
.err { color: #c02b1e; font-size: 0.85rem; display: none; }
.field.invalid .err { display: block; }
.field.invalid input, .field.invalid textarea { border-color: #c02b1e; }
.form-note { margin-top: 0.9rem; font-size: 0.86rem; color: var(--ink-3); max-width: 50ch; }

/* ================================================================== footer */

.site-footer { background: var(--paper-2); border-top: 1px solid var(--line-2); color: var(--ink-2); }
.site-footer .wrap { padding-block: clamp(2.5rem, 6vw, 3.5rem) 1.5rem; }
.footer-top { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 8fr); gap: 2.5rem; }
.site-footer .wordmark { color: var(--ink); }
.site-footer address { font-style: normal; margin-top: 1rem; font-size: 0.88rem; line-height: 1.65; }
.footer-contact { margin-top: 0.9rem; font-size: 0.88rem; line-height: 1.8; }
.footer-cols { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1.5rem; }
.site-footer h3 {
  font-family: var(--mono); font-size: 0.64rem; font-weight: 600;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--ink-3); margin-bottom: 0.9rem;
}
.footer-cols ul { list-style: none; margin: 0; padding: 0; }
.footer-cols li { margin-bottom: 0.42rem; }
.site-footer a { color: var(--ink-2); text-decoration: none; font-size: 0.845rem; line-height: 1.4; }
.site-footer a:hover { color: var(--accent); text-decoration: underline; }
.footer-bottom {
  margin-top: 2.5rem; padding-top: 1.15rem; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.5rem;
  font-size: 0.76rem; font-family: var(--mono); letter-spacing: 0.02em; color: var(--ink-3);
}
@media (max-width: 1099px) { .footer-cols { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 859px) {
  .footer-top { grid-template-columns: 1fr; gap: 2rem; }
  .footer-cols { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 499px) { .footer-cols { grid-template-columns: 1fr; } }

/* ================================================================= reveal */

/* .reveal now lives in the v6.6 block, scoped to .js */

/* ============================ accessibility preferences (apple-design 14) */

/* Reduced transparency: materials go frosty and solid, blur goes. */
@media (prefers-reduced-transparency: reduce) {
  .site-header, .site-header.is-scrolled, .mega {
    background: var(--surface);
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
  .site-header { border-bottom: 1px solid var(--line); }
  .site-header::after { display: none; }
}

/* Increased contrast: near-solid surfaces with defined borders. */
@media (prefers-contrast: more) {
  :root {
    --ink-2: #39424f; --ink-3: #4c5567;
    --line: #b4bdcc; --line-2: #c3cbd9; --accent: #1740c8;
  }
  .site-header, .mega { background: var(--surface); backdrop-filter: none; -webkit-backdrop-filter: none; }
  .pc, .dc, .ic, .ap, .ap-row, .person, .st, .machines li, .checks li,
  .spec-table, .pt-rail, .pn-rail, .ok-row, .ordering-code, .builder, .chips span {
    border-color: var(--ink-3);
  }
  a { text-decoration: underline; }
  .btn, .wordmark, .site-nav a, .pc, .dc, .ic, .crumbs a, .mega-col a,
  .side-list a, .mega-head { text-decoration: none; }
}

/* Reduced motion: cross-fade in place. Feedback stays, travel goes. */
@media (prefers-reduced-motion: reduce) {
  .btn:hover, .pc:hover, .dc:hover, .ic:hover { transform: none; }
  .pc:hover .pc-ph img, .dc:hover .dc-ph img, .ic:hover .ic-ph img { transform: none; }
  .mega { transform: none !important; filter: none !important; }
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
}

/* ==================================================================== print */

@media print {
  .site-header, .cta, .site-footer, .side, .builder { display: none; }
  body { background: #fff; }
  .pt-rail, .pn-rail { overflow: visible; max-height: none; }
  .pt { min-width: 0; font-size: 9pt; }
}

/* ==================================================================== v6.1
   Photography pass. The catalogue's own product shots now carry the site, so
   the hero is a real image (a video when the company supplies footage), the
   cards lead with the part, and the plant, machines and certificates appear
   as photographs rather than as claims. */

/* ---- media hero ---------------------------------------------------------- */

.hero { position: relative; border-bottom: 0; background: var(--ink); }
.hero-bg { position: absolute; inset: 0; overflow: hidden; }
.hero-bg img, .hero-bg video {
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 42%;
  filter: saturate(0.92) contrast(1.02);
}
/* Two stops: a dark wash for text contrast, and a blue cast that ties the
   photograph to the brand rather than letting it sit as a stock plate. */
.hero-bg::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(105deg, rgba(8, 12, 22, 0.94) 0%, rgba(8, 12, 22, 0.82) 38%,
                    rgba(8, 12, 22, 0.42) 68%, rgba(8, 12, 22, 0.34) 100%),
    linear-gradient(0deg, rgba(16, 30, 84, 0.34), rgba(16, 30, 84, 0.34));
}
.hero-inner {
  position: relative;
  padding-block: clamp(4rem, 11vw, 8rem) clamp(3rem, 7vw, 5rem);
}
.hero-inner .eyebrow { color: #8fb0ff; }
.hero-inner h1 { color: #fff; max-width: 15ch; }
.hero-inner h1 em { color: #8fb0ff; font-style: normal; }
.hero-lead { color: rgba(255, 255, 255, 0.82); max-width: 54ch; }
.btn-onmedia {
  background: rgba(255, 255, 255, 0.1); color: #fff;
  border-color: rgba(255, 255, 255, 0.42);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
}
.btn-onmedia:hover { background: rgba(255, 255, 255, 0.2); border-color: #fff; }

.hero-stats {
  position: relative; margin: 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px; background: rgba(255, 255, 255, 0.14);
  border-top: 1px solid rgba(255, 255, 255, 0.14);
}
.hero-stats > div {
  background: rgba(10, 14, 26, 0.55);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  padding: 1.1rem clamp(1.15rem, 4vw, 2.75rem);
}
.hero-stats dt { color: rgba(255, 255, 255, 0.55); }
.hero-stats dd { color: #fff; }
@media (max-width: 719px) { .hero-stats { grid-template-columns: repeat(2, 1fr); } }

.market-strip {
  position: relative; background: rgba(10, 14, 26, 0.72);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.market-strip p { color: rgba(255, 255, 255, 0.5); }
.market-strip .markets span {
  background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.2);
  color: rgba(255, 255, 255, 0.9);
}

/* ---- the parts strip under the hero -------------------------------------- */

.strip { background: var(--surface); border-bottom: 1px solid var(--line); }
.strip-rail {
  display: flex; gap: 1px; overflow-x: auto; scrollbar-width: thin;
  background: var(--line-2);
}
.sc {
  flex: 0 0 auto; width: 172px; background: var(--surface);
  padding: 1rem 0.9rem 0.9rem; text-decoration: none; color: var(--ink-2);
  display: grid; gap: 0.6rem; justify-items: center; text-align: center;
  transition: background-color 200ms var(--ease), color 200ms var(--ease);
}
.sc img { height: 74px; width: auto; object-fit: contain; mix-blend-mode: multiply; }
.sc span { font-size: 0.76rem; line-height: 1.3; }
.sc:hover { background: var(--accent-wash); color: var(--accent); }

/* ---- product hero plate -------------------------------------------------- */

.hero-plate { position: relative; }
.hero-plate img { max-height: 340px; }
.plate-fig {
  position: absolute; left: clamp(1.25rem, 3vw, 2rem); bottom: clamp(1.25rem, 3vw, 2rem);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-ctl); padding: 0.7rem 0.95rem; box-shadow: var(--shadow-1);
}
.plate-fig b {
  display: block; font-family: var(--mono); font-weight: 600;
  font-size: 1.25rem; letter-spacing: -0.03em; color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.plate-fig small { display: block; margin-top: 0.15rem; font-size: 0.7rem; color: var(--ink-3); }
@media (max-width: 599px) { .plate-fig { position: static; margin-top: 1rem; } }

/* ---- gallery ------------------------------------------------------------- */

.gs-rail {
  display: flex; gap: 0.75rem; overflow-x: auto;
  scrollbar-width: thin; padding-bottom: 0.5rem;
}
.gs {
  flex: 0 0 auto; margin: 0; width: min(300px, 74vw);
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 0.9rem;
}
.gs img { width: 100%; height: 200px; object-fit: contain; mix-blend-mode: multiply; }

/* ---- product cards lead with the part ------------------------------------ */

.pc-ph { aspect-ratio: 5 / 4; background: #fff; }
.pc-ph img { padding: 0.85rem; }
.dc-ph { background: #fff; }

/* ---- facility, machines, certificates, map ------------------------------- */

.units {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem; margin-top: 2.5rem;
}
.unit {
  margin: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden;
}
.unit img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
.unit figcaption {
  padding: 0.9rem 1.1rem 1.1rem; font-size: 0.88rem;
  color: var(--ink-2); border-top: 1px solid var(--line-2);
}
.unit figcaption b { color: var(--ink); font-weight: 600; margin-right: 0.35rem; }
@media (max-width: 719px) { .units { grid-template-columns: 1fr; } }

.mshots { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 0.75rem; }
.mshot {
  margin: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden;
}
.mshot img { width: 100%; aspect-ratio: 1 / 1; object-fit: contain; padding: 0.7rem; background: #fff; }
.mshot figcaption {
  padding: 0.6rem 0.8rem 0.85rem; font-size: 0.75rem; line-height: 1.35;
  color: var(--ink-2); border-top: 1px solid var(--line-2);
}
@media (max-width: 979px) { .mshots { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 599px) { .mshots { grid-template-columns: repeat(2, 1fr); } }
.img-note { margin-top: 1rem; font-size: 0.78rem; color: var(--ink-3); }

.certs {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0.85rem; margin-top: 1.5rem;
}
.cert {
  margin: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: 0.9rem;
}
.cert img { width: 100%; height: 230px; object-fit: contain; }
@media (max-width: 719px) { .certs { grid-template-columns: repeat(2, 1fr); } }

.map {
  margin: 0; background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: clamp(1rem, 3vw, 2rem);
}
.map img { width: 100%; max-width: 900px; margin-inline: auto; }

/* ---- industry cards get taller photography ------------------------------- */

.ic-ph { aspect-ratio: 16 / 10; }

/* ---- preference handling for the new media ------------------------------- */

@media (prefers-reduced-motion: reduce) {
  .hero-video { display: none; }
}
@media (prefers-reduced-transparency: reduce) {
  .hero-stats > div, .market-strip, .btn-onmedia {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: rgba(10, 14, 26, 0.92);
  }
}
@media (prefers-contrast: more) {
  .hero-bg::after {
    background: linear-gradient(105deg, rgba(4, 7, 14, 0.97) 0%,
                rgba(4, 7, 14, 0.9) 55%, rgba(4, 7, 14, 0.7) 100%);
  }
  .hero-lead { color: #fff; }
}
@media print {
  .hero-bg, .strip, .mshots, .certs { display: none; }
  .hero-inner h1, .hero-lead { color: #000; }
}

/* ---- let product photography fill its frame ------------------------------
   The catalogue's shots are studio sweeps: some on white, some on a light grey
   gradient. Floating them with padding on a white card drew a hard rectangle
   around every one. Filling the frame removes the seam entirely and reads the
   way a product catalogue should. The crop is a few percent on a centred
   subject, so nothing is cut off. */

.pc-ph, .dc-ph { background: #f2f4f7; }
.pc-ph img, .dc-ph img {
  width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 50%;
  padding: 0; mix-blend-mode: normal;
}
.pc:hover .pc-ph img, .dc:hover .dc-ph img { transform: scale(1.035); }

.sc img {
  height: 88px; width: 100%;
  object-fit: cover; border-radius: 4px;
  mix-blend-mode: normal;
}

.gs img { mix-blend-mode: normal; object-fit: cover; height: 210px; border-radius: 4px; }

/* The product page plate keeps `contain`: at that size the whole part must be
   visible, and the plate's own tone is close enough to the sweep to hide the
   join. */
.hero-plate { background: #f6f7f9; }
.hero-plate img {
  mix-blend-mode: normal;
  border-radius: calc(var(--r-card) - 4px);
  width: 100%; max-height: 380px; object-fit: cover;
}

.mshot img { mix-blend-mode: normal; }

/* ==================================================================== v6.2
   Proportion fix.

   v6.1 filled every frame with `object-fit: cover` to hide the seam where a
   studio sweep met a white card. That was the wrong trade: the catalogue's
   shots run from 0.75:1 (weld pads, tall) to 1.46:1 (meltbolts, wide), so a
   fixed box cropped the tall ones badly and upscaled a 400px source about
   two times over.

   The fix is to stop cropping and stop guessing. Every <img> now carries its
   true intrinsic width and height, and each frame is painted with `--media-bg`,
   the colour of the sweep that shot was taken on (precomputed in imagemeta.py).
   The photo can then sit whole, at its own proportions, with no visible join
   and no upscaling. */

.pc-ph, .dc-ph, .sc-ph, .gs, .hero-plate, .mshot {
  background: var(--media-bg, #f2f4f7);
}

/* Cards: contain, centred, never blown up past what the file actually holds. */
.pc-ph, .dc-ph {
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.pc-ph img, .dc-ph img {
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  padding: 0;
  mix-blend-mode: normal;
  transition: transform 450ms var(--ease);
}
.pc:hover .pc-ph img, .dc:hover .dc-ph img { transform: scale(1.04); }

/* The product page plate shows the part at its own aspect. `aspect-ratio: auto`
   plus the intrinsic attributes means the browser reserves the right box before
   the file lands, so nothing jumps. */
.hero-plate {
  /* Column, so that when .plate-fig drops out of absolute positioning on a
     narrow screen it stacks under the photo instead of becoming a second flex
     item beside it and pushing the page wider than the viewport.
     The plate hugs the photo (fit-content) rather than stretching the column:
     a wide frame around a centred shot exaggerates any difference between the
     sweep in the file and the flat colour sampled from its corners. Hugging
     leaves a thin, even ring that reads as a mount. */
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  width: fit-content; max-width: 100%;
  margin-inline: auto;
  padding: clamp(0.75rem, 1.6vw, 1.1rem);
  min-height: 0;
}
.hero-plate img {
  width: auto; height: auto;
  max-width: 100%;
  max-height: min(420px, 60vh);
  object-fit: contain;
  border-radius: calc(var(--r-card) - 6px);
  mix-blend-mode: normal;
}

/* Gallery tiles: same rule, smaller box. */
.gs {
  display: flex; align-items: center; justify-content: center;
  height: 220px;
}
.gs img {
  width: auto; height: auto; max-width: 100%; max-height: 100%;
  object-fit: contain; border-radius: 4px; mix-blend-mode: normal;
}

/* Home strip thumbnails. */
.sc-ph {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 84px; border-radius: 4px; overflow: hidden;
}
.sc-ph img {
  width: auto; height: auto; max-width: 100%; max-height: 100%;
  object-fit: contain; mix-blend-mode: normal;
}

/* Machine tiles: frame carries the sweep colour, image sits in it at its own
   proportions like everything else. */
.mshot { display: flex; flex-direction: column; }
.mshot > a, .mshot picture { display: contents; }
.mshot img {
  width: auto; height: auto;
  aspect-ratio: auto;              /* beats the 1/1 set earlier in this file */
  max-width: calc(100% - 1.4rem); max-height: 186px;
  object-fit: contain; margin: 0.7rem auto;
  background: transparent;
}

/* Certificates are documents: show the whole page, never crop one. */
.cert img { object-fit: contain; height: auto; max-height: 260px; width: auto; max-width: 100%; margin-inline: auto; }
.cert { display: flex; align-items: center; justify-content: center; min-height: 260px; }

/* Facility and industry photography is scenic, so filling the frame is right
   there; only the part shots need to be shown whole. */
.unit img, .ic-ph img { object-fit: cover; width: 100%; height: 100%; }
.ic-ph { display: block; }

/* ==================================================================== v6.3
   The key figure moves off the photograph and sits beside it. A number laid
   over a part covers the part and reads as a sticker; alongside, it reads as
   a caption to it. */

.plate-row {
  display: flex; align-items: center; gap: clamp(1rem, 2.5vw, 2rem);
  flex-wrap: wrap;
}
.plate-row .hero-plate { margin-inline: 0; }

.plate-fig {
  /* No longer absolutely positioned, so it takes part in the row. */
  position: static;
  flex: 0 1 auto; min-width: 0;
  background: none; border: 0; box-shadow: none; padding: 0;
  border-left: 2px solid var(--accent);
  padding-left: clamp(0.85rem, 2vw, 1.15rem);
}
.plate-fig b {
  display: block; font-family: var(--mono); font-weight: 600;
  font-size: clamp(1.35rem, 2.6vw, 1.9rem); line-height: 1.1;
  letter-spacing: -0.03em; color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.plate-fig small {
  display: block; margin-top: 0.35rem;
  font-size: 0.8rem; line-height: 1.4; color: var(--ink-3);
  max-width: 18ch;
}

/* Narrow: the figure drops under the photo rather than squeezing beside it. */
@media (max-width: 719px) {
  .plate-row { flex-direction: column; align-items: flex-start; gap: 1rem; }
  .plate-row .hero-plate { width: 100%; }
  .plate-fig { border-left: 0; border-top: 2px solid var(--accent);
               padding-left: 0; padding-top: 0.8rem; }
  .plate-fig small { max-width: none; }
}

/* ---- searchable multi-select ---------------------------------------------
   The native <select multiple> stays in the DOM and stays the source of
   truth; JS hides it and puts this in front. With scripting off the native
   control is what you get, and it still submits. */

.ms { position: relative; }

.ms-control {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem;
  min-height: 2.75rem; padding: 0.4rem 0.5rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-input); cursor: text;
  transition: border-color 160ms var(--ease), box-shadow 160ms var(--ease);
}
.ms-control.is-open, .ms-control:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(30, 80, 224, 0.14);
}

.ms-chips { display: contents; }
.ms-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font-size: 0.82rem; line-height: 1.2;
  background: var(--accent-wash); color: var(--accent-ink);
  border: 1px solid rgba(30, 80, 224, 0.24);
  border-radius: var(--r-input); padding: 0.28rem 0.3rem 0.28rem 0.55rem;
  max-width: 100%;
}
.ms-chip > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ms-x {
  font: inherit; font-size: 1rem; line-height: 1;
  background: none; border: 0; cursor: pointer; color: var(--accent);
  padding: 0 0.2rem; border-radius: 3px;
  transition: background-color 140ms var(--ease), color 140ms var(--ease);
}
.ms-x:hover { background: rgba(30, 80, 224, 0.16); color: var(--accent-ink); }

.ms-input {
  flex: 1 1 8rem; min-width: 8rem;
  font: inherit; font-size: 0.95rem;
  border: 0; outline: 0; background: none; color: var(--ink);
  padding: 0.3rem 0.25rem;
}
.ms-input::placeholder { color: #98a1b2; }

.ms-clear {
  font: inherit; font-family: var(--mono); font-size: 0.66rem;
  letter-spacing: 0.08em; text-transform: uppercase;
  background: none; border: 0; cursor: pointer; color: var(--ink-3);
  padding: 0.3rem 0.4rem; border-radius: 4px;
}
.ms-clear:hover { color: var(--accent); background: var(--accent-wash); }

.ms-panel {
  position: absolute; z-index: 20; inset: calc(100% + 6px) 0 auto 0;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); box-shadow: var(--shadow-2);
  overflow: hidden;
  transform-origin: 50% top;
  will-change: transform, opacity;
}
.ms-scroll { max-height: 17rem; overflow-y: auto; padding: 0.35rem; scrollbar-width: thin; }

.ms-group {
  font-family: var(--mono); font-size: 0.62rem; font-weight: 600;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3);
  padding: 0.7rem 0.6rem 0.35rem;
}
.ms-opt {
  display: flex; align-items: center; gap: 0.55rem;
  padding: 0.45rem 0.6rem; border-radius: var(--r-input);
  font-size: 0.9rem; cursor: pointer; color: var(--ink-2);
}
/* Highlight follows the keyboard and the pointer alike, so both modes share
   one idea of "where am I". */
.ms-opt.on { background: var(--accent-wash); color: var(--accent-ink); }
.ms-opt[aria-selected="true"] { color: var(--ink); font-weight: 500; }
.ms-tick {
  flex: 0 0 auto; width: 15px; height: 15px; border-radius: 3px;
  border: 1px solid var(--line); background: var(--surface); position: relative;
}
.ms-opt[aria-selected="true"] .ms-tick { background: var(--accent); border-color: var(--accent); }
.ms-opt[aria-selected="true"] .ms-tick::after {
  content: ""; position: absolute; left: 4px; top: 1px;
  width: 4px; height: 8px; border: solid #fff;
  border-width: 0 2px 2px 0; transform: rotate(42deg);
}
.ms-empty { padding: 0.9rem 0.85rem; font-size: 0.88rem; color: var(--ink-3); }
.ms-count {
  margin-top: 0.45rem; font-family: var(--mono); font-size: 0.7rem;
  letter-spacing: 0.04em; color: var(--accent);
}
.ms-count:empty { margin: 0; }
.ms-hint { margin-top: 0.4rem; }

/* Without JS the native control is on show, so give it room to breathe. */
[data-multiselect] select[multiple] { padding: 0.4rem; min-height: 11rem; }

@media (prefers-reduced-motion: reduce) {
  .ms-panel { transform: none !important; }
}
@media (prefers-contrast: more) {
  .ms-control, .ms-panel { border-color: var(--ink-3); }
  .ms-tick { border-color: var(--ink-2); }
}


/* ---- quote form status + honeypot ---------------------------------------- */

/* Off-screen rather than display:none: some bots skip hidden inputs. */
.hp {
  position: absolute !important; left: -9999px !important;
  width: 1px; height: 1px; opacity: 0; pointer-events: none;
}
.form-note.is-busy { color: var(--ink-2); }
.form-note.is-ok {
  color: #1c6b45; background: #e9f7ef; border: 1px solid #bfe6cf;
  border-radius: var(--r-input); padding: 0.75rem 0.9rem; max-width: 46ch;
}
.form-note.is-bad {
  color: #a2261b; background: #fdeceb; border: 1px solid #f3c7c3;
  border-radius: var(--r-input); padding: 0.75rem 0.9rem; max-width: 46ch;
}
#quote-form button[type="submit"][disabled] { opacity: 0.6; cursor: progress; }

/* ==================================================================== v6.4
   Machine list, and the part table caption. */

/* The machine list used to be fourteen identical text chips, which read as an
   inventory rather than a capability. Each entry now carries an icon for its
   machine group and a line saying what it is there for. */
.machines {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 19rem), 1fr));
  gap: 0.6rem;
}
.mc {
  display: flex; align-items: flex-start; gap: 0.85rem;
  padding: 0.95rem 1.1rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card);
  transition: border-color 200ms var(--ease), transform 200ms var(--ease),
              box-shadow 200ms var(--ease);
}
.machines .mc::before { content: none; }   /* beats .machines li::before */
.machines .mc { padding-left: 1.1rem; }
.mc:hover {
  border-color: rgba(30, 80, 224, 0.35);
  transform: translateY(-1px);
  box-shadow: var(--shadow-1);
}
.mc-ic {
  flex: 0 0 auto;
  width: 34px; height: 34px; border-radius: 8px;
  display: grid; place-items: center;
  background: var(--accent-wash); color: var(--accent);
  border: 1px solid rgba(30, 80, 224, 0.16);
}
.mc-ic svg { width: 19px; height: 19px; display: block; }
.mc-t { min-width: 0; }
.mc-t b {
  display: block; font-size: 0.92rem; font-weight: 600;
  letter-spacing: -0.01em; line-height: 1.3; color: var(--ink);
}
.mc-t small {
  display: block; margin-top: 0.25rem;
  font-size: 0.79rem; line-height: 1.45; color: var(--ink-3);
}


/* ==================================================================== v6.5
   A real map, and a logo you can actually see. */

/* ---- world map ------------------------------------------------------------
   Replaces the catalogue's decorative colour-blocked picture. Land is a quiet
   ground so the markers carry all the meaning; the works gets a halo, the
   markets get plain dots. */

.map { padding: clamp(1.25rem, 3vw, 2.25rem); }
.wmap { display: block; width: 100%; height: auto; }

.wmap-land {
  fill: #dde3ec;
  stroke: #ccd5e2;
  stroke-width: 0.6;
  vector-effect: non-scaling-stroke;
}

.mk-dot { fill: var(--accent); }
.mk-works .mk-dot { fill: var(--ink); }
.mk-halo {
  fill: none; stroke: var(--accent); stroke-width: 2;
  opacity: 0.4; vector-effect: non-scaling-stroke;
}
/* One slow pulse on the works marker, so the eye lands there first. Large,
   slow and low contrast, and it stops entirely under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .mk-halo { animation: mk-pulse 3.2s var(--ease) infinite; transform-origin: center; }
  @keyframes mk-pulse {
    0%   { r: 9;  opacity: 0.55; }
    70%  { r: 21; opacity: 0; }
    100% { r: 21; opacity: 0; }
  }
}

.mk-label {
  font-family: var(--sans);
  font-size: 17px;                /* viewBox units, so it scales with the map */
  fill: var(--ink-2);
  paint-order: stroke;            /* a halo of page colour keeps it legible */
  stroke: var(--surface);
  stroke-width: 4;
  stroke-linejoin: round;
}
.mk-label.is-works { fill: var(--ink); font-weight: 600; }

.map figcaption {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem;
  margin-top: 1rem; padding-top: 1rem; border-top: 1px solid var(--line-2);
}
.mk-key {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-size: 0.84rem; color: var(--ink-2);
}
.mk-key i {
  width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
}
.mk-key .k-works { background: var(--ink); box-shadow: 0 0 0 3px rgba(30, 80, 224, 0.25); }
.mk-key .k-market { background: var(--accent); }

@media (max-width: 599px) {
  /* Labels crowd badly on a phone; the caption list below still names them. */
  .mk-label { display: none; }
}
@media (prefers-contrast: more) {
  .wmap-land { fill: #c4ccda; stroke: #7d8798; }
  .mk-label { fill: var(--ink); }
}

/* ---- logo ---------------------------------------------------------------
   The mark was 32px against a 62px bar, which read as an afterthought.
   Bigger mark, bigger wordmark, and a taller bar to hold them. */

:root { --bar: 74px; }

.wordmark { gap: 0.7rem; font-size: 1.06rem; letter-spacing: 0.045em; }
.wordmark img { width: 46px; height: 46px; }

.site-footer .wordmark { font-size: 1.14rem; }
.site-footer .wordmark img { width: 52px; height: 52px; }

@media (max-width: 639px) {
  :root { --bar: 66px; }
  .wordmark { font-size: 0.95rem; }
  .wordmark img { width: 40px; height: 40px; }
}

/* ==================================================================== v6.6
   Routes on the map, facility cards, and a reveal that does not depend on JS. */

/* ---- a .reveal must never be the reason a page looks empty ----------------
   The hiding is now scoped to .js, set by an inline line in <head>. If the
   script file fails (ad blocker, CSP, dropped request) the content is simply
   there, rather than 19 invisible sections. */
/* The reveal uses the `translate` property, NOT `transform`.
   `.js .reveal.in { transform: none }` outranks `.ic:hover`/`.pc:hover`, so
   using transform here silently killed the lift on every card that is also a
   reveal. Keeping the two on separate properties lets them compose: the card
   can be revealed and hovered at the same time. */
.reveal { opacity: 1; translate: none; }
@media (prefers-reduced-motion: no-preference) {
  .js .reveal {
    opacity: 0; translate: 0 12px;
    transition: opacity 520ms var(--ease), translate 520ms var(--ease);
    transition-delay: var(--d, 0ms);
  }
  .js .reveal.in { opacity: 1; translate: 0 0; }
}

/* ---- flight paths ---------------------------------------------------------
   Every route starts at the works, so the fan itself says where the parts come
   from. Dashed, thin, and under the markers in the stacking order. */
.route {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.6;
  stroke-dasharray: 5 5;
  opacity: 0.5;
  vector-effect: non-scaling-stroke;
}

/* The reveal is a mask wiping along each path, so the line grows out of India
   rather than fading in everywhere at once. pathLength="1" normalises every
   route to the same length, so one keyframe covers all of them and the timing
   does not depend on how far away the country is. */
.rv { stroke-dasharray: 1; stroke-dashoffset: 0; }
@media (prefers-reduced-motion: no-preference) {
  .js .map .rv { stroke-dashoffset: 1; }
  .js .map.in .rv {
    animation: route-draw 900ms var(--ease) forwards;
    animation-delay: var(--d, 0ms);
  }
  @keyframes route-draw { to { stroke-dashoffset: 0; } }
}

@media (prefers-contrast: more) {
  .route { opacity: 0.85; stroke-width: 2; }
}

/* ---- facility cards -------------------------------------------------------
   One card per works: photo, name, area, role, full address, the numbers and a
   map link. Same block on the contact page and the company page, so the two
   cannot drift apart. */
.ucs {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
.uc {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); overflow: hidden;
}
.uc-ph {
  display: block; aspect-ratio: 16 / 9; overflow: hidden;
  background: var(--media-bg, #f2f4f7);
  border-bottom: 1px solid var(--line-2);
}
.uc-ph img { width: 100%; height: 100%; object-fit: cover; }
.uc-body { padding: 1.25rem 1.35rem 1.4rem; }
.uc-name {
  font-size: 1.1rem; font-weight: 600; letter-spacing: -0.014em;
  display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
}
.uc-name span {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.04em; color: var(--accent);
}
.uc-role {
  margin-top: 0.25rem;
  font-family: var(--mono); font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}
.uc address {
  font-style: normal; margin-top: 0.9rem;
  font-size: 0.92rem; line-height: 1.65; color: var(--ink-2);
}
.uc-contact {
  margin-top: 0.9rem; padding-top: 0.9rem; border-top: 1px solid var(--line-2);
  display: flex; flex-direction: column; gap: 0.25rem;
}
.uc-contact a { font-size: 0.9rem; text-decoration: none; }
.uc-contact a:hover { text-decoration: underline; }
.uc-map { margin-top: 0.8rem; font-size: 0.88rem; }

@media (max-width: 719px) { .ucs { grid-template-columns: 1fr; } }

/* ==================================================================== v6.7
   Spacing pass. Found by measuring real whitespace between content across all
   47 pages (scratchpad/gap_audit.py), not by eye: a 0px margin between two
   <section>s is fine because each carries its own padding, so the audit looks
   at the gap between the elements that actually put ink on the page. */

/* ---- product page: the breadcrumb was sitting on the content -------------
   Crumbs live in their own .wrap with only top padding, and .product-layout
   began immediately after it: 0px between the trail and the sidebar heading. */
.product-layout { padding-top: clamp(1.35rem, 3vw, 2.25rem); }

/* ---- company page: prose, button and the facility cards were touching ----
   `p { margin: 0 }` is the global reset, and nothing put the stacked
   paragraphs or the button back apart again. */
.two-up p + p { margin-top: 1rem; }
/* One rule, not three. The first attempt had a :has() and a deep descendant
   selector both setting this, and they outranked the later fix. */
.two-up p > .btn { margin-top: 0.75rem; }
.ucs { margin-top: clamp(2rem, 4vw, 3rem); }

/* ---- the + and = in the area sum were nearly invisible -------------------
   They carried --line, a border colour, which is far too light to read as
   type. They are doing arithmetic, so they need to be legible. */
.page-facts span {
  color: var(--ink-3);
  font-weight: 500;
  margin-inline: 0.5rem;
}

/* ---- headings need more air than a single line of leading ---------------- */
.product h2 { margin-bottom: 1.45rem; }
.page-lead { margin-top: 1.35rem; }
.page-facts { margin-top: 1.6rem; }

/* ---- ordering guide and part tables -------------------------------------- */
.ordering-sub { margin-top: 0; margin-bottom: 1.15rem; }
.ok { margin-top: 1.15rem; }
.parts figcaption { margin-bottom: 0.8rem; }
.pt-legend { margin-top: 0.95rem; }
.parts-intro { margin-bottom: 1.4rem; }

/* ---- part number builder -------------------------------------------------- */
.builder h2 { margin-bottom: 1.05rem; }
.builder-head p { margin-bottom: 0.25rem; }

/* ---- odds and ends the audit turned up ----------------------------------- */
.cd-code { margin-top: 1.1rem; }
.form-note { margin-top: 1.15rem; }
.map figcaption { margin-top: 1.25rem; padding-top: 1.25rem; }
.feature-list, .onreq ul { margin-top: 0.25rem; }

/* `.sec-head p` (0,1,1) was beating `.page-facts` (0,1,0), so the facts line
   inside a section header kept the tighter paragraph spacing. */
.sec-head .page-facts { margin-top: 1.6rem; }
.sec-head p { margin-top: 1rem; }

/* A button following prose needs to read as an action, not as the next line
   of the paragraph. */

/* ==================================================================== v6.8
   Industry cards that are not links, and the catalogue download. */

/* ---- industry cards -------------------------------------------------------
   They used to open a page each. Those pages held a lead and a short list, so
   the content now lives on the card and there is nothing behind it. The lift
   on hover stays, because the card is still a distinct object on the page,
   but nothing here is clickable and nothing pretends to be. */
.ic { cursor: default; }
.ic-body { display: block; padding: 1.4rem 1.5rem 1.6rem; }
.ic-name {
  font-size: 1.18rem; font-weight: 600; letter-spacing: -0.018em;
  line-height: 1.25; color: var(--ink);
}
.ic-lead { margin-top: 0.6rem; color: var(--ink-2); font-size: 0.94rem; }
.ic-serves {
  list-style: none; margin: 1.1rem 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.4rem;
}
.ic-serves li {
  font-size: 0.82rem; line-height: 1.3;
  padding: 0.35rem 0.7rem;
  background: var(--accent-wash); color: var(--accent-ink);
  border: 1px solid rgba(30, 80, 224, 0.18); border-radius: var(--r-input);
}

/* ---- catalogue download ---------------------------------------------------
   A real file, so it says what it is and how big before anyone commits to it.
   `download` rather than a new tab: the point is to keep the copy, and most
   people forward it on. */
.dl-row { margin-top: clamp(1.75rem, 4vw, 2.5rem); }
.dl {
  display: inline-flex; align-items: center; gap: 0.9rem;
  padding: 0.85rem 1.35rem 0.85rem 1rem;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--r-card); text-decoration: none; color: var(--ink);
  transition: border-color 200ms var(--ease), transform 200ms var(--ease),
              box-shadow 200ms var(--ease);
}
.dl:hover {
  border-color: rgba(30, 80, 224, 0.45);
  transform: translateY(-1px);
  box-shadow: var(--shadow-1);
}
.dl:active, .dl.is-pressed { transform: translateY(0) scale(0.985); transition-duration: var(--press); }
.dl-ic {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 9px;
  display: grid; place-items: center;
  background: var(--accent-wash); color: var(--accent);
  border: 1px solid rgba(30, 80, 224, 0.16);
}
.dl-ic svg { width: 20px; height: 20px; display: block; }
.dl-t b { display: block; font-size: 0.96rem; font-weight: 600; letter-spacing: -0.01em; }
.dl-t small {
  display: block; margin-top: 0.15rem;
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.05em;
  color: var(--ink-3); text-transform: uppercase;
}

@media (prefers-contrast: more) {
  .dl { border-color: var(--ink-3); }
  .ic-serves li { border-color: var(--accent); }
}
@media (prefers-reduced-motion: reduce) {
  .dl:hover { transform: none; }
}


/* ==================================================================== v6.9
   Measurements, and a larger wordmark.

   Fractions are set the way a drawing sets them: numerator raised,
   denominator dropped, a fraction slash between. Built from real sup/sub
   rather than a precomposed glyph, because 5/16 and 3/16 have none, and
   because it stays selectable as "1/2". The inch mark itself is a double
   prime character, so nothing here has to style it. */
.frac {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
}
.frac sup,
.frac sub {
  font-size: 0.74em;
  line-height: 0;
  font-weight: inherit;
}
.frac sup { vertical-align: 0.42em; }
.frac sub { vertical-align: -0.04em; }
.frac > span { margin: 0 -0.04em; opacity: 0.85; }

/* The name carries the header and the footer, so it is sized to be read
   across the room rather than squinted at. The bar grows with it. */
:root { --bar: 80px; }
.wordmark { font-size: 1.24rem; letter-spacing: 0.04em; }
.wordmark img { width: 52px; height: 52px; }
.site-footer .wordmark { font-size: 1.42rem; }
.site-footer .wordmark img { width: 60px; height: 60px; }

@media (max-width: 720px) {
  :root { --bar: 68px; }
  .wordmark { font-size: 1.05rem; gap: 0.55rem; }
  .wordmark img { width: 44px; height: 44px; }
  .site-footer .wordmark { font-size: 1.18rem; }
  .site-footer .wordmark img { width: 50px; height: 50px; }
}

/* Inspection photographs. A column layout, not a grid of equal tiles: each
   photograph sets its own height from its own proportions, so a tall shot
   stays tall and nothing is stretched or cropped to make a tidy rectangle. */
.qa-collage {
  margin-top: 2.25rem;
  column-count: 2;
  column-gap: 0.75rem;
}
/* The column count follows how many photographs there actually are, so
   supplying three does not leave a fourth column empty. */
@media (min-width: 900px) {
  .qa-collage { column-count: var(--qa-cols, 3); }
}
.qac-fig {
  break-inside: avoid;
  margin: 0 0 0.75rem;
  border-radius: var(--r-card);
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--line);
}
.qac-fig img {
  display: block;
  width: 100%;
  height: auto;
  /* Capped so one portrait shot does not run twice the height of the
     landscape ones. object-fit: cover crops, it does not stretch: the
     photograph keeps its own proportions, we just see less of it. */
  max-height: 380px;
  object-fit: cover;
  object-position: center;
}


/* =================================================================== v6.10
   Length sliders in the part number builder.

   Stem and insertion length were six buttons each, which said the six
   printed lengths were the only ones. They are machined to order, so the
   control is a slider across the real range and the catalogue's standard
   lengths sit under the track as ticks.

   A native <input type="range">: it drags 1:1, takes arrow keys, Home and
   End, and announces itself. Everything below is appearance only. */
.bfield-range .blabel { gap: 0.55rem; width: 100%; }
.bfield-range .blabel label { cursor: pointer; }
.bval {
  margin-left: auto;
  font-family: var(--mono); font-size: 0.92rem; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: 0;
  color: var(--accent);
}
.bslider {
  --thumb: 22px;
  --track: 6px;
  position: relative;
}

.brange {
  -webkit-appearance: none; appearance: none;
  display: block; width: 100%; margin: 0;
  height: var(--thumb); background: transparent;
  cursor: grab; touch-action: pan-y;
}
.brange:active { cursor: grabbing; }
.brange:focus-visible { outline: none; }

/* --fill is set on .bslider, in build.py for the first paint and in app.js on
   every frame of a drag, so the filled part of the track always reads as the
   value rather than lagging it. */
.brange::-webkit-slider-runnable-track {
  height: var(--track); border-radius: 999px;
  background: linear-gradient(to right,
    var(--accent) 0 var(--fill), var(--line) var(--fill) 100%);
}
.brange::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: var(--thumb); height: var(--thumb); border-radius: 50%;
  margin-top: calc((var(--track) - var(--thumb)) / 2);
  background: #fff; border: 2px solid var(--accent);
  box-shadow: var(--shadow-1);
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease);
}
.brange:hover::-webkit-slider-thumb { transform: scale(1.08); }
.brange:active::-webkit-slider-thumb {
  transform: scale(1.16); transition-duration: var(--press);
}
.brange:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 4px var(--accent-wash);
}

.brange::-moz-range-track {
  height: var(--track); border-radius: 999px; background: var(--line);
}
.brange::-moz-range-progress {
  height: var(--track); border-radius: 999px; background: var(--accent);
}
.brange::-moz-range-thumb {
  width: var(--thumb); height: var(--thumb); border-radius: 50%;
  background: #fff; border: 2px solid var(--accent);
  box-shadow: var(--shadow-1);
  transition: transform 160ms var(--ease), box-shadow 160ms var(--ease);
}
.brange:hover::-moz-range-thumb { transform: scale(1.08); }
.brange:active::-moz-range-thumb {
  transform: scale(1.16); transition-duration: var(--press);
}
.brange:focus-visible::-moz-range-thumb {
  box-shadow: 0 0 0 4px var(--accent-wash);
}

/* The ticks are inset by half a thumb at each end, because that is the
   distance the thumb's centre actually travels. Without the inset every tick
   sits slightly off its own length. */
.bticks {
  position: absolute;
  left: calc(var(--thumb) / 2); right: calc(var(--thumb) / 2);
  top: calc(var(--thumb) / 2 + var(--track) / 2 + 5px);
  height: 5px; pointer-events: none;
}
.bticks span {
  position: absolute; top: 0; width: 1px; height: 5px;
  background: var(--ink-3); opacity: 0.45;
}
.bscale {
  display: flex; justify-content: space-between;
  margin: 0.95rem 0 0;
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.04em;
  color: var(--ink-3);
}

@media (prefers-reduced-motion: reduce) {
  .brange::-webkit-slider-thumb { transition: none; }
  .brange::-moz-range-thumb { transition: none; }
  .brange:hover::-webkit-slider-thumb { transform: none; }
  .brange:hover::-moz-range-thumb { transform: none; }
}

@media (prefers-contrast: more) {
  .brange::-webkit-slider-runnable-track { outline: 1px solid var(--ink); }
  .brange::-moz-range-track { outline: 1px solid var(--ink); }
  .bticks span { opacity: 1; }
}

/* The insertion length ceiling moves with the stem length. Without a line
   saying so, a maximum that changes on its own looks like a fault. */
.bhint {
  margin: 0.5rem 0 0;
  font-size: 0.78rem; color: var(--ink-3);
}


/* =================================================================== v6.12
   The footer's own text, and a larger mark.

   v6.9 grew the wordmark but left everything under it where it was: links at
   0.845rem, column headings at 0.64rem, the legal line at 0.76rem. The name
   got bigger and the footer did not. These are the sizes people actually read
   the footer at. */
.site-footer a { font-size: 0.95rem; line-height: 1.45; }
.site-footer address { font-size: 0.98rem; line-height: 1.7; }
.footer-contact { font-size: 0.98rem; line-height: 1.85; }
.site-footer h3 { font-size: 0.75rem; letter-spacing: 0.1em; margin-bottom: 1rem; }
.footer-cols { gap: 1.7rem; }
.footer-cols li { margin-bottom: 0.5rem; }
.footer-bottom { font-size: 0.84rem; }

/* The mark, a size up in both bars. */
:root { --bar: 86px; }
/* The strapline sits inside the logo image's own empty band, so the brand
   block is 50px, shorter than the 56px image was alone. The bar keeps its
   height: the second line costs the page nothing. */
.wordmark img { width: 60px; height: 60px; }
.site-footer .wordmark img { width: 72px; height: 72px; }

@media (max-width: 720px) {
  :root { --bar: 74px; }
  .wordmark img { width: 50px; height: 50px; }
  .site-footer .wordmark img { width: 58px; height: 58px; }
  .site-footer a { font-size: 0.92rem; }
  .site-footer address, .footer-contact { font-size: 0.95rem; }
}


/* =================================================================== v6.13
   Footer balance, and the wordmark set like the logo artwork.

   v6.12 overshot: the link columns are a list to scan, not body copy, so they
   come back down. The section headings are what tell you which list you are
   in, and those go up. */
.site-footer a { font-size: 0.9rem; }
.site-footer h3 {
  font-size: 0.82rem; letter-spacing: 0.07em; color: var(--ink-2);
  margin-bottom: 0.95rem;
}

/* The wordmark follows the logo artwork: caps, wide tracking, and the two
   words separated by weight rather than by size. Colours are unchanged. */
.wordmark span {
  letter-spacing: 0.19em;
  font-weight: 400;
  white-space: nowrap;
  /* Tracking is added after the last letter too, which leaves a phantom gap
     on the right and throws off anything measured from the mark's edge. */
  margin-inline-end: -0.19em;
}
.wordmark b { font-weight: 600; }
.wordmark { letter-spacing: 0; font-size: 1.06rem; }
.site-footer .wordmark { font-size: 1.2rem; }

@media (max-width: 720px) {
  .wordmark { font-size: 0.86rem; }
  .wordmark span { letter-spacing: 0.14em; }
  .site-footer .wordmark { font-size: 0.98rem; }
  .site-footer h3 { font-size: 0.78rem; }
}


/* =================================================================== v6.14
   The real logo, in place of a wordmark set in type.

   The company's own artwork arrived as a PDF: one 1877x838 XObject with a
   DeviceGray SMask carrying the alpha. It is the mark and the name as one
   lockup, in the company's own face, so the CSS approximation from v6.13 is
   gone and this is drawn instead. Sized by height, because that is the
   dimension a bar has to hold; the width follows the artwork. */
.wordmark {
  display: inline-flex; align-items: center;
  letter-spacing: normal;
}
/* flex: none, or the bar shrinks the lockup narrower than its own aspect
   ratio and squashes the mark. The header has room to size by height; the
   footer column does not, so there it is sized by width and the height
   follows the artwork. */
.wordmark img {
  flex: none;
  width: auto; height: 54px;
  display: block;
}
.site-footer .wordmark img {
  height: auto;
  width: min(100%, 288px);
}

@media (max-width: 720px) {
  .wordmark img { height: 38px; }
  .site-footer .wordmark img { width: min(100%, 236px); }
}


/* =================================================================== v6.15
   The alloy band.

   Twenty identical light chips said "we have a list". This is the one place
   on the home page that talks about raw material, so it goes dark, takes a
   photograph of bar stock behind it, and sets each alloy as its own numbered
   tile. The heading claims twenty; the tiles are numbered so the claim is
   checkable at a glance. */
.alloys {
  position: relative;
  /* An explicit colour under the gradient, not just the gradient. A band
     whose only background is an image is a transparent band the moment
     anything drops that image, and white text on paper is unreadable. */
  background-color: #0d1220;
  background-image:
    linear-gradient(160deg, #0d1220 0%, #141a28 55%, #0b1018 100%);
  color: #fff;
  border-block: 1px solid rgba(255, 255, 255, 0.09);
}
/* The photograph, when it is there. The scrim is angled: heaviest where the
   heading sits, lightest across the tiles, so the bar stock stays visible
   instead of being flattened to a texture. */
.alloys-photo {
  background-image:
    linear-gradient(112deg, rgba(6, 9, 15, 0.86) 0%,
                            rgba(6, 9, 15, 0.66) 45%,
                            rgba(6, 9, 15, 0.44) 100%),
    url("img/barstock.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.alloys .sec-head h2 { color: #fff; }
.alloys .sec-head p { color: rgba(255, 255, 255, 0.7); }

.alloys-grid {
  list-style: none; margin: 2.1rem 0 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 9.5rem), 1fr));
  gap: 0.55rem;
}
.alloy {
  display: flex; align-items: baseline; gap: 0.6rem;
  padding: 0.8rem 0.9rem;
  border-radius: var(--r-ctl);
  /* Dark, not a light film: a tile has to hold its text over a bright bar
     end as well as over a shadow, and the scrim behind it is deliberately
     thin so the stock shows through. */
  background: rgba(10, 14, 24, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.2);
  backdrop-filter: blur(7px); -webkit-backdrop-filter: blur(7px);
  transition: background-color 220ms var(--ease),
              border-color 220ms var(--ease), scale 220ms var(--ease);
}
/* Hover uses scale, entrance uses translate. They are separate properties, so
   a tile that is doing both composes instead of one silently winning. */
.alloy:hover {
  background: rgba(18, 24, 38, 0.72);
  border-color: rgba(255, 255, 255, 0.42);
  scale: 1.035;
}
.alloy b {
  font-family: var(--mono); font-size: 0.86rem; font-weight: 500;
  color: #fff; letter-spacing: 0.01em;
}

/* The tiles come in one after another, off the grid's own reveal. */
@media (prefers-reduced-motion: no-preference) {
  .js .alloys-grid .alloy {
    opacity: 0; translate: 0 10px;
    transition: opacity 460ms var(--ease) var(--d, 0ms),
                translate 460ms var(--ease) var(--d, 0ms),
                background-color 220ms var(--ease),
                border-color 220ms var(--ease), scale 220ms var(--ease);
  }
  .js .alloys-grid.in .alloy { opacity: 1; translate: 0 0; }
}

@media (prefers-reduced-transparency: reduce) {
  /* Solid tiles, no blur. The PHOTOGRAPH STAYS: reduced transparency asks
     for no see-through materials, it does not ask for no pictures. Dropping
     the bar stock here is why the band read as a plain black panel on any
     machine with Windows transparency effects switched off, which is a lot
     of them. */
  .alloy {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: rgba(10, 14, 24, 0.92);
  }
}
@media (prefers-contrast: more) {
  .alloy { border-color: rgba(255, 255, 255, 0.55); }
  .alloys .sec-head p { color: #fff; }
}


/* =================================================================== v6.16
   The machine tiles are white, not sampled.

   --media-bg exists so a product photograph's studio sweep blends into its
   card. The machine images are manufacturer renders on white, and one of
   them sits on a yellow ground, so sampling their corners painted whole
   tiles grey and yellow. A machine tile is white. */
.mshot { background: var(--surface); }

/* Six machines, so three across reads as two even rows rather than five and
   an orphan. The tiles get bigger too, which these renders can carry. */
.mshots { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 700px) { .mshots { grid-template-columns: repeat(2, 1fr); } }


/* =================================================================== v6.17
   The drawing, and the image viewer.

   A dimensioned drawing in a thumbnail rail is unreadable, which defeats the
   point of a drawing. It gets the full content width instead. */
.drawings { margin-top: 2.75rem; }
.dwg {
  margin: 1.25rem 0 0;
  background: var(--media-bg, var(--surface));
  border: 1px solid var(--line); border-radius: var(--r-card);
  overflow: hidden;
}
.dwg a { display: block; cursor: zoom-in; }
.dwg img { display: block; width: 100%; height: auto; }
.dwg figcaption {
  padding: 0.7rem 1rem 0.9rem;
  font-size: 0.82rem; color: var(--ink-2);
  border-top: 1px solid var(--line-2); background: var(--surface);
}

.gs-open { display: block; cursor: zoom-in; }

/* The viewer is a real <dialog>: the browser owns the top layer, the
   backdrop, Escape and the focus trap, so none of that is reimplemented. */
.lb {
  border: 0; padding: 0; max-width: 100vw; max-height: 100vh;
  width: 100%; height: 100%;
  background: transparent; color: #fff; overflow: hidden;
}
.lb::backdrop { background: rgba(8, 11, 18, 0.88); }
.lb-fig {
  margin: 0; height: 100%;
  display: grid; grid-template-rows: minmax(0, 1fr) auto;
  align-items: center; justify-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  box-sizing: border-box;
}
.lb-fig img {
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain;
  border-radius: 6px; background: #fff;
}
.lb-fig figcaption {
  margin-top: 1rem; text-align: center;
  font-size: 0.85rem; color: rgba(255, 255, 255, 0.75);
  max-width: 60ch;
}
.lb-x, .lb-nav {
  position: absolute; z-index: 1;
  display: grid; place-items: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(255, 255, 255, 0.12); color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.22);
  font: inherit; cursor: pointer;
  transition: background-color 180ms var(--ease), scale 180ms var(--ease);
}
.lb-x:hover, .lb-nav:hover {
  background: rgba(255, 255, 255, 0.22); scale: 1.06;
}
.lb-x { top: 1rem; right: 1rem; font-size: 1.6rem; line-height: 1; }
.lb-nav { top: 50%; translate: 0 -50%; }
.lb-nav svg { width: 22px; height: 22px; }
.lb-prev { left: 1rem; }
.lb-next { right: 1rem; }

@media (prefers-reduced-motion: reduce) {
  .lb-x:hover, .lb-nav:hover { scale: none; }
}
@media (prefers-contrast: more) {
  .lb-x, .lb-nav { background: #000; border-color: #fff; }
}
@media (max-width: 600px) {
  .lb-nav { width: 40px; height: 40px; }
  .lb-prev { left: 0.35rem; }
  .lb-next { right: 0.35rem; }
}

/* The drawing gets breathing room inside its frame, so the caption bar does
   not sit hard against the linework. */
.dwg a { padding: 0.75rem 0.75rem 0.55rem; }

/* "More Views" sat 12px off the first thumbnail, which reads as the heading
   belonging to the rail rather than labelling it. */
.gallery h2 { margin-bottom: 1.1rem; }

/* Wrapping each shot in a link made the LINK the flex child of the card, so
   the img's max-height: 100% resolved against an auto-height anchor and the
   photo spilled out of its tile. The anchor has to be the box the card sizes. */
.gs .gs-open {
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%; min-height: 0;
}


/* =================================================================== v6.18
   The footer stops merging into the quote band.

   Both were --paper-2, so the CTA and the footer read as one long grey block
   and the quote band lost its edge. The footer goes a step deeper, with a
   border that is darker than the panel rather than the same value. */
.site-footer {
  background: #dde4ee;
  border-top: 1px solid #c7d1e0;
}
.site-footer .footer-bottom { border-top-color: #c7d1e0; }

/* The main photograph opens in the viewer like the gallery shots do. The
   anchor has to carry the centring, because it is now the block that sits
   between the frame and the image. */
.hero-plate .gs-open {
  display: block; text-align: center;
}


/* =================================================================== v6.19
   The first screen is the whole screen.

   The hero used to end partway down, so the strip below it was already in
   view on load and the page opened as a list of things rather than as one
   photograph. It now fills the window under the header, and everything else
   starts below the fold.

   min-height, not height: on a short laptop or a phone held sideways the
   content still has to fit, and growing past the window is better than
   clipping the headline. */
.hero-inner {
  min-height: calc(100dvh - var(--bar));
  display: flex; flex-direction: column; justify-content: center;
  padding-block: clamp(3rem, 7vw, 5rem);
}

/* Now that the rest of the page is genuinely out of sight, say so. */
.hero-cue {
  margin: auto 0 0; padding-top: clamp(2rem, 6vh, 3.5rem);
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.66rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: rgba(255, 255, 255, 0.5);
}
.hero-cue svg { width: 15px; height: 15px; }
@media (prefers-reduced-motion: no-preference) {
  .hero-cue svg { animation: cue 2.4s var(--ease) infinite; }
}
@keyframes cue {
  0%, 62%, 100% { transform: translateY(0); opacity: 0.55; }
  78% { transform: translateY(4px); opacity: 1; }
}

/* Very short windows: a 100dvh hero would push the headline off a 420px tall
   browser, so it goes back to sizing from its own content. */
@media (max-height: 560px) {
  .hero-inner { min-height: 0; padding-block: clamp(2rem, 6vw, 3rem); }
  .hero-cue { display: none; }
}

/* The strip drifts, so it must never look like the page is scrolling
   sideways. Its own scrollbar is hidden; drag and wheel still work. */
.strip-rail { scrollbar-width: none; }
.strip-rail::-webkit-scrollbar { display: none; }


/* =================================================================== v6.20
   The hero headline carries the screen.

   Now that the photograph fills the window, the type has to hold its own
   against it. The headline goes up to 5rem at desktop width, the lead follows
   it, and the block sits on the vertical centre rather than being pushed to
   the top by the scroll cue below it. */
.hero-inner h1 {
  font-size: clamp(2.5rem, 5.6vw, 4.75rem);
  line-height: 0.98;
  letter-spacing: -0.042em;
  max-width: 16ch;
}
.hero-inner .hero-lead {
  margin-top: 1.75rem;
  font-size: clamp(1.08rem, 1.55vw, 1.32rem);
  line-height: 1.55;
  max-width: 48ch;
}
.hero-inner .hero-cta { margin-top: 2.5rem; }
.hero-inner .eyebrow { margin-bottom: 1.4rem; }

/* Out of the flex flow, so the headline block centres on its own. Anchored to
   the content column's right edge, which is where the eye already is. */
.hero-cue {
  position: absolute;
  right: 0; bottom: clamp(1rem, 3.5vh, 2.25rem);
  margin: 0; padding: 0;
}

/* Tall enough to matter, short enough that a 5rem headline would not fit. */
@media (max-height: 760px) and (min-width: 900px) {
  .hero-inner h1 { font-size: clamp(2.4rem, 4.4vw, 3.6rem); }
  .hero-inner .hero-lead { margin-top: 1.4rem; }
  .hero-inner .hero-cta { margin-top: 2rem; }
}
@media (max-height: 560px) {
  .hero-inner h1 { font-size: clamp(1.9rem, 3.4vw, 2.6rem); }
  .hero-inner .hero-lead { margin-top: 1rem; font-size: 1rem; }
  .hero-inner .hero-cta { margin-top: 1.4rem; }
}

/* The cue's containing block is the wrap's PADDING box, so right: 0 puts it
   hard against the screen edge on a phone, where the gutter is all there is.
   Inset it by the gutter so it lines up with the text above it. */
.hero-cue {
  right: var(--gutter);
  color: rgba(255, 255, 255, 0.72);
  text-shadow: 0 1px 10px rgba(6, 9, 15, 0.65);
}

/* Both works in the footer. Each address is labelled, because two unlabelled
   addresses a few streets apart are a puzzle rather than information. */
.site-footer address + address { margin-top: 1.15rem; }
.site-footer address b {
  display: block; margin-bottom: 0.3rem;
  font-family: var(--mono); font-size: 0.72rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3);
}


/* =================================================================== v6.21
   Industries on the home page.

   The four cards used to be a page of their own, so they were sized to fill
   one. As one section among six they run four across on a wide screen, with a
   shallower photograph: enough to recognise the sector, not so much that the
   home page turns into a scroll through four large pictures. */
#industries .ics { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.85rem; }
#industries .ic-ph { aspect-ratio: 4 / 3; }
#industries .ic-body { padding: 1.05rem 1.1rem 1.25rem; }
#industries .ic-name { font-size: 1.02rem; }
#industries .ic-lead { font-size: 0.86rem; }

@media (max-width: 1099px) {
  #industries .ics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 599px) {
  #industries .ics { grid-template-columns: 1fr; }
  #industries .ic-ph { aspect-ratio: 16 / 9; }
}

/* The card is a grid of photo + body inside a stretched row, so the spare
   height was being shared out BETWEEN the two: cards with shorter text pushed
   their body further from the photograph, and the four looked misaligned even
   though every card and every photo was the same size. The space belongs at
   the bottom. */
.ic { align-content: start; }

/* The headline is a four word phrase now, not a three word one, so it needs a
   wider measure and a step down in size to keep each line on one row. */
.hero-inner h1 {
  font-size: clamp(2.05rem, 4.4vw, 3.75rem);
  max-width: 26ch;
  line-height: 1.02;
}
@media (max-height: 760px) and (min-width: 900px) {
  .hero-inner h1 { font-size: clamp(2rem, 3.6vw, 3.1rem); }
}

/* Two shorter lines than before, so the type can go back up. */
.hero-inner h1 {
  font-size: clamp(2.4rem, 5.4vw, 4.6rem);
  max-width: 22ch;
  line-height: 0.99;
  letter-spacing: -0.045em;
}
@media (max-height: 760px) and (min-width: 900px) {
  .hero-inner h1 { font-size: clamp(2.2rem, 4.2vw, 3.5rem); }
}
@media (max-height: 560px) {
  .hero-inner h1 { font-size: clamp(1.9rem, 3.4vw, 2.7rem); }
}

/* On a phone the clamp floor was holding the type at 38px, which split both
   lines in two and made a four line headline. Lower floor, two lines. */
.hero-inner h1 { font-size: clamp(1.8rem, 5.4vw, 4.6rem); }


/* =================================================================== v6.22
   The industries band gets its own ground.

   It followed "Where most enquiries start", which is also .section-alt, so
   two identical greys ran together as one long block with a hairline in the
   middle of it. The cards are white, so this band cannot go lighter without
   dissolving them: it goes deeper instead, which also steps the page down
   into the dark alloy band that follows it.

   white strip -> paper -> paper-2 -> this -> dark. A descent, not a flicker. */
#industries {
  background: linear-gradient(180deg, #e3e9f5 0%, #d6dfef 100%);
  border-block: 1px solid #c6d1e4;
}
#industries .ic {
  /* A white card on a deeper ground carries its own edge, so the border can
     step back and let the card do the work. */
  border-color: rgba(255, 255, 255, 0.9);
  box-shadow: 0 1px 2px rgba(16, 22, 40, 0.05), 0 10px 26px rgba(16, 22, 40, 0.07);
}
#industries .ic:hover {
  box-shadow: 0 2px 6px rgba(16, 22, 40, 0.07), 0 18px 40px rgba(16, 22, 40, 0.12);
}
@media (prefers-contrast: more) {
  #industries .ic { border-color: var(--ink-3); }
}


/* =================================================================== v6.23
   The company name, legible.

   The lockup is placed by height, and the supplied artwork sets a 318px mark
   against 62px lettering, so at 54px the name rendered at 10.5px: smaller
   than the nav links next to it. logo-lockup.png is now re-spaced (same
   pixels, mark scaled toward the words) so the lettering is 34% of the height
   instead of 19%, and it reads at 18px in the header. The untouched original
   is kept at logo-lockup-full.png. */
.wordmark img { height: 56px; }
.site-footer .wordmark img { height: auto; width: min(100%, 330px); }

@media (max-width: 1099px) {
  .wordmark img { height: 48px; }
}
@media (max-width: 720px) {
  .wordmark img { height: 34px; }
  .site-footer .wordmark img { width: min(100%, 260px); }
}

/* The footer lockup is sized by width, so inside a 314px column the name
   could never be larger than 13px however the grid was tuned: widening that
   column to 4fr bought 4px of lettering and wrapped eight more product links.
   The name comes out of the column instead and sits across the top of the
   footer, where it has the full measure and costs the lists nothing. */
/* Specificity: the v6.23 rule above is .site-footer .wordmark img (0,3,1),
   so this has to match it or the 330px cap wins and the name stays small. */
.site-footer .footer-brand {
  display: flex; flex-direction: column; align-items: stretch; gap: 0;
  width: min(100%, 520px); margin-bottom: 2.25rem;
}
.site-footer .footer-brand img { width: 100%; height: auto; display: block; }
@media (max-width: 720px) {
  .site-footer .footer-brand { margin-bottom: 1.75rem; width: min(100%, 320px); }
}


/* =================================================================== v6.24
   The strapline from the printed card.

   The card sets it between two rules with diamonds between the words. At
   header size the rules collapse to nothing and the diamonds turn to specks,
   so what carries over is the proportion rather than the ornament: caps on
   very wide tracking, sitting quietly under the name. The diamonds stay,
   at half weight, because they are the part of the device that is the
   company's own. */
/* Both brand blocks are exactly as wide as the logo, so the strapline can be
   positioned as a PERCENTAGE of the artwork instead of a pixel sum per
   breakpoint. In the file the lettering starts 165px into 1509, so 10.93% is
   where "APEX" begins; padding that much and then centring puts the strapline
   on the middle of the name rather than the middle of the whole lockup. */
.brand {
  display: inline-flex; flex-direction: column; align-items: stretch;
  gap: 0;
}
.brand .wordmark img { display: block; }

.brandline {
  display: flex; align-items: center; justify-content: center;
  flex-wrap: nowrap; gap: 0.55em;
  padding-left: 10.93%;
  font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink); white-space: nowrap;
  /* Tracking is added after the last letter too, which pulls a centred line
     off centre by half of it. */
  text-indent: 0.2em;
  /* The lettering ends 64px up from the bottom of a 1509px wide file, so the
     image carries 4.24% of its own width as empty space underneath. Without
     this the strapline sits a whole band of nothing away from the name and no
     amount of gap tuning explains why. Percentage margins resolve against the
     container's WIDTH, and the container is exactly the logo's width, so this
     stays true at any size. */
  margin-top: calc(-4.2412% + 0.1rem);
}
/* The diamonds are the one piece of colour outside the brand blue. Deep and
   slightly muted rather than a signal red: at 8px a saturated red vibrates
   against the near black lettering either side of it. */
.bl-d { font-size: 0.7em; color: #c1272d; letter-spacing: 0; }
@media (prefers-contrast: more) { .bl-d { color: #a01c22; } }

/* The footer has room the header does not. */
.brandline-lg { font-size: 0.92rem; gap: 0.66em; letter-spacing: 0.22em; }

@media (max-width: 1099px) {
  .brandline { font-size: 0.66rem; letter-spacing: 0.16em; }
}
@media (max-width: 860px) {
  /* No room under a 34px mark for a second line without the bar growing into
     the page. The footer still carries it. */
  .brand .brandline { display: none; }
  .brandline-lg { font-size: 0.72rem; letter-spacing: 0.16em; }
}

/* Two phone numbers separated by a 0.84rem middle dot ran together as one
   long number. The separator gets its own weight and air. */
.footer-contact .sep {
  display: inline-block;
  margin-inline: 0.5em;
  font-size: 1.6em; line-height: 0;
  vertical-align: -0.06em;
  color: var(--ink-3);
}


/* =================================================================== v6.25
   The alloy grid is 6 across, 3 down.

   Eighteen materials on an auto-fill grid landed at 7 columns and left an
   orphan row of four. Six columns divides the list exactly, and the wider
   column makes each tile bigger without the type growing to fill it. */
.alloys-grid { grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 0.65rem; }
.alloy { padding: 1rem 1.15rem; }
.alloy b { font-size: 0.95rem; }

@media (max-width: 1180px) { .alloys-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 820px)  { .alloys-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .alloys-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
