/* ==========================================================================
   FROM COIL TO PIPE — the scroll-forming sequence.
   CSS sticky pin + one rAF loop. No libraries. Transform and opacity only.

   The pin is a TRUE CENTRED PIN (revision 4): the composition is centred in
   the space below the fixed header and does not travel while it plays, so it
   can never be clipped by the header or run away from its caption.
   ========================================================================== */

.forge {
  position: relative;
  height: 260vh;
  background: var(--navy-950);
  --pipe-length: 640px;
  --slat-h: 14px;
}
@media (max-width: 899px) { .forge { height: 190vh; } }

/* TRUE CENTRED PIN. The composition is centred in the space BELOW the fixed
   header — padding-top reserves it — and stays there for the whole sequence.
   Nothing drifts up into the header, so nothing can be clipped by it. */
.forge__sticky {
  position: sticky; top: 0;
  height: 100svh;
  padding-top: var(--header-h);   /* keep the composition clear of the header, always */
  overflow: hidden;
  display: grid;
  place-items: center;
  isolation: isolate;
}

/* Atmosphere behind the scene — a lit mill floor, not a black void. */
.forge__sticky::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(70% 55% at 50% 46%, rgba(12, 70, 129, 0.30), transparent 70%),
    radial-gradient(120% 80% at 50% 118%, rgba(1, 13, 34, 0.9), transparent 60%);
}
/* Floor line — grounds the tube so it isn't floating in space. */
.forge__sticky::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 20%; height: 1px; z-index: 0;
  background: linear-gradient(90deg, transparent, rgba(113, 203, 227, 0.16) 22%, rgba(113, 203, 227, 0.16) 78%, transparent);
  pointer-events: none;
}

.forge__scene {
  position: relative; z-index: 1;
  width: 100%; height: 100%;
  display: grid; place-items: center;
  transform-origin: 50% 50%;
  will-change: transform, opacity;
}
.forge__cards { will-change: transform; }

/* --------------------------------------------------------------------------
   3D STAGE
   -------------------------------------------------------------------------- */
.forge__stage {
  position: absolute; inset: 0;
  perspective: 1700px;
  transform-style: preserve-3d;
  display: grid; place-items: center;
}

.forge__pipe {
  position: absolute; left: 50%; top: 50%;
  width: 0; height: 0;
  transform-style: preserve-3d;
  will-change: transform;
}

/* Each slat is one thin strip running the full length of the pipe at a fixed
   circumferential angle. 48 of them close into a cylinder of radius W / 2pi. */
.forge__slat {
  position: absolute; left: 0; top: 0;
  width: var(--pipe-length);
  height: calc(var(--slat-h) + 0.6px);   /* 0.6px overlap kills hairline gaps */
  margin-left: calc(var(--pipe-length) / -2);
  margin-top: calc((var(--slat-h) + 0.6px) / -2);
  transform-style: flat;
  /* Rolled-steel base: light falls off along the axis. No per-slat edge
     highlight — 48 of those read as corrugation, not as a smooth surface. */
  background-image:
    repeating-linear-gradient(90deg, rgba(0,0,0,0.045) 0 2px, transparent 2px 5px),
    linear-gradient(90deg,
      #141317 0%, #2f353c 5%, #5d656f 14%, #838c97 24%, #a2abb6 33%,
      #8d96a1 41%, #737b86 52%, #575e68 65%, #3b424a 79%, #23282e 91%, #121519 100%);
}

/* Promoted only while the section is on screen, dropped again on exit. */
.forge__pipe.is-live { will-change: transform; }
.forge__pipe.is-live .forge__slat { will-change: transform, filter; }

/* --------------------------------------------------------------------------
   COIL  (stage 01)
   -------------------------------------------------------------------------- */
.forge__coil {
  position: absolute; top: 50%; left: clamp(-70px, -3vw, -10px);
  transform: translateY(-50%);
  width: clamp(210px, 23vw, 320px); height: auto;
  z-index: 2; pointer-events: none;
}
.forge__coil svg { width: 100%; height: auto; }
.forge__coil .cl-arc { fill: none; stroke: rgba(169, 182, 198, 0.5); stroke-width: 1.1; }
.forge__coil .cl-arc-hi { stroke: rgba(113, 203, 227, 0.55); }
.forge__coil .cl-core { fill: rgba(1, 13, 34, 0.9); stroke: rgba(113, 203, 227, 0.4); stroke-width: 1.2; }
.forge__coil .cl-body { fill: none; stroke: rgba(169, 182, 198, 0.45); stroke-width: 1.4; }
.forge__coil .cl-face { fill: url(#clFace); }
.forge__coil .cl-lit { fill: none; stroke: rgba(206, 214, 224, 0.75); stroke-width: 2.6; stroke-linecap: round; }
.forge__coil .cl-pay { stroke: rgba(169, 182, 198, 0.55); stroke-width: 2.2; stroke-linecap: round; }
.forge__coil .cl-pay--dim { stroke: rgba(113, 203, 227, 0.28); stroke-width: 1.4; }

/* --------------------------------------------------------------------------
   SLITTING GUIDES + DIMENSION CALLOUT  (stage 02)
   -------------------------------------------------------------------------- */
.forge__slit { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.forge__guide {
  position: absolute; left: 50%; top: 50%;
  width: clamp(260px, 46vw, 720px); height: 1px;
  margin-left: calc(clamp(260px, 46vw, 720px) / -2);
  background: linear-gradient(90deg, transparent, var(--cyan-400) 18%, var(--cyan-400) 82%, transparent);
  opacity: 0;
}
.forge__guide::after {
  content: ''; position: absolute; right: -1px; top: -4px;
  width: 1px; height: 9px; background: var(--cyan-400);
}
.forge__dim {
  position: absolute; left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.1em;
  color: var(--cyan-400); background: rgba(1, 13, 34, 0.86);
  border: 1px solid rgba(113, 203, 227, 0.35); border-radius: 2px;
  padding: 5px 10px; white-space: nowrap; opacity: 0;
}

/* --------------------------------------------------------------------------
   FORMING ROLLS  (stage 03)
   -------------------------------------------------------------------------- */
.forge__rolls { position: absolute; inset: 0; z-index: 4; pointer-events: none; }
.forge__roll {
  position: absolute; left: 50%; top: 50%;
  width: 96px; height: 96px; margin: -48px 0 0 -48px;
  opacity: 0;
}
.forge__roll .rl-body { fill: rgba(18, 23, 29, 0.92); stroke: rgba(169, 182, 198, 0.45); stroke-width: 1.4; }
.forge__roll .rl-rim  { fill: none; stroke: rgba(113, 203, 227, 0.4); stroke-width: 1; }
.forge__roll .rl-groove { stroke: rgba(113, 203, 227, 0.30); stroke-width: 1.1; fill: none; }
.forge__roll .rl-spoke { stroke: rgba(169, 182, 198, 0.4); stroke-width: 1.2; }
.forge__roll .rl-hub  { fill: rgba(47, 58, 69, 0.9); stroke: rgba(169, 182, 198, 0.5); stroke-width: 1; }

/* SVG groups spun from JS need an explicit box to rotate about. */
.rl-spin, .forge__coil-spin { transform-box: fill-box; transform-origin: 50% 50%; }

/* --------------------------------------------------------------------------
   WELD SEAM + GLOW  (stage 04)  — lives inside the 3D scene
   -------------------------------------------------------------------------- */
/* The seam sits at alpha = PI, so its element carries rotateX(180deg). That
   flips Y and Z but leaves X alone, so the glow still travels left to right
   and the bar's own gradient is vertically symmetric. No mirror correction. */
.forge__seam {
  position: absolute; left: 0; top: 0;
  width: var(--pipe-length); height: 5px;
  margin-left: calc(var(--pipe-length) / -2); margin-top: -2.5px;
  opacity: 0;
  background: linear-gradient(to bottom,
    rgba(1,13,34,0.5) 0%, rgba(140,42,0,0.55) 30%, rgba(206,206,206,0.75) 50%,
    rgba(140,42,0,0.55) 70%, rgba(1,13,34,0.5) 100%);
}

/* Hot core with a ~200px cooling trail behind it: white-hot core, amber,
   dull red, back to steel. One element, translated in X. */
.forge__glow {
  position: absolute; top: 50%; left: 50%;
  width: 280px; height: 30px; margin-top: -15px; margin-left: -140px;
  border-radius: 50%;
  background: linear-gradient(90deg,
    rgba(90, 24, 0, 0) 0%, rgba(120, 30, 0, 0.42) 22%,
    rgba(176, 44, 0, 0.66) 42%, rgba(232, 96, 12, 0.84) 60%,
    rgba(255, 150, 52, 0.94) 74%, rgba(255, 214, 150, 1) 86%,
    rgba(255, 243, 214, 1) 94%, rgba(255, 243, 214, 0.86) 100%);
  opacity: 0;
}

/* Cyan rim light. The per-slat filter is monochrome, so the cool edge the
   metal needs is carried by one tinted bar sitting at the rim angle. */
.forge__rim {
  position: absolute; left: 0; top: 0;
  width: var(--pipe-length); height: 14px;
  margin-left: calc(var(--pipe-length) / -2); margin-top: -7px;
  background: linear-gradient(to bottom,
    transparent, rgba(113, 203, 227, 0.42) 45%, rgba(160, 220, 240, 0.55) 52%,
    rgba(113, 203, 227, 0.30) 62%, transparent);
  opacity: 0; pointer-events: none;
}

/* Longitudinal mill scale on the raw strip, polished away by stage 03. */
.forge__millscale {
  position: absolute; left: 0; top: 0;
  opacity: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg,
      rgba(20, 14, 8, 0.22) 0 2px, transparent 2px 7px,
      rgba(60, 48, 32, 0.14) 7px 9px, transparent 9px 16px);
}

/* Radial heat bloom on the slats around the seam, travelling with the head. */
.forge__heat {
  position: absolute; left: 0; top: 0;
  width: 300px; height: 190px; margin-left: -150px; margin-top: -95px;
  border-radius: 50%;
  background: radial-gradient(closest-side,
    rgba(255, 200, 120, 0.42) 0%, rgba(255, 122, 24, 0.24) 38%,
    rgba(140, 42, 0, 0.12) 66%, transparent 100%);
  opacity: 0;
}

/* --------------------------------------------------------------------------
   WELD HEAD  (2D overlay, positioned from the projected seam point)
   -------------------------------------------------------------------------- */
.forge__head {
  position: absolute; left: 0; top: 0;
  width: 68px; height: 82px; margin: -41px 0 0 -34px;
  z-index: 6; opacity: 0; pointer-events: none;
  filter: drop-shadow(0 0 14px rgba(255, 138, 43, 0.35));
}
.forge__head .hd-box { fill: rgba(18, 23, 29, 0.95); stroke: var(--cyan-400); stroke-width: 1.2; }
.forge__head .hd-fin { stroke: rgba(169, 182, 198, 0.6); stroke-width: 1.2; }
.forge__head .hd-tip { fill: var(--weld-hot); }
.forge__head .hd-coil { fill: none; stroke: rgba(255, 138, 43, 0.85); stroke-width: 1.4; }

/* --------------------------------------------------------------------------
   END CAP + FLANGE  (stages 05 / 06) — inside the 3D scene
   -------------------------------------------------------------------------- */
.forge__endcap {
  position: absolute; left: 0; top: 0;
  border-radius: 50%;
  background:
    radial-gradient(closest-side, rgba(18,23,29,0.98) 0 62%, rgba(120,129,139,0.9) 63%, rgba(58,66,75,0.95) 100%);
  box-shadow: inset 0 0 0 1px rgba(206, 206, 206, 0.35);
  opacity: 0;
}
.forge__flange {
  position: absolute; left: 0; top: 0;
  opacity: 0;
}
.forge__flange svg { width: 100%; height: 100%; display: block; }
.forge__flange .fl-face { fill: #2c333b; stroke: rgba(206,206,206,0.55); stroke-width: 1.4; }
.forge__flange .fl-raise { fill: #454e59; stroke: rgba(214,214,212,0.45); stroke-width: 1.1; }
.forge__flange .fl-bore { fill: #0b0f13; stroke: rgba(206,206,206,0.45); stroke-width: 1.2; }
.forge__flange .fl-bolt { fill: #10141a; stroke: rgba(169,182,198,0.5); stroke-width: 1; }
.forge__flange .fl-etch { opacity: 0; }

/* --------------------------------------------------------------------------
   CUT LINE  (stage 05)
   -------------------------------------------------------------------------- */
.forge__cut {
  position: absolute; left: 50%; top: 50%;
  width: 2px; height: 42vh; margin-top: -21vh;
  background: linear-gradient(to bottom, transparent, var(--weld-hot) 25%, var(--weld-hot) 75%, transparent);
  box-shadow: 0 0 12px rgba(255, 243, 214, 0.55);
  opacity: 0; z-index: 5; pointer-events: none;
}

/* --------------------------------------------------------------------------
   SPARKS CANVAS  (stage 04)
   -------------------------------------------------------------------------- */
.forge__sparks {
  position: absolute; inset: 0; z-index: 7;
  width: 100%; height: 100%; pointer-events: none;
}

/* --------------------------------------------------------------------------
   STAGE CARDS
   -------------------------------------------------------------------------- */
.forge__cards {
  position: absolute; z-index: 8; pointer-events: none;
  left: var(--gut); bottom: 92px; right: var(--gut);
}
/* The pin centres the pipe in the space below the header, so anything that
   has to sit on the pipe's axis is centred on the same line, not on the raw
   viewport centre. Otherwise the caption drifts half a header off the tube. */
@media (min-width: 900px) {
  .forge__cards {
    left: var(--gut); right: auto; top: calc(50% + var(--header-h) / 2); bottom: auto;
    transform: translateY(-50%);
    width: min(30vw, 360px);
  }
}

.forge__card {
  position: absolute; left: 0; bottom: 0; width: 100%;
  opacity: 0; transform: translateY(12px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
}
@media (min-width: 900px) { .forge__card { bottom: auto; top: 0; } }
.forge__card.is-on { opacity: 1; transform: none; }

.forge__card-n {
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.18em;
  color: var(--cyan-400); display: flex; align-items: center; gap: 10px; margin-bottom: 14px;
}
.forge__card-n::before { content: ''; width: 22px; height: 1px; background: currentColor; opacity: 0.6; }
.forge__card-t {
  font-family: var(--font-display); font-stretch: 125%; font-weight: 700;
  font-size: clamp(1.375rem, 2.4vw, 2rem); line-height: 1.08; letter-spacing: -0.02em;
  color: var(--text-hi);
}
.forge__card-d { color: var(--text-mid); font-size: 0.9375rem; line-height: 1.6; margin-top: 14px; max-width: 42ch; }
.forge__card-s {
  display: inline-block; margin-top: 16px; padding: 7px 11px;
  font-family: var(--font-mono); font-size: 0.6875rem; letter-spacing: 0.04em;
  color: var(--text-hi); background: rgba(1, 13, 34, 0.7);
  border: 1px solid rgba(113, 203, 227, 0.28); border-radius: 2px;
}
@media (max-width: 899px) {
  .forge__card-d { display: none; }
  .forge__cards { bottom: 76px; }
}

/* --------------------------------------------------------------------------
   PROGRESS RAIL  (desktop only)
   -------------------------------------------------------------------------- */
.forge__rail {
  position: absolute; right: var(--gut); top: calc(50% + var(--header-h) / 2);
  transform: translateY(-50%);
  z-index: 8; display: none; gap: 2px; flex-direction: column; pointer-events: none;
}
@media (min-width: 1080px) { .forge__rail { display: flex; } }

.forge__tick { display: flex; align-items: center; gap: 12px; justify-content: flex-end; height: 46px; }
.forge__tick-l {
  font-family: var(--font-mono); font-size: 0.625rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--text-low);
  transition: color 260ms var(--ease); text-align: right;
}
.forge__tick-b {
  position: relative; width: 2px; height: 100%; background: rgba(233, 238, 245, 0.12); flex: none;
}
.forge__tick-b i {
  position: absolute; inset: 0; background: var(--cyan-400);
  transform: scaleY(0); transform-origin: top;
  transition: transform 120ms linear;
}
.forge__tick.is-on .forge__tick-l { color: var(--cyan-400); }


/* --------------------------------------------------------------------------
   WELCOME MOMENT
   The payoff at the end of the scroll: the mark lifts off the flange face,
   the wordmark resolves under it, a cyan hairline draws outward from centre.
   Carries the page's only <h1>, present in the HTML from first paint.
   -------------------------------------------------------------------------- */
.forge__welcome {
  position: absolute; left: 0; right: 0; top: calc(50% + var(--header-h) / 2);
  transform: translate3d(0, -50%, 0);
  z-index: 9; opacity: 0; pointer-events: none;
  padding-inline: var(--gut);
  text-align: center;
  will-change: transform, opacity;
}
.forge__wmark {
  width: clamp(56px, 8vw, 84px); height: auto; margin: 0 auto 26px;
  transform-origin: 50% 50%;
}
.forge__weyebrow {
  font-family: var(--font-mono); font-size: 0.6875rem; font-weight: 500;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--cyan-400);
  margin-bottom: 16px;
}
.forge__wtitle { margin: 0; font-weight: 400; }
.forge__wname {
  display: block;
  font-family: var(--font-display); font-stretch: 125%; font-weight: 700;
  font-size: clamp(1.75rem, 4.4vw, 3.5rem); line-height: 1.02;
  letter-spacing: -0.025em; color: var(--text-hi); text-wrap: balance;
}
.forge__wrule {
  display: block; width: min(320px, 60vw); height: 1px; margin: 26px auto 0;
  background: linear-gradient(90deg, transparent, var(--cyan-400), transparent);
  transform: scaleX(0); transform-origin: 50% 50%;
}
.forge__wsub {
  display: block; margin-top: 22px;
  font-family: var(--font-mono); font-size: 0.75rem; font-weight: 400;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-mid);
  line-height: 1.7;
}
/* The rail and stage cards step aside once the brand moment takes over. */
.forge.is-welcome .forge__rail { opacity: 0; transition: opacity 400ms var(--ease); }

/* Closing line under the sequence. */
.forge__outro {
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 28px; z-index: 8; opacity: 0;
  transition: opacity 400ms var(--ease);
}
.forge__outro.is-on { opacity: 1; }
@media (max-width: 899px) { .forge__outro { display: none; } }

/* --------------------------------------------------------------------------
   STATIC / REDUCED-MOTION VARIANT
   Not a degraded version — a deliberate one. The finished pipe is rendered
   once, and the six stages become a readable technical list.
   -------------------------------------------------------------------------- */
.forge.forge--static { height: auto; }
.forge--static .forge__sticky { position: relative; height: auto; display: block; overflow: visible; }
.forge--static .forge__scene { height: 62svh; min-height: 420px; transform: none; opacity: 1; }
.forge--static .forge__welcome { position: static; transform: none; opacity: 1; padding-block: 0 clamp(32px,5vw,56px); }
.forge--static .forge__rail { display: none; }
.forge--static .forge__rail,
.forge--static .forge__sparks,
.forge--static .forge__coil,
.forge--static .forge__rolls,
.forge--static .forge__slit,
.forge--static .forge__head,
.forge--static .forge__cut,
.forge--static .forge__outro { display: none; }

.forge--static .forge__cards {
  position: static; transform: none; width: auto; pointer-events: auto;
  display: grid; gap: 1px;
  max-width: var(--max); margin: 0 auto; padding: 0 var(--gut) clamp(56px, 7vw, 96px);
}
@media (min-width: 760px) { .forge--static .forge__cards { grid-template-columns: repeat(2, 1fr); gap: 1px; } }
@media (min-width: 1080px) { .forge--static .forge__cards { grid-template-columns: repeat(3, 1fr); } }

.forge--static .forge__card {
  position: static; opacity: 1; transform: none; transition: none;
  padding: 28px 26px; background: var(--navy-900);
  outline: 1px solid rgba(113, 203, 227, 0.14);
}
.forge--static .forge__card-d { display: block; }

/* The no-JS path shows the same static list — core content never needs JS. */
.no-js .forge { height: auto; }
/* The no-JS header is static, so there is nothing overhead to reserve for. */
.no-js .forge__sticky { position: relative; height: auto; display: block; padding-top: 0; }
.no-js .forge__scene { display: none; }
.no-js .forge__welcome { position: static; transform: none; opacity: 1; padding: clamp(56px,8vw,104px) var(--gut) 0; }
.no-js .forge__cards { position: static; transform: none; width: auto; display: grid; gap: 1px; max-width: var(--max); margin: 0 auto; padding: clamp(56px,7vw,96px) var(--gut); }
@media (min-width: 760px) { .no-js .forge__cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .no-js .forge__cards { grid-template-columns: repeat(3, 1fr); } }
.no-js .forge__card { position: static; opacity: 1; transform: none; padding: 28px 26px; background: var(--navy-900); outline: 1px solid rgba(113,203,227,0.14); }
.no-js .forge__card-d { display: block; }
.no-js .forge__rail { display: none; }
/* The hairline's scaleX(0) is the first frame of the reveal, not a resting
   state. With no JS to draw it there is nothing to animate, so it rests drawn. */
.no-js .forge__wrule { transform: scaleX(1); }

/* --------------------------------------------------------------------------
   SCROLL CUE
   The one thing that tells a first-time visitor the page rewards scrolling.
   Sits below the opening composition and fades permanently on first input.
   -------------------------------------------------------------------------- */
.forge__cue {
  position: absolute; left: 50%; bottom: 26px; z-index: 8;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  pointer-events: none;
  transition: opacity 600ms var(--ease);
}
.forge__cue.is-gone { opacity: 0; }
.forge__cue-bar {
  position: relative; width: 1px; height: 40px;
  background: rgba(113, 203, 227, 0.16); overflow: hidden;
}
.forge__cue-bar::after {
  content: ''; position: absolute; left: 0; top: -100%;
  width: 1px; height: 100%;
  background: linear-gradient(to bottom, transparent, var(--cyan-400));
  animation: cueDraw 1900ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
@keyframes cueDraw { to { transform: translateY(200%); } }
.forge__cue-t {
  font-family: var(--font-mono); font-size: 0.625rem; font-weight: 500;
  letter-spacing: 0.22em; text-transform: uppercase; color: var(--text-low);
}
@media (max-width: 899px) {
  .forge__cue { bottom: 18px; }
  .forge__cue-bar { height: 30px; }
}
/* The opening caption has to be readable without scrolling, so it clears the
   cue rather than sitting on the bottom edge. */
@media (max-width: 899px) {
  .forge__cards { bottom: 112px; }
}
.forge--static .forge__cue, .no-js .forge__cue { display: none; }

/* --------------------------------------------------------------------------
   OPENING COMPOSITION
   The coil is part of the first frame now, so on desktop it has to clear the
   caption column instead of sitting under it.
   -------------------------------------------------------------------------- */
@media (min-width: 900px) {
  .forge__coil { left: clamp(180px, 31vw, 520px); }
}
/* On a phone the strip fills most of the frame, so the opening caption sits
   on a scrim rather than competing with polished steel behind it. Its own
   element with an explicit z-index between the scene and the cards — a
   negative-z pseudo-element inside the zero-height card wrapper was too
   fragile to reason about. */
.forge__scrim {
  position: absolute; left: 0; right: 0; bottom: 0; height: 46%;
  z-index: 7; pointer-events: none; display: none;
  background: linear-gradient(to top,
    rgba(1, 13, 34, 0.97) 22%, rgba(1, 13, 34, 0.88) 52%, transparent 100%);
}
@media (max-width: 899px) { .forge__scrim { display: block; } }
.forge--static .forge__scrim, .no-js .forge__scrim { display: none; }
