/* =========================================================
   Section redesign — MANUFACTURING.  See REDESIGN-BRIEF.md.

   Loads after pages.css so it can override the .tile/.g3 rules
   it replaces. Scoped to this page only; nothing here ships to
   the other six.

   Archetypes, in page order:
     hero           0 · drawn route + photographic plate
     process        8 · photograph rail        <- the one moment
     infrastructure 5 · full-bleed split
     capability     2 · editorial rows
     batch          6 · counter field, deliberately unequal
     promise            statement plate + one hairline strip

   Tokens only. No new colour, no new radius, no green. Molten
   carries labels, heat and process marks and never a CTA.

   THE `--live` CONVENTION
   Every rule below defaults to the FINISHED state. The hidden
   pre-states are scoped under `.mline--live` / `.mpromise--live`,
   which js/sec-manufacturing.js adds only once it has decided to
   animate. So a visitor with no JS, a failed script or reduced
   motion gets the completed section rather than an empty one —
   the same contract js/transitions.js uses for the product cast.
   ========================================================= */

/* =========================================================
   0 · HERO — the plan sheet

   .phero and .phero__* live in shared pages.css and are not
   editable from here, so everything below overrides them under
   `.phero--plan` and lands on this page only.

   Three layers, back to front: a drafting grid on the ground, a
   photographic plate held to the bottom-right corner, and a route
   drawn across both. No copy sits on the photograph — the plate is
   held below and right of the text column at every width — so this
   hero carries no text-on-image contrast debt, which is what lets
   the plate stay a photograph rather than a dark smear.

   The `--live` convention applies as it does everywhere else on
   this page: the CSS below is the FINISHED drawing, and
   js/sec-manufacturing.js winds the strokes back only when it has
   decided to animate them.
   ========================================================= */

.phero--plan {
  position: relative;
  padding-bottom: clamp(3rem, 8vh, 5.5rem);
  /* One variable for the plate's geometry, because the route is placed
     against the PLATE and not against the section. Anchoring the route
     to a percentage of the hero instead put it straight through the
     h1's baseline at 1440 and through the lede at 1100 — the copy
     block's height changes with the viewport and the plate's does not. */
  --plate-w: min(55%, 880px);
  --plate-h: min(62%, 430px);
  --route-lead: clamp(80px, 11vw, 170px);
}

/* The page's own wash, plus the sheet it is drawn on. */
.phero--plan .phero__bg {
  background:
    linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px) 0 0 / 100% 46px,
    linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px) 0 0 / 46px 100%,
    radial-gradient(120% 90% at 78% 18%, rgba(255,107,26,.14) 0%, rgba(255,107,26,0) 58%),
    radial-gradient(90% 70% at 8% 92%, rgba(22,56,95,.72) 0%, rgba(6,21,41,0) 70%);
  /* fades the grid out under the copy so it never fights the type */
  -webkit-mask-image: radial-gradient(120% 120% at 82% 78%, #000 32%, rgba(0,0,0,.55) 68%, rgba(0,0,0,.28) 100%);
          mask-image: radial-gradient(120% 120% at 82% 78%, #000 32%, rgba(0,0,0,.55) 68%, rgba(0,0,0,.28) 100%);
}

/* 41%, not 47%. The lede's own 58ch cap is wider than the space left of
   the plate at 1440, and its last line was landing ON the photograph —
   _qc/heroglyph-pim.js measured 4.26:1 against the picture where 4.5 is
   required. Nothing on this page's hero may sit on the plate. */
.mplan__copy { max-width: 41%; }
.mplan__jump { display: inline-flex; margin-top: clamp(1.1rem, 2.6vh, 1.6rem); }

/* --- the plate --------------------------------------------------- */

.mplan__plate {
  position: absolute; z-index: 1; margin: 0;
  right: calc(-1 * clamp(8px, 1.6vw, 32px));
  bottom: 0;
  width: var(--plate-w);
  height: var(--plate-h);
  overflow: hidden;
  border-top: 1px solid var(--rule-d2);
  border-left: 1px solid var(--rule-d2);
  border-radius: var(--rad) 0 0 0;
  isolation: isolate;
}
.mplan__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 52% 46%;
  /* Held well under the .ph--live grade in main.css on purpose: a
     drawing has to stay legible over it, and a bright plate would
     tip a navy-dominant band into a photo-dominant one. */
  filter: saturate(.9) brightness(.78) contrast(1.1);
}
.mplan__grade {
  position: absolute; inset: 0; display: block;
  background:
    linear-gradient(to right, rgba(6,21,41,.80) 0%, rgba(6,21,41,.26) 34%, rgba(6,21,41,.06) 100%),
    linear-gradient(to top, rgba(6,21,41,.46) 0%, rgba(6,21,41,0) 46%);
}
/* Drafting corner — two strokes, molten, at the plate's registered
   corner. This is the only ornament on it. */
.mplan__corner {
  position: absolute; left: 0; top: 0; display: block;
  width: clamp(26px, 3vw, 44px); height: clamp(26px, 3vw, 44px);
  border-top: 2px solid var(--molten);
  border-left: 2px solid var(--molten);
}

/* --- the route --------------------------------------------------- */

.mplan__route {
  position: absolute; z-index: 2;
  /* Fully opaque only from the plate's left edge onward; before that it
     is a lead-in that fades to nothing, so wherever the copy column
     happens to end at a given width the rail is already invisible
     rather than ruled through the type. */
  left: calc(100% - var(--plate-w) - var(--route-lead));
  right: clamp(30px, 8vw, 130px);
  top: calc(100% - var(--plate-h) + clamp(46px, 8vh, 86px));
  height: 40px;
  pointer-events: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.35) 14%, #000 26%, #000 100%);
          mask-image: linear-gradient(to right, transparent 0%, rgba(0,0,0,.35) 14%, #000 26%, #000 100%);
}
.mplan__svg { display: block; width: 100%; height: 100%; overflow: visible; }
.mplan__rail { stroke: var(--molten); stroke-width: 1.5; opacity: .9; }
.mplan__ticks line { stroke: var(--ember); stroke-width: 1.5; opacity: .62; }

/* The travelling head. A CSS element rather than an SVG circle,
   because the SVG box is stretched non-uniformly and a circle in it
   would arrive as an ellipse. */
.mplan__head {
  /* left:100% IS the finished state — the head parked at the end of the
     rail. The script tweens x from -railWidth back to 0, so no-JS and
     reduced motion both land on a drawing that has already arrived. */
  position: absolute; left: 100%; top: 50%;
  width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px;
  border-radius: 50%;
  background: #ffd9a8;
  box-shadow: 0 0 0 4px rgba(255,107,26,.28), 0 0 22px 6px var(--glow);
}
/* The pre-states. Only present once the script has committed to
   animating, so no-JS and reduced-motion see the completed drawing. */
.mplan--live .mplan__rail { stroke-dasharray: 1; stroke-dashoffset: 1; }
.mplan--live .mplan__ticks line { opacity: 0; }

/* Below 1180 the plate stops competing with the copy for the same
   corner and becomes a full-bleed band under it, with the route drawn
   across it. The breakpoint is where the h1's longest unbreakable word
   ("Manufacturing") plus the copy column stops clearing the plate's
   left edge — at 1100 the lede ran straight onto the photograph. */
@media (max-width: 1180px) {
  .phero--plan { padding-bottom: 0; --plate-h: clamp(180px, 40vw, 300px); }
  .mplan__copy { max-width: none; padding-bottom: clamp(2rem, 6vh, 3rem); }
  .mplan__plate {
    position: relative; right: auto; bottom: auto;
    width: auto; height: var(--plate-h);
    border-left: 0; border-radius: 0;
    margin: 0;
  }
  .mplan__corner { display: none; }
  .mplan__grade {
    background:
      linear-gradient(to right, rgba(6,21,41,.62) 0%, rgba(6,21,41,.18) 60%, rgba(6,21,41,.06) 100%),
      linear-gradient(to top, rgba(6,21,41,.5) 0%, rgba(6,21,41,0) 52%);
  }
  .mplan__img { filter: saturate(.9) brightness(.76) contrast(1.1); }
  /* Still drawn ACROSS the plate, which is now the band at the foot of
     the hero — half its height up, so the line sits in the picture. */
  .mplan__route {
    left: clamp(24px, 8vw, 90px); right: clamp(20px, 6vw, 60px);
    top: auto; bottom: calc(var(--plate-h) * .48);
    -webkit-mask-image: none; mask-image: none;
  }
}

/* Reduced motion needs no block of its own here: js/sec-manufacturing.js
   returns before start(), `.mplan--live` is never added, and the rules
   above already ARE the end state — rail whole, ticks visible, head
   parked at the end of the line. */

/* =========================================================
   1 · PROCESS — the eight stages, photograph-led

   REPLACES the 1280x800 plan drawing: the drafting grid, the
   bay lines, the three-stroke routed path (.mline__track /
   __glow / __core), the eight 88px .mst glyph plates and the
   SVG pour front. The long note in build/pages/manufacturing.html
   records why it went; the short version is that the section
   explaining how the metal is made had no photograph in it.

   What survives is the ROUTE, promoted from the old narrow-
   screen spine to the whole section's organising device: a
   cold track down the left, a molten fill scaled by the
   section's scroll progress, the pour front riding its leading
   edge, and a bracket branching off into every station. The
   stations still latch in order as the front reaches them, off
   the same single progress value — the reading is still "a line
   you travel", not "a grid of cards".

   THE PHOTOGRAPHS CARRY NO SCRIM, AND THAT IS THE POINT.
   Copy sits beside the plate (>=900px) or under it (below), and
   never on it, so these slots carry no text-contrast debt and
   take the full .ph--live grade from main.css unmodified — the
   grade Daniel re-judged against real photographs on 2026-08-08
   after the first one came out too dark. Nothing here darkens
   them further. On a sec--deep band the temptation is a scrim;
   a scrim is exactly how a dark band swallows a photograph, and
   this rebuild exists because the client could not see enough
   of them.

   THE --live CONVENTION still governs. Every rule below is the
   FINISHED state; the pre-states live under .mline--live, which
   js/sec-manufacturing.js adds only once it has committed to
   animating. No JS, a thrown error or reduced motion leaves
   eight complete photographic stations.
   ========================================================= */

.mline__run {
  position: relative;
  margin-top: clamp(1.8rem, 4vh, 3rem);

  /* The route's geometry lives in three custom properties so it only
     ever moves in one place. The rail, the node ring, the bracket and
     the list's own indent are all derived from them.
       --rail-x   centre line of the route, from .mline__run's left edge
       --rail-gap air between the route and the station content
       --node     diameter of the station marker on the route */
  --rail-x: 10px;
  --rail-gap: 1.5rem;
  --node: 20px;
}

/* ---- The route ------------------------------------------- */

/* Mid-grey rather than white at low alpha, unchanged from the retired
   schematic: this has to hold against navy without becoming a second
   bright line beside eight photographs. */
.mline__rail {
  position: absolute;
  left: calc(var(--rail-x) - 1px);
  top: calc(var(--node) / 2);
  bottom: 0;
  width: 2px;
  background: rgba(169, 187, 208, .26);
}

/* Bay-end ticks — the plan drawing's own marks (M40 48v24 and its
   three siblings), kept at the scale they now belong at. They are the
   reason the route reads as a drawn route and not as a progress bar. */
.mline__rail::before,
.mline__rail::after {
  content: '';
  position: absolute; left: -5px;
  width: 12px; height: 2px;
  background: rgba(169, 187, 208, .34);
}
.mline__rail::before { top: 0; }
.mline__rail::after { bottom: 0; }

/* Scaled on Y from --mp, which js/sec-manufacturing.js writes on
   .mline__run. Stretching the gradient is deliberate: the hot end
   stays at the drawn edge, which is where the front is. */
.mline__fill {
  position: absolute; inset: 0; display: block;
  background: linear-gradient(180deg, rgba(194, 65, 12, .85), var(--molten) 52%, var(--ember));
  transform: scaleY(1);
  transform-origin: 50% 0;
}

/* The pour front. Same construction as .thread__head in main.css so
   the two molten heads on this site are recognisably one device.
   Invisible until the script positions it — see .mline__head in the
   reduced-motion block at the foot of this file. */
.mline__head {
  position: absolute; left: 50%; top: 0; display: block;
  width: 11px; height: 11px; margin: -5.5px 0 0 -5.5px;
  border-radius: 50%;
  background: var(--ember);
  box-shadow: 0 0 12px 2px rgba(255, 107, 26, .85), 0 0 30px 8px rgba(255, 107, 26, .3);
  opacity: 0;
}

/* ---- Stations -------------------------------------------- */

.mline__nodes { padding-left: calc(var(--rail-x) + var(--rail-gap)); }

.mstn { position: relative; }
.mstn + .mstn { margin-top: clamp(2.6rem, 7vh, 5.5rem); }

/* The station marker ON the route. One pseudo-element, not two: the
   ring is the border and the dot is an inset shadow eaten out of a
   molten fill, so a single box-shadow value animates both. The old
   spine needed ::before AND ::after for the same mark, which left no
   pseudo-element for the bracket. */
.mstn::before {
  content: '';
  position: absolute; z-index: 2;
  left: calc(-1 * var(--rail-gap) - var(--node) / 2);
  top: 0;
  width: var(--node); height: var(--node);
  border-radius: 50%;
  border: 1px solid var(--molten);
  background: var(--molten);
  box-shadow: inset 0 0 0 calc(var(--node) / 3) var(--navy-900);
  transition: border-color var(--d-s) var(--e-quad),
              box-shadow var(--d-s) var(--e-out),
              transform var(--d-s) var(--e-out);
}

/* The bracket — the route branching into the station. This is the
   piece that keeps the rail from reading as a decorative timeline
   bar: the line does not run PAST the stations, it feeds them. */
.mstn::after {
  content: '';
  position: absolute;
  top: calc(var(--node) / 2 - 1px);
  left: calc(-1 * var(--rail-gap) + var(--node) / 2);
  width: calc(var(--rail-gap) - var(--node) / 2);
  height: 2px;
  background: linear-gradient(90deg, var(--molten), rgba(255, 107, 26, .16));
  transform: scaleX(1);
  transform-origin: 0 50%;
  transition: transform var(--d-m) var(--e-out);
}

/* ---- The plate ------------------------------------------- */

/* aspect-ratio on the frame, absolutely positioned contents: the box
   is the same size before the photograph decodes as after, which is
   what keeps eight of these off the CLS ledger. It is also what makes
   station 08's drawn terminal a drop-in slot — see the markup. */
.mstn__fig {
  position: relative;
  margin: 0;
  aspect-ratio: 16 / 9;
  max-width: 44rem;
  overflow: hidden;
  border: 1px solid var(--rule-d);
  border-radius: var(--rad);
  background: var(--navy-800);
  isolation: isolate;
}

/* Its own element, and it exists for exactly one reason: this is what
   carries the GSAP parallax transform, so the settle-scale on the
   photograph underneath is never fighting it for the same property.
   The -4.5% overhang is the travel the parallax is allowed. */
.mstn__plate {
  position: absolute; inset: -4.5% 0;
  transition: clip-path var(--d-l) var(--e-out);
}

.mstn__ph {
  position: absolute; inset: 0;
  transition: transform var(--d-xl) var(--e-out);
}

/* A single pass of heat across the plate as the front arrives — the
   .mst__hot flash from the retired stations, at photograph scale.
   Transient by construction: it ends at opacity 0, so the finished
   state of this element is invisible and a no-JS visitor loses
   nothing by never seeing it. */
.mstn__sweep {
  position: absolute; z-index: 3;
  top: -8%; bottom: -8%; left: 0;
  width: 52%;
  display: block;
  pointer-events: none;
  opacity: 0;
  background: linear-gradient(96deg,
      rgba(255, 145, 68, 0) 0%,
      rgba(255, 166, 92, .42) 46%,
      rgba(255, 107, 26, 0) 100%);
}

@keyframes mstn-sweep {
  0%   { opacity: 0;  transform: translate3d(-130%, 0, 0) skewX(-9deg); }
  18%  { opacity: .5; }
  100% { opacity: 0;  transform: translate3d(290%, 0, 0) skewX(-9deg); }
}

/* The registration corner, the same two-stroke mark the hero plate
   carries — bottom-left here rather than top-left, at the corner the
   copy runs on from. It is the only ornament on the plate. */
.mstn__corner {
  position: absolute; z-index: 4;
  left: 0; bottom: 0; display: block;
  width: clamp(20px, 2.4vw, 34px);
  height: clamp(20px, 2.4vw, 34px);
  border-left: 2px solid var(--molten);
  border-bottom: 2px solid var(--molten);
  transition: border-color var(--d-m) var(--e-out);
}

/* ---- Station 08 · the drawn terminal --------------------- */

/* The one place the retired plan drawing is kept, and it is kept on
   purpose: 40px grid, bay ticks, and the elbow-and-arrow out-mark that
   was .mline__out on the old sheet. Seven photographs and one drawing
   reads as a decision; seven photographs and one empty box reads as a
   mistake. Replaced wholesale by a .mstn__plate when the despatch
   photograph arrives — .mstn__fig owns the box, so nothing reflows. */
.mterm {
  position: absolute; inset: 0;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: clamp(.7rem, 2vh, 1.1rem);
  background-color: var(--navy-800);
  background-image:
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .055) 0 1px, transparent 1px 40px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, .055) 0 1px, transparent 1px 40px);
  transition: clip-path var(--d-l) var(--e-out);
}
.mterm__mark {
  width: clamp(104px, 26%, 168px);
  height: auto;
  overflow: visible;
}
.mterm__line,
.mterm__tip {
  fill: none;
  stroke: var(--molten);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke var(--d-m) var(--e-out);
}
.mterm__cap {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--steel-dim);
}

/* ---- Labels ---------------------------------------------- */

.mstn__body { padding-top: clamp(1rem, 2.6vh, 1.5rem); }

.mstn__no {
  display: block;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .16em;
  color: var(--molten);
}

/* Deliberately never animated, along with .mstn__no. The photograph,
   the rule and the description are all gated on the front arriving;
   the number and the title are what tell a visitor where they are if
   any of that gating ever fails to release. */
.mstn__t {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(1.08rem, .98rem + .42vw, 1.42rem);
  line-height: 1.22;
  letter-spacing: -.014em;
  color: var(--white);
  margin: .5rem 0 0;
}

/* A tick, not a rule across the column. Eight full-width molten bars
   beside eight photographs is more accent than this direction allows —
   molten carries the process marks, and a mark is what this is. */
.mstn__rule {
  display: block;
  width: clamp(3rem, 5vw, 5rem);
  height: 2px;
  background: var(--molten);
  margin: .85rem 0;
  transform: scaleX(1);
  transform-origin: 0 50%;
  transition: transform var(--d-m) var(--e-out);
}

.mstn__d {
  font-size: var(--fs-small);
  line-height: 1.62;
  color: var(--steel);
  max-width: 46ch;
  margin: 0;
  transition: opacity var(--d-m) var(--e-out), transform var(--d-m) var(--e-out);
}

/* ---- Wide: the plate and the copy sit side by side -------- */

/* 900px, not the schematic's old 1100px. The drawing needed 1100px of
   room before its eight stations stopped colliding; two columns and a
   photograph do not, and a 1024px tablet gets the composed layout
   instead of a 500px-tall stacked plate. */
@media (min-width: 900px) {
  .mline__run {
    --rail-x: 15px;
    --rail-gap: clamp(2.4rem, 3.6vw, 4.2rem);
    --node: 26px;
  }

  .mstn {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: clamp(1.8rem, 3.2vw, 3.4rem);
    align-items: center;
  }
  .mstn__fig { max-width: none; }
  .mstn__body { padding-top: 0; }

  /* Alternating sides, source order untouched. Every station reads
     figure-then-body to a screen reader whichever way it is laid out,
     which is the whole reason the placement is done here and not with
     two different orders in the markup. */
  .mstn--b { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .mstn--b .mstn__fig  { grid-column: 2; grid-row: 1; }
  .mstn--b .mstn__body { grid-column: 1; grid-row: 1; }

  /* 05 · the crescendo. One station has to be bigger than the others
     or eight plates on a rail read as a table, and the quench curtains
     are the only frame in the set that shows the metal being made.
     2/1 trims 44px off a 788px original — nothing in the frame is
     lost, and the wider box is what makes it read as a moment. */
  .mstn--wide .mstn__fig {
    grid-column: 1 / -1;
    grid-row: 1;
    aspect-ratio: 2 / 1;
  }
  .mstn--wide .mstn__body {
    grid-column: 1 / -1;
    grid-row: 2;
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: clamp(1.8rem, 3.2vw, 3.4rem);
    grid-template-areas: 'no d' 't d' 'rule d';
    align-content: start;
    padding-top: clamp(1.4rem, 3vh, 2.2rem);
  }
  .mstn--wide .mstn__no   { grid-area: no; }
  .mstn--wide .mstn__t    { grid-area: t; font-size: clamp(1.5rem, 1.1rem + 1.2vw, 2.15rem); }
  .mstn--wide .mstn__rule { grid-area: rule; width: clamp(4rem, 7vw, 7rem); }
  .mstn--wide .mstn__d    { grid-area: d; align-self: center; font-size: var(--fs-body); max-width: 52ch; }
}

/* ---- Armed: the pre-states, only once JS is driving ------- */

.mline--live .mline__fill { transform: scaleY(var(--mp, 0)); }

/* The frame, its rim and its corner stay — an empty registered box
   waiting for its plate. Only the picture is withheld, and it wipes in
   left to right, the same gesture .mledger__row uses further down this
   page. */
.mline--live .mstn__plate,
.mline--live .mterm { clip-path: inset(0 100% 0 0); }
.mline--live .mstn.is-on .mstn__plate,
.mline--live .mstn.is-on .mterm { clip-path: inset(0 0 0 0); }

.mline--live .mstn__ph { transform: scale(1.06); }
.mline--live .mstn.is-on .mstn__ph { transform: scale(1); }

.mline--live .mstn__corner { border-color: rgba(255, 255, 255, .2); }
.mline--live .mstn.is-on .mstn__corner { border-color: var(--molten); }

.mline--live .mterm__line,
.mline--live .mterm__tip { stroke: var(--steel-dim); }
.mline--live .mstn.is-on .mterm__line,
.mline--live .mstn.is-on .mterm__tip { stroke: var(--molten); }

/* No fill-mode on purpose. With `both` the sweep parks on its 100%
   keyframe — a transparent strip left translated 290% to the right of
   its own box for the rest of the session. It is clipped by the frame
   and costs nothing, but it leaves an element whose rect sits outside
   the viewport, which is exactly the shape of a real overflow bug and
   will cost somebody an afternoon. Let it return to its base state. */
.mline--live .mstn.is-on .mstn__sweep { animation: mstn-sweep 1s var(--e-quad); }

.mline--live .mstn__rule { transform: scaleX(0); }
.mline--live .mstn.is-on .mstn__rule { transform: scaleX(1); }
.mline--live .mstn__d { opacity: 0; transform: translateY(10px); }
.mline--live .mstn.is-on .mstn__d { opacity: 1; transform: none; }

.mline--live .mstn::after { transform: scaleX(0); }
.mline--live .mstn.is-on::after { transform: scaleX(1); }

.mline--live .mstn::before {
  border-color: rgba(255, 255, 255, .22);
  box-shadow: inset 0 0 0 calc(var(--node) / 2) var(--navy-900);
  transform: scale(.82);
}
.mline--live .mstn.is-on::before {
  border-color: var(--molten);
  box-shadow: inset 0 0 0 calc(var(--node) / 3) var(--navy-900),
              0 0 16px rgba(255, 107, 26, .45);
  transform: scale(1);
}

/* =========================================================
   2 · INFRASTRUCTURE — the plant, hard to the right edge
   ========================================================= */

.minfra { overflow: hidden; }

.minfra__media {
  position: absolute;
  inset: 0 0 0 50%;
  z-index: 0;
  overflow: hidden;
}
.minfra__img {
  position: absolute; inset: -6% 0;
  /* The photograph owns the right edge of the viewport and dissolves into
     the navy on its inner side — the same device the homepage hero uses,
     which is why the two read as one building rather than two pictures.
     Inset vertically so the scrubbed drift never exposes an edge. */
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
          mask-image: linear-gradient(90deg, transparent 0%, #000 26%);
  will-change: transform;
}

.minfra__inner { position: relative; z-index: 2; }
/* The cap goes HERE, not on `.wrap` — see the note in the fragment. */
.minfra__col { max-width: 44%; }
.minfra .sechead--stack { margin-bottom: 0; }
.minfra .sechead--stack > div { max-width: 100%; }

.mledger { margin: clamp(1.6rem, 4vh, 2.4rem) 0 0; display: grid; }
.mledger__row {
  display: grid;
  grid-template-columns: minmax(6.5rem, 10.5rem) minmax(0, 1fr);
  gap: .4rem 1.4rem;
  padding: .95rem 0;
  border-top: 1px solid var(--rule-d);
}
.mledger__row:last-child { border-bottom: 1px solid var(--rule-d); }
.mledger dt {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--steel-dim);
  padding-top: .3em;
}
.mledger dd {
  margin: 0;
  font-family: var(--f-display);
  font-weight: 300;
  font-size: clamp(1rem, .94rem + .28vw, 1.2rem);
  line-height: 1.32;
  letter-spacing: -.008em;
  color: var(--white);
}
.minfra__go { margin-top: clamp(1.4rem, 3.4vh, 2rem); }

@media (max-width: 1000px) {
  .minfra__media {
    position: relative; inset: auto;
    height: clamp(220px, 46vw, 400px);
    margin-bottom: clamp(1.8rem, 4vh, 2.6rem);
  }
  /* The horizontal mask above is exact because the image spans the media box
     horizontally. Vertically it does NOT — it is inset past both edges so the
     scrubbed drift never exposes one — so a vertical mask on the image gets
     clipped before it reaches transparent and leaves a hard bottom edge. The
     fade goes on the CONTAINER instead, where it is immune to the transform. */
  .minfra__img {
    inset: -8% 0;
    -webkit-mask-image: none;
            mask-image: none;
  }
  .minfra__media::after {
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    background: linear-gradient(180deg, rgba(10, 30, 60, 0) 58%, var(--navy-800) 100%);
  }
  .minfra__col { max-width: 100%; }
}
@media (max-width: 560px) {
  .mledger__row { grid-template-columns: 1fr; }
}

/* =========================================================
   3 · CAPABILITY — three records on paper
   ========================================================= */

.mcap__rows { margin-top: clamp(1.4rem, 3vh, 2.2rem); }

.mcap__row {
  position: relative;
  display: grid;
  /* rem, not ch: `ch` resolves against the GRID's font-size, not the h3's,
     so a value tuned by eye against the heading comes out roughly half the
     intended width. */
  grid-template-columns: minmax(0, 21rem) minmax(0, 1fr);
  gap: clamp(1.2rem, 3vw, 3.4rem);
  align-items: start;
  padding: clamp(1.8rem, 4vh, 2.8rem) 0;
  border-top: 1px solid var(--rule-l);
}
.mcap__row:last-child { border-bottom: 1px solid var(--rule-l); }

/* The index is scenery: set at a size no label would ever be set at and
   parked behind the type. That is what stops these rows reading as three
   cards with a number in the corner. It is a WATERMARK, so it takes the
   faintest rule token — at `--rule-l2` it competed with the body copy
   sitting on top of it. */
.mcap__no {
  position: absolute;
  left: -.06em; top: clamp(.4rem, 1.6vh, 1rem);
  z-index: 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(4.5rem, 9vw, 8.5rem);
  line-height: .8;
  letter-spacing: -.05em;
  color: var(--rule-l);
  pointer-events: none;
  -webkit-user-select: none; user-select: none;
}

.mcap__claim { position: relative; z-index: 1; }
.mcap__claim h3 {
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(1.15rem, 1rem + .55vw, 1.55rem);
  line-height: 1.16;
  letter-spacing: -.018em;
  color: var(--ink);
  margin: 0 0 .6rem;
}
.mcap__claim p { margin: 0; font-size: var(--fs-small); color: var(--slate); }

/* A photograph under the claim (2026-08-09), on Process Control and Testing
   Capability. Deliberately in the LEFT column rather than as a third grid
   column: Traceability has no picture, and an empty third column would read
   as a hole and break the alignment the three stacked rows share. Under the
   claim, a row without one is simply shorter.

   This band is on the light section, so it takes no scrim — nothing is
   overlaid on it and the copy sits above it on paper. */
.mcap__ph {
  aspect-ratio: 16 / 9;
  margin-top: clamp(1rem, 2.4vh, 1.5rem);
  border-radius: var(--rad);
  border: 1px solid var(--rule-l);
}
.mcap__ph.ph--live { filter: saturate(.96) contrast(1.03); }

.mcap__reg {
  position: relative; z-index: 1;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: .1rem clamp(1rem, 2.4vw, 2.4rem);
  align-content: start;
}
.mcap__reg li {
  position: relative;
  padding: .55rem 0 .55rem 1.5rem;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--slate);
  border-bottom: 1px solid var(--rule-l);
}
/* 2px, not 1px: these ticks sit at fractional device-pixel offsets down a
   list, so a hairline anti-aliases to a washed grey on half the rows and
   renders solid on the other half. Same reason as `.mstn__rule`. */
.mcap__reg li::before {
  content: '';
  position: absolute;
  left: 0; top: 1.05em;
  width: 10px; height: 2px;
  background: var(--molten-ink);
}

@media (max-width: 900px) {
  .mcap__row { grid-template-columns: 1fr; }
  .mcap__no {
    position: static; display: block; margin-bottom: .2rem;
    font-size: clamp(3.4rem, 13vw, 5rem); color: var(--rule-l2);
  }
}
@media (max-width: 620px) {
  .mcap__reg { grid-template-columns: 1fr; }
}

/* =========================================================
   4 · BATCH — the numerals, deliberately unequal
   ========================================================= */

/* The capability list enters from the right, and in LTR a rightward
   overhang is real horizontal overflow (a leftward one is not). Clipping
   the band survives every offset rather than one tuned per breakpoint. */
.mbatch { overflow: hidden; }

.mbatch__head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: .2rem clamp(1.4rem, 3.4vw, 3.4rem);
  /* Bottom-aligned: the capability list is half the height of the heading
     column, and hanging it from the top left a dead quarter-screen on the
     right of the band. */
  align-items: end;
}
.mbatch .sechead--stack { margin-bottom: 0; }
.mbatch .arrowlink { grid-column: 1; margin-top: clamp(1.2rem, 3vh, 2rem); }

.mbatch__list { display: grid; gap: .2rem; align-content: start; padding-top: .3rem; }
.mbatch__list li {
  position: relative;
  padding: .6rem 0 .6rem 1.6rem;
  font-size: var(--fs-small);
  color: var(--steel);
  border-bottom: 1px solid var(--rule-d);
}
/* Navy-700 is the lightest of the four bands; molten measures under the
   floor there, so every accent in this section steps up to ember. */
.mbatch__list li::before {
  content: '';
  position: absolute;
  left: 0; top: 1.1em;
  width: 10px; height: 2px;
  background: var(--ember);
}

/* Four figures, four sizes, four baselines. A repeat(4, 1fr) row of stat
   boxes is exactly the shape this redesign exists to remove. */
.mfig {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(1.4rem, 3vh, 2.4rem) clamp(1rem, 2.4vw, 2rem);
  margin-top: clamp(2.4rem, 6vh, 4rem);
  align-items: end;
}
.mfig__item { position: relative; padding-top: 1.1rem; border-top: 1px solid var(--rule-d2); }
.mfig__item--a { grid-column: 1 / span 6;  grid-row: 1; }
.mfig__item--b { grid-column: 8 / span 5;  grid-row: 1; transform: translateY(clamp(.8rem, 2.6vh, 2.2rem)); }
.mfig__item--c { grid-column: 1 / span 4;  grid-row: 2; }
.mfig__item--d { grid-column: 6 / span 6;  grid-row: 2; transform: translateY(clamp(.6rem, 1.8vh, 1.5rem)); }

.mfig__v {
  display: block;
  font-family: var(--f-display);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
  color: var(--white);
}
.mfig__item--a .mfig__v { font-size: clamp(2.1rem, 1.1rem + 3.4vw, 4.2rem); }
.mfig__item--b .mfig__v { font-size: clamp(1.7rem, 1rem + 2.2vw, 3rem); }
.mfig__item--c .mfig__v { font-size: clamp(1.5rem, 1rem + 1.5vw, 2.3rem); }
.mfig__item--d .mfig__v { font-size: clamp(1.5rem, 1rem + 1.5vw, 2.3rem); font-weight: 300; }
.mfig__k {
  display: block;
  margin-top: .6rem;
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--steel-dim);
}
.mfig__item--d .mfig__k { color: var(--ember); }

@media (max-width: 900px) {
  .mbatch__head { grid-template-columns: 1fr; }
  .mfig__item--a { grid-column: 1 / span 12; grid-row: 1; }
  .mfig__item--b { grid-column: 1 / span 12; grid-row: 2; transform: none; }
  .mfig__item--c { grid-column: 1 / span 5;  grid-row: 3; }
  .mfig__item--d { grid-column: 7 / span 6;  grid-row: 3; transform: none; }
}
@media (max-width: 560px) {
  .mfig__item--c, .mfig__item--d { grid-column: 1 / span 12; }
  .mfig__item--d { grid-row: 4; }
}

/* =========================================================
   5 · PROMISE — the statement plate
   ========================================================= */

.mpromise__words {
  display: flex;
  flex-wrap: wrap;
  gap: .4em clamp(.6rem, 2.4vw, 2.2rem);
  margin: clamp(1.1rem, 3vh, 1.8rem) 0 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(1.9rem, .9rem + 4vw, 4.4rem);
  line-height: 1.06;
  letter-spacing: -.03em;
  color: var(--white);
}
.mpromise__words span { position: relative; display: block; }
/* A molten hairline under each word — the seam's language at word scale. */
.mpromise__words span::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -.14em; height: 2px;
  background: var(--molten);
  transform: scaleX(var(--wr, 1));
  transform-origin: 0 50%;
}
.mpromise--live .mpromise__words span { --wr: 0; }

/* rem, not ch — `ch` here resolves against the grid's 1rem body size, not
   against the display type in the first column, which pinched the heading
   to three lines. */
.mpromise__body {
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 34rem);
  gap: clamp(1.2rem, 3vw, 3.2rem);
  align-items: start;
  margin-top: clamp(2rem, 5vh, 3.2rem);
}
.mpromise__t { max-width: none; }
.mpromise__body > p { margin: 0; color: var(--steel); }

/* The page's ONE uniform grid, and deliberately its quietest object: a
   hairline record strip, not four more cards. */
.mrec {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: clamp(2.4rem, 6vh, 3.6rem) 0 0;
  border-top: 1px solid var(--rule-d2);
}
.mrec__cell { padding: clamp(1rem, 2.4vh, 1.5rem) clamp(.8rem, 1.6vw, 1.4rem) 0 0; }
.mrec__cell + .mrec__cell { padding-left: clamp(.9rem, 1.8vw, 1.6rem); border-left: 1px solid var(--rule-d); }
.mrec dt {
  font-family: var(--f-mono);
  font-size: var(--fs-label);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--steel-dim);
}
.mrec dd {
  margin: .45rem 0 0;
  font-family: var(--f-display);
  font-weight: 600;
  font-size: clamp(1.15rem, .9rem + .8vw, 1.7rem);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
  color: var(--white);
}

@media (max-width: 860px) {
  .mpromise__body { grid-template-columns: 1fr; }
  .mrec { grid-template-columns: repeat(2, 1fr); }
  .mrec__cell:nth-child(2n+1) { padding-left: 0; border-left: 0; }
  .mrec__cell:nth-child(n+3) { border-top: 1px solid var(--rule-d); margin-top: .4rem; }
}
@media (max-width: 460px) {
  .mrec { grid-template-columns: 1fr; }
  .mrec__cell,
  .mrec__cell + .mrec__cell { padding-left: 0; border-left: 0; }
  .mrec__cell + .mrec__cell { border-top: 1px solid var(--rule-d); margin-top: .4rem; }
}

/* =========================================================
   REDUCED MOTION
   js/sec-manufacturing.js never arms the section, so nothing
   above is in a pre-state and the page is already finished.
   These two lines are belt and braces for the pieces the
   script owns directly.
   ========================================================= */

@media (prefers-reduced-motion: reduce) {
  .mline__head { display: none; }
  .minfra__img { transform: none; }
}
