/* Chromatic System v2 — the engine is the page's only cool-dominant zone.
   Stage accents run amber → cyan → violet → magenta so the stage change is
   readable as a hue shift, not just a moving highlight. */
.process-engine {
  /* ONE accent, not four. The stage system ran amber -> cyan -> violet ->
     magenta so a stage change read as a hue shift; that is four decorative
     colours doing what an index number already says. Commerce gold, and only
     where it marks the live state. */
  --engine-accent: var(--store-gold, #e7a51a);
  /* The pinned run length, in CSS rather than JS.

     This section used to have NO reserved height until process-engine.js
     mounted and added `.is-native-scroll`, at which point min-height jumped
     from 1526px to 4733px — +3207px injected while the customer was already
     scrolling, shoving cosmic-collection, journey, philosophy, faq,
     first-batch and the footer down the page. Measured CLS 1.005 at 390x844
     (2026-08-20), and it was nondeterministic: whether you saw it depended on
     whether the dynamic import resolved before or after you reached it.

     The space is now reserved at parse time and updateNativeMetrics() READS
     the rendered geometry back instead of writing it. This multiplier is the
     only copy — there is no second number in JS to keep in sync.

     SWEPT 2026-09-09, 1440x900, 24 samples per viewport-height. The four
     stages were never the constraint -- SEAL holds through the landing hold
     as well, so its real dwell is the longest of the four at every value
     tested. What 4.2 bought was empty travel: measured stage dwell ran
     0.97 / 1.39 / 1.39 / 1.56 viewport-heights, and the section alone was
     32% of the document. At 3.0 it is 0.76 / 0.97 / 0.97 / 1.39 -- every
     stage still legible, 1080px and 1.20 screens off the page, and the
     Task 05 plateau rule still satisfied (worst dead interval 0.127vh
     against a 0.20vh limit, unchanged by the shortening). */
  --process-native-distance: max(2300px, 3.0 * 100svh);
  position: relative;
  z-index: 1;
  isolation: isolate;
  padding: 0;
  overflow: clip;
  background: var(--store-canvas, #070709);
}

/* Matches `compact` in process-engine.js exactly. If one moves, move both. */
@media (max-width: 760px), (pointer: coarse) {
  /* 2.8, not the 2.71 that would preserve the old 3.8/4.2 ratio. Composed
     for the viewport rather than scaled down from the desktop one: 2.8 puts
     compact SEAL dwell at 0.41vh against desktop 0.42vh, so the stage a
     phone reads fastest is the one stage that does not get shorter than its
     desktop counterpart. Measured 390x844: worst dead interval improves from
     0.166vh to 0.124vh. */
  .process-engine { --process-native-distance: max(2300px, 2.8 * 100svh); }
}

/* Gated on the same condition as setupScroll(), which returns early under
   reduced motion. Reserving the travel there would leave a ~3200px dead
   scroll region under a pin that never advances. */
@media (prefers-reduced-motion: no-preference) {
  .process-engine {
    /* `visible`, exactly as .is-native-scroll used to set it — overflow-y must
       not clip or the pin cannot stick, and the children (__intro and __pin)
       already clip themselves. */
    overflow: visible;
    min-height: calc(94svh + var(--process-native-distance) + 100svh);
  }

}

/* Stage accents collapsed to the single commerce gold above. */



/* `.is-native-scroll` is now a BEHAVIOUR flag only — it carries no geometry.
   The height reservation and the sticky pin moved to the base rules above so
   that mounting the engine cannot change layout. Deliberately left in the DOM
   because the JS still toggles it and it remains a useful state hook. */

.process-engine__intro {
  position: relative;
  z-index: 2;
  min-height: 94svh;
  padding-top: clamp(5rem, 9vw, 9rem);
  padding-bottom: clamp(5rem, 9vw, 9rem);
  overflow: hidden;
  background: var(--store-canvas, #070709);
}

.process-engine__intro::before {
  position: absolute;
  top: 50%;
  left: 63%;
  width: min(58rem, 62vw);
  aspect-ratio: 1.18;
  display: none;
  clip-path: polygon(47% 0, 83% 8%, 100% 37%, 88% 78%, 59% 100%, 17% 87%, 0 51%, 13% 16%);
  box-shadow: 0 0 0 5rem rgba(32, 93, 255, 0.018), 0 0 0 12rem rgba(255, 80, 191, 0.014);
  content: "";
  transform: translate(-50%, -50%) rotate(-18deg) scaleY(0.72);
}

.process-engine__intro::after {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.021) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.021) 1px, transparent 1px);
  background-size: 7rem 7rem;
  content: "";
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 84%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 84%, transparent);
}

.process-engine__intro-grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(18rem, 0.42fr);
  gap: clamp(2.5rem, 8vw, 10rem);
  align-items: end;
  padding-top: clamp(5rem, 11vw, 10rem);
}

.process-engine__intro-grid > div > p {
  margin: 0 0 1.5rem;
  color: var(--store-metadata, #8a8280);
  font-size: 0.64rem;
  letter-spacing: 0.24em;
}

.process-engine__intro-grid h2 {
  margin: 0;
  font-family: var(--font-ui);
  font-size: clamp(4.2rem, 8.25vw, 10.2rem);
  font-weight: 500;
  line-height: 0.77;
  letter-spacing: -0.07em;
}

.process-engine__intro-grid h2 em {
  color: var(--store-metadata, #8a8280);
  font-family: var(--font-display);
  font-weight: 400;
}

.process-engine__intro-grid > p {
  max-width: 28rem;
  margin: 0 0 0.8rem;
  color: rgba(255, 255, 255, 0.68);
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.1vw, 2.15rem);
  line-height: 1.32;
}

.process-engine__pin {
  /* Sticky in the BASE rule, not in a `.is-native-scroll` descendant selector.

     The travel space above is reserved by the stylesheet from first paint, so
     if the pin were not already sticky the section would render as a ~3200px
     empty well that the customer scrolls through. It has to be sticky at the
     same moment the space exists, which is parse time.

     Reduced motion turns it back to `relative` below — setupScroll() bails in
     that mode and the reservation is not made either, so the two agree. */
  position: sticky;
  top: 0;
  width: 100%;
  height: 100svh;
  min-height: 0;
  overflow: hidden;
  color: #f8f3ec;
  background: var(--store-canvas, #070709);
  isolation: isolate;
  transition: background-color 420ms ease;
}

.process-engine__canvas,
.process-engine__fallback,
.process-engine__shade {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.process-engine__canvas {
  z-index: 1;
  max-width: none;
  opacity: 0;
  transition: opacity 700ms cubic-bezier(0.23, 1, 0.32, 1);
}
.process-engine.is-webgl-ready .process-engine__canvas { opacity: 1; }

.process-engine__fallback {
  z-index: 0;
  background: var(--store-canvas, #070709);
}

.process-engine__shade {
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(90deg, rgba(7, 7, 9, 0.94), rgba(7, 7, 9, 0.54) 34%, transparent 54%, rgba(7, 7, 9, 0.12)),
    linear-gradient(180deg, rgba(7, 7, 9, 0.78), transparent 18%, transparent 75%, rgba(7, 7, 9, 0.92));
}

.process-engine__pack {
  position: absolute;
  z-index: 3;
  top: 50%;
  left: 62%;
  width: min(22rem, 27vw);
  max-height: 70svh;
  object-fit: contain;
  opacity: 0;
  pointer-events: none;
  /* The magenta bloom around the pouch is gone; the pack casts a shadow, not
     a coloured glow. */
  filter: drop-shadow(0 3rem 4rem rgba(0, 0, 0, 0.76)) drop-shadow(0 0 3.4rem rgba(0, 0, 0, 0.5));
  transform: translate3d(-50%, -48%, 0) scale(0.91) rotate(3deg);
  will-change: transform, opacity;
}

.process-engine__register {
  position: absolute;
  z-index: 5;
  top: clamp(5.7rem, 9svh, 7rem);
  right: var(--gutter);
  left: var(--gutter);
  display: flex;
  justify-content: space-between;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.16);
  color: rgba(255, 255, 255, 0.46);
  font-size: 0.53rem;
  letter-spacing: 0.2em;
}

.process-engine__readout {
  position: absolute;
  z-index: 5;
  /* Anchored BELOW the register rather than at a fixed 16% of the pin. At a
     720px viewport 16% resolved to 115px while the register's rule ends at
     ~121px, so the 4.1rem numeral sat on top of "SCROLL THROUGH THE FOUR
     STATES". Tracking the register's own clamp keeps them apart at every
     viewport height instead of only the one it was eyeballed at. */
  top: calc(clamp(5.7rem, 9svh, 7rem) + 3.4rem);
  right: var(--gutter);
  display: flex;
  gap: 0.85rem;
  align-items: center;
  min-width: 15rem;
  justify-content: flex-end;
  color: #fff;
  text-align: right;
}

.process-engine__readout > span {
  color: var(--engine-accent);
  font-family: var(--font-display);
  font-size: 4.1rem;
  line-height: 0.8;
  transition: color 360ms ease;
}

.process-engine__readout > div {
  display: grid;
  gap: 0.22rem;
  padding-left: 0.85rem;
  border-left: 1px solid rgba(255, 255, 255, 0.22);
}
.process-engine__readout strong { font-size: 0.69rem; font-weight: 500; letter-spacing: 0.2em; }
.process-engine__readout small { color: rgba(255, 255, 255, 0.46); font-size: 0.46rem; letter-spacing: 0.14em; }

.process-engine__copy {
  position: absolute;
  z-index: 5;
  top: 48%;
  left: var(--gutter);
  width: min(43rem, 42vw);
  min-height: 24rem;
  transform: translate3d(0, calc(-43% + var(--engine-drift, 0px)), 0);
}

.process-engine__copy article {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  filter: blur(6px);
  transform: translate3d(0, 1rem, 0) scale(0.985);
  /* OUT FAST, IN LATE. Both directions used to run 260ms from the same frame,
     so at the swap the outgoing and incoming step copy were each sitting near
     50% — two headlines competing for one slot. The outgoing now clears in
     170ms and the incoming waits 150ms before it starts, which leaves a short
     empty beat instead of an overlap. */
  transition: opacity 170ms ease, filter 260ms ease, transform 420ms cubic-bezier(0.23, 1, 0.32, 1);
}

.process-engine__copy article.is-active {
  opacity: 1;
  filter: blur(0);
  transform: translate3d(0, 0, 0) scale(1);
  transition: opacity 300ms ease 150ms, filter 420ms ease 150ms, transform 560ms cubic-bezier(0.23, 1, 0.32, 1) 150ms;
}

.process-engine__copy span {
  margin-bottom: 1.3rem;
  color: var(--engine-accent);
  font-size: 0.6rem;
  letter-spacing: 0.22em;
  transition: color 360ms ease;
}

.process-engine__copy h3 {
  margin: 0;
  font-family: var(--font-ui);
  font-size: clamp(3.8rem, 6.4vw, 8rem);
  font-weight: 500;
  line-height: 0.77;
  letter-spacing: -0.07em;
}

.process-engine__copy h3 em {
  color: var(--engine-accent);
  font-family: var(--font-display);
  font-weight: 400;
  transition: color 360ms ease;
}

/* MOBILE-ONLY SECONDARY LINE.

   Desktop keeps the composition it has: a two-line display headline with its
   italic second half, and the explanatory paragraph under it. There is
   horizontal room there for all of it beside the object.

   A phone has none. This line exists so the mobile state can drop BOTH the
   italic half-headline and the paragraph and still say what the step is. It
   is display:none above the breakpoint, so nothing about desktop changes. */
.process-engine__sub { display: none; }

.process-engine__copy p {
  max-width: 27rem;
  margin: 1.8rem 0 0;
  color: rgba(255, 255, 255, 0.64);
  font-size: clamp(0.86rem, 1vw, 1rem);
  line-height: 1.62;
}

.process-engine__telemetry {
  position: absolute;
  z-index: 5;
  right: var(--gutter);
  bottom: 23%;
  display: grid;
  width: min(21rem, 25vw);
  gap: 0.7rem;
}

.process-engine__telemetry > div {
  display: grid;
  grid-template-columns: 4.6rem 1fr;
  gap: 0.32rem 0.8rem;
  align-items: center;
  padding-bottom: 0.55rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}

.process-engine__telemetry span { color: rgba(255, 255, 255, 0.42); font-size: 0.46rem; letter-spacing: 0.17em; }
.process-engine__telemetry strong { font-family: var(--font-display); font-size: 1rem; font-weight: 400; text-align: right; font-variant-numeric: tabular-nums; }
.process-engine__telemetry i { grid-column: 1 / -1; height: 1px; overflow: hidden; background: rgba(255, 255, 255, 0.13); }
.process-engine__telemetry b {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--engine-accent);
  box-shadow: 0 0 0.8rem var(--engine-accent);
  transform-origin: left;
  transition: background-color 360ms ease;
  will-change: transform;
}

.process-engine__stages {
  position: absolute;
  z-index: 6;
  right: var(--gutter);
  bottom: 10.5%;
  left: var(--gutter);
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
}

.process-engine__stages::before {
  position: absolute;
  top: 0.54rem;
  right: 0;
  left: 0;
  height: 1px;
  background: rgba(255, 255, 255, 0.18);
  content: "";
}

.process-engine__stages button {
  position: relative;
  display: grid;
  width: 100%;
  grid-template-columns: 1rem auto;
  gap: 0.55rem 0.65rem;
  align-items: center;
  padding: 0 0.35rem;
  border: 0;
  color: rgba(255, 255, 255, 0.42);
  text-align: left;
  background: transparent;
  cursor: pointer;
  transition: color 180ms ease, transform 120ms cubic-bezier(0.23, 1, 0.32, 1);
}

.process-engine__stages button i {
  position: relative;
  z-index: 1;
  width: 1.05rem;
  aspect-ratio: 1;
  border: 1px solid rgba(255, 255, 255, 0.38);
  background: var(--store-surface, #0d0d11);
  clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%);
  box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
  transition: border-color 180ms ease, background-color 180ms ease, box-shadow 240ms ease, transform 240ms cubic-bezier(0.23, 1, 0.32, 1);
}

.process-engine__stages button span { grid-column: 2; color: rgba(255, 255, 255, 0.38); font-size: 0.45rem; letter-spacing: 0.16em; }
.process-engine__stages button strong { grid-column: 2; font-family: var(--font-display); font-size: 1.08rem; font-weight: 400; }
.process-engine__stages button[aria-pressed="true"] { color: #fff; }
.process-engine__stages button[aria-pressed="true"] i { border-color: var(--engine-accent); background: var(--engine-accent); box-shadow: 0 0 1.6rem var(--engine-accent); transform: rotate(45deg) scale(1.16); }
.process-engine__stages button[aria-pressed="true"] span { color: var(--engine-accent); }
.process-engine__stages button:active { transform: scale(0.97); }
.process-engine__stages button:focus-visible { outline: 1px solid color-mix(in srgb, var(--engine-accent) 68%, transparent); outline-offset: 0.35rem; }

.process-engine__rail {
  position: absolute;
  z-index: 6;
  right: var(--gutter);
  bottom: 4.8%;
  left: var(--gutter);
  height: 2px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.12);
}

.process-engine__rail i {
  display: block;
  width: 100%;
  height: 100%;
  background: var(--store-gold, #e7a51a);
  box-shadow: 0 0 1.2rem rgba(168,64,255,.9);
  transform: scaleX(0);
  transform-origin: left;
  will-change: transform;
}

.process-engine__instruction {
  position: absolute;
  z-index: 6;
  right: var(--gutter);
  bottom: 1.5%;
  left: var(--gutter);
  display: flex;
  justify-content: space-between;
  margin: 0;
  color: rgba(255, 255, 255, 0.4);
  font-size: 0.48rem;
  letter-spacing: 0.18em;
}
.process-engine__instruction b { color: var(--engine-accent); font-weight: 500; transition: color 360ms ease; }

@media (hover: hover) and (pointer: fine) {
  .process-engine__stages button:hover { color: #fff; }
  .process-engine__stages button:hover i { border-color: rgba(255, 255, 255, 0.84); transform: scale(1.08); }
}

@media (max-width: 900px) {
  .process-engine__intro { min-height: auto; }
  .process-engine__intro-grid { grid-template-columns: 1fr; gap: 2rem; }
  .process-engine__intro-grid > p { max-width: 37rem; }
  .process-engine__copy { top: 17%; width: calc(100% - var(--gutter) * 2); min-height: 18rem; transform: translate3d(0, var(--engine-drift, 0px), 0); }
  .process-engine__copy article { justify-content: flex-start; }
  .process-engine__copy h3 { max-width: 36rem; font-size: clamp(3.7rem, 10vw, 6rem); }
  .process-engine__copy p { max-width: 24rem; margin-top: 1.25rem; }
  .process-engine__readout { top: auto; right: var(--gutter); bottom: 30%; }
  .process-engine__telemetry { right: var(--gutter); bottom: 20%; width: min(18rem, 42vw); }
  .process-engine__shade { background: linear-gradient(180deg, rgba(2, 1, 6, 0.9), rgba(2, 1, 6, 0.42) 34%, transparent 57%, rgba(2, 1, 6, 0.9)); }
  .process-engine__pack { top: 57%; left: 53%; width: min(18rem, 45vw); max-height: 47svh; }
}

@media (max-width: 760px) {
  .process-engine__intro { padding-top: 4rem; padding-bottom: 4rem; }
  .process-engine__intro::before { left: 72%; width: 130vw; }
  .process-engine__intro-grid { padding-top: 4rem; }
  .process-engine__intro-grid h2 { font-size: clamp(3.25rem, 15.4vw, 5rem); }
  .process-engine__intro-grid > p { font-size: 1.1rem; }
  .process-engine__pin { min-height: 0; }
  .process-engine__register { top: 5.5rem; }
  .process-engine__register span:last-child { display: none; }
  /* ------------------------------------------------------------------
     OBJECT FIRST, INSTRUMENTATION SECOND, COPY THIRD.

     The headline was clamp(3rem, 14.4vw, 4.7rem) — 56px at 390 — over two
     lines at 0.77 leading, with a 4-line paragraph under it. Together they
     occupied roughly 280px of an 844px viewport and sat directly on top of
     the mango, the freeze geometry, the dry pieces and the pouch in turn.
     Four posters layered over an animation.

     The copy is now a compact header band at the top of the frame and
     nothing else. Everything below it belongs to the object.
     ------------------------------------------------------------------ */
  /* ------------------------------------------------------------------
     MOBILE COPY — REDUCED, NOT STRIPPED.

     Two settings were wrong in opposite directions. The original was
     clamp(3rem, 14.4vw, 4.7rem) — 56px at 390, two display lines at 0.77
     leading with a four-line paragraph — which sat bodily on top of the
     mango, the freeze geometry, the pieces and the pouch in turn. The
     correction went to 41px and deleted the paragraph outright, which left
     the sequence reading as a bare technical demo with no narrative at all.

     This is the middle. The full four-part hierarchy is intact — overline,
     primary, italic secondary, supporting paragraph — at roughly 47px at 390
     rather than 56, so the object keeps a clear field without the section
     losing its voice.
     ------------------------------------------------------------------ */
  /* ==================================================================
     THREE PROTECTED ZONES.

     The mobile sequence had no spatial contract: the copy block, the WebGL
     stage and the instrument panel were each positioned independently and
     simply overlapped. Measured at 390x844 on Step 04, the pouch spanned
     38%-77% of the pinned viewport and ran straight through the readout at
     66% and the CORE / FIELD / RESULT row at 72%.

       ZONE A  10-24%   register, overline, headline, italic secondary
       ZONE B  30-64%   the object. Nothing else is positioned into it.
       ZONE C  67-91%   readout, telemetry, progress rail — one panel
                        commerce rail sits below, untouched

     Everything below is expressed against those bands, so the zones can be
     read off the stylesheet rather than inferred from six scattered offsets.
     ================================================================== */

  /* --- ZONE A ------------------------------------------------------- */
  .process-engine__copy { top: 14.5%; min-height: 0; width: min(30rem, 90vw); transform: translate3d(0, var(--engine-drift, 0px), 0); }
  .process-engine__copy span { margin-bottom: 0.5rem; font-size: 0.48rem; }

  .process-engine__copy h3 { width: 100%; font-size: clamp(2.35rem, 10.2vw, 2.9rem); line-height: 0.9; letter-spacing: -0.045em; }

  /* The italic half moves OUT of the headline on mobile and becomes the
     secondary line below it, at a third of the size. Same words, same order,
     one display line instead of two. */
  .process-engine__copy h3 br,
  .process-engine__copy h3 em { display: none; }

  .process-engine__copy p.process-engine__sub {
    display: block;
    width: 100%;
    max-width: none;
    /* More air above it than the old 0.45rem: the secondary has to read as a
       deliberate second beat, not as a wrapped third line of the headline. */
    margin: 0.7rem 0 0;
    color: var(--store-secondary, #b8b0a3);
    font-family: var(--font-display, Georgia, serif);
    font-size: clamp(1.3rem, 4.4vw, 1.65rem);
    font-style: italic;
    line-height: 1.08;
    letter-spacing: -0.01em;
  }

  /* HIDDEN, NOT DELETED. The four paragraphs stay in the markup and stay
     visible on desktop; inside the pinned mobile sequence they are the one
     thing that cannot fit without crossing Zone B. On a phone the animation
     and the telemetry carry the explanation. */
  .process-engine__copy p:not(.process-engine__sub) { display: none; }
  /* --- ZONE C: one instrument panel ---------------------------------
     The readout used to float at bottom 30%, mid-stage, where the object
     lives — a second hero element rather than a gauge. It now sits
     directly on top of the telemetry row so the numeral, the state, CORE,
     FIELD, RESULT and the progress rail read as one block. */
  .process-engine__readout { bottom: 29%; gap: 0.55rem; min-width: auto; }
  /* Instrument, not headline. */
  .process-engine__readout > span { font-size: 1.9rem; }
  .process-engine__readout strong { font-size: 0.56rem; }
  .process-engine__readout small { font-size: 0.4rem; }
  .process-engine__telemetry { right: var(--gutter); bottom: 21%; left: var(--gutter); width: auto; grid-template-columns: repeat(3, 1fr); gap: 0.7rem; }
  .process-engine__telemetry > div { display: grid; grid-template-columns: 1fr; gap: 0.25rem; padding: 0; border: 0; align-content: space-between; }
  .process-engine__telemetry span { font-size: 0.38rem; }
  .process-engine__telemetry strong { font-size: 0.8rem; text-align: left; }
  .process-engine__telemetry i { grid-column: auto; }
  .process-engine__stages { bottom: 9%; }
  .process-engine__stages button { min-height: 44px; grid-template-columns: 0.8rem 1fr; gap: 0.35rem; padding: 0.35rem 0.1rem; }
  .process-engine__stages button i { width: 0.78rem; }
  .process-engine__stages button span { display: none; }
  .process-engine__stages button strong { font-size: 0.7rem; }
  .process-engine__stages::before { top: 50%; }
  .process-engine__instruction { bottom: 1.6%; }
  .process-engine__instruction span { display: none; }
  /* --- ZONE B: sacred object space ----------------------------------
     The pack carries an inline transform from the engine —
     translate3d(-50%, -48%, 0) — so its painted box is
     top - 0.48h .. top + 0.52h. At top:57% / 39svh that resolved to
     38%-77% and sat across the whole instrument panel.

     46% / 34svh puts it at roughly 30%-64%: centred in Zone B and
     finishing about 30px clear of the readout. Position and size only —
     the transform, the scale and the timing are the engine's and are
     untouched. */
  .process-engine__pack { top: 46%; left: 50%; width: min(12.5rem, 47vw); max-height: 34svh; }
}

@media (max-width: 900px) and (max-height: 700px) {
  .process-engine__register { top: 4.6rem; padding-bottom: 0.55rem; }
  /* SHORT PHONES. This block sits after the mobile one and was still setting
     the old headline scale — clamp(2.75rem, 8.2vw, 4rem), i.e. 44px at 360,
     quietly overriding the reduction above it. Same scale as the mobile
     block now, one step tighter for the shorter frame. */
  /* Short phones: the same hierarchy, one step tighter. This block sits after
     the mobile one and will silently shadow it, so it has to carry the whole
     set rather than a partial override. */
  /* Short phones inherit the same three zones, compressed. This block sits
     after the mobile one and shadows it, so it restates every value it
     needs rather than half-overriding. */
  .process-engine__copy { top: 12.5%; min-height: 0; }
  .process-engine__copy span { margin-bottom: 0.45rem; }
  .process-engine__copy h3 { max-width: none; font-size: clamp(2.35rem, 9.6vw, 2.65rem); }
  .process-engine__copy p.process-engine__sub { margin-top: 0.55rem; font-size: clamp(1.3rem, 4.2vw, 1.5rem); }
  /* Hidden here too — this query also catches small landscape tablets. */
  .process-engine__copy p:not(.process-engine__sub) { display: none; }
  .process-engine__readout { bottom: 27%; }
  .process-engine__readout > span { font-size: 1.8rem; }
  .process-engine__telemetry { bottom: 17%; }
  .process-engine__stages { bottom: 8.5%; }
  .process-engine__rail { bottom: 3.7%; }
  .process-engine__instruction { bottom: 0.9%; }
  .process-engine__pack { top: 44%; max-height: 33svh; }
}

@media (prefers-reduced-motion: reduce) {
  .process-engine__copy article { filter: none; transform: none; transition: opacity 180ms ease; }
  .process-engine__canvas { transition: opacity 180ms ease; }
}

/* NEUTRAL ZONE.

   This block was "the abyss zone — cold blue floor, hot accents on top", and
   it is what was actually rendering: it sits at the end of the file and
   overrode every base rule above it. Magenta at 38%, lime at 26%, amber at
   34%, a cyan-bordered polygon and a five-stop rainbow rail — the tech-poster
   layer, at full strength.

   All of it is gone. The section now runs on the same canvas as the commerce
   stack above it, and the only accent left is the single commerce gold on the
   live state. The one texture kept is the 7rem drafting grid on
   .process-engine__intro::after at 2% white, which is the "quiet technical"
   layer the brief allows — it is invisible until you look for it. */
.process-engine { background: var(--store-canvas, #070709); }
.process-engine__intro { background: var(--store-canvas, #070709); }
.process-engine__intro::before { display: none; }
.process-engine__intro-grid > div > p { color: var(--store-metadata, #8a8280); }
.process-engine__intro-grid h2 em { color: var(--store-gold, #e7a51a); }
.process-engine__intro-grid > p { color: var(--store-secondary, #b8b0a3); }
.process-engine__pin { background: var(--store-canvas, #070709); }
.process-engine__fallback { background: var(--store-canvas, #070709); }
.process-engine__shade {
  background:
    linear-gradient(90deg,rgba(7,7,9,.93),rgba(7,7,9,.55) 34%,transparent 56%,rgba(7,7,9,.14)),
    linear-gradient(180deg,rgba(7,7,9,.68),transparent 21%,transparent 72%,rgba(7,7,9,.9));
}
.process-engine__rail i {
  background: var(--store-gold, #e7a51a);
  box-shadow: none;
}

/* ==================================================================
   SCROLL-LINKED COPY — the .is-native-scroll path only.

   The four step blocks used to cross-fade on a CSS transition fired by a
   class toggle: 170ms out, a 150ms hold-off, 300ms in. That is a clock
   with no relationship to the scroll position driving the object beneath
   it, so the text cut between four slides while the fruit flowed. The
   engine now writes opacity and transform per scroll event instead, which
   also makes the sequence exactly reversible — scrolling back up is the
   same function evaluated at a smaller number, not a forward transition
   played backwards.

   The blur goes with it, deliberately. filter: blur(6px) animated per
   scroll event is a full-size repaint on every event — the single most
   expensive thing this section did on a phone — and it existed to soften a
   crossfade that no longer happens in one plane.

   Reduced motion needs no exception here: setupScroll() returns before
   adding .is-native-scroll, so none of this applies and the class-driven
   cross-fade above remains the entire behaviour.
   ================================================================== */
.process-engine.is-native-scroll .process-engine__copy article {
  filter: none;
  transition: none;
  will-change: transform, opacity;
}

/* THE RUN, DRAWN THROUGH THE MARKERS.

   The stage row already had a static hairline joining the four states.
   This is the same line filled to the live position, so the steps read as
   one track being traversed rather than four buttons standing in a row —
   the cheapest available cue that the stages are one continuous process.
   Geometry is copied from ::before exactly; the markers keep their own
   z-index and stay above it. */
.process-engine__stages::after {
  position: absolute;
  top: 0.54rem;
  right: 0;
  left: 0;
  height: 1px;
  background: var(--engine-accent);
  opacity: 0.62;
  content: "";
  transform: scaleX(var(--engine-run, 0));
  transform-origin: left;
  will-change: transform;
}

/* Matches the ::before offset in the mobile block above. */
@media (max-width: 760px) {
  .process-engine__stages::after { top: 50%; }
}

/* Reduced motion: no reserved travel (see the base rule), so nothing to stick
   to — the pin is just the last block in the section. Last in the file so it
   wins over the base rule at equal specificity. */
@media (prefers-reduced-motion: reduce) {
  .process-engine__pin { position: relative; top: auto; }
}

/* ============================================================================
   IN SOFT. OUT CRUNCHY.

   The engine's closing beat, written as what the process CHANGES. It sits AFTER
   the pinned stage, in normal flow, and is still not a chapter: no register, no
   scroll length of its own.

   The site's own grammar, not a new one. The statement is the house two-line
   display -- sans caps, then serif italic in gold -- at the Gateway's scale, not
   a poster word: a 200px single word was tried here and read as a different
   site. The proof is a before -> after ledger, the Gateway's fresh -> freeze-
   dried idea restated as texture, flavour, moisture and time: dim serif in, a
   hairline that warms to gold, bright serif out. Ruled rows and small-caps
   labels keep it in the telemetry language of the engine above. No cards, no
   icons, no benefit grid.

   Two columns from 861px so the block is a beat, not a section; stacked below.
   Claim sources are recorded beside the markup in index.html.
   ========================================================================== */
.process-result {
  display: grid;
  gap: clamp(2.2rem, 6vw, 3.2rem);
  margin: 0;
  padding: clamp(3.4rem, 8vw, 6.2rem) var(--gutter) clamp(3.6rem, 8.5vw, 6.6rem);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
@media (min-width: 861px) {
  .process-result {
    grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr);
    column-gap: clamp(3rem, 6vw, 6.5rem);
    align-items: center;
  }
}
.process-result__eyebrow {
  margin: 0;
  color: var(--store-gold, #e7a51a);
  font-family: var(--font-ui);
  font-size: clamp(0.56rem, 0.9vw, 0.66rem);
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.process-result__title {
  margin: clamp(0.8rem, 1.8vw, 1.2rem) 0 0;
  color: #fdf3e2;
  font-family: var(--font-ui);
  font-size: clamp(2.6rem, 5.4vw, 5.8rem);
  font-weight: 500;
  line-height: 0.9;
  letter-spacing: -0.055em;
  text-transform: uppercase;
}
.process-result__title em {
  display: block;
  color: var(--store-gold, #e7a51a);
  font-family: var(--font-display);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.035em;
}
.process-result__lede {
  max-width: 40ch;
  margin: clamp(1.2rem, 2.6vw, 1.8rem) 0 0;
  color: rgba(255, 255, 255, 0.66);
  font-family: var(--font-ui);
  font-size: clamp(0.86rem, 1.2vw, 1rem);
  line-height: 1.55;
}
.process-result__lede sup,
.process-result__out sup { color: var(--store-gold, #e7a51a); font-size: 0.55em; }

/* THE LEDGER. Label | in -- axis -- out. The column heads sit on the same grid
   as the rows so IN and OUT line up over the values they name. */
.process-result__ledger { width: 100%; }
.process-result__ledger dl { margin: 0; }
.process-result__cols,
.process-result__row {
  display: grid;
  /* Fixed "in" and "out" columns with the axis taking the slack. With "in" as 1fr
     the axis began at the far edge of a wide column, leaving a dead gap between
     "Soft" and its line; now the line runs from word to word, and every "out"
     value keeps one left edge. 9rem holds "Mostly water", 11rem "More intense". */
  grid-template-columns: minmax(5.2rem, 0.24fr) minmax(0, 9rem) minmax(2.4rem, 1fr) minmax(0, 11rem);
  column-gap: clamp(0.8rem, 1.6vw, 1.3rem);
  align-items: center;
}
.process-result__cols {
  margin: 0 0 0.7rem;
  color: rgba(255, 255, 255, 0.4);
  font-family: var(--font-ui);
  font-size: 0.52rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
}
.process-result__cols span:last-child { color: var(--store-gold, #e7a51a); }
/* IN heads a right-aligned column, so it is right-aligned too: left-aligned it
   sat ~140px short of the words it names. */
.process-result__cols span:nth-child(2) { text-align: right; }
.process-result__row {
  padding: clamp(0.85rem, 1.6vw, 1.1rem) 0;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.process-result__row:last-of-type { border-bottom: 1px solid rgba(255, 255, 255, 0.12); }
.process-result__row dt {
  color: rgba(255, 255, 255, 0.5);
  font-family: var(--font-ui);
  font-size: clamp(0.56rem, 0.95vw, 0.66rem);
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* The dd's children join the row's grid, so every "in", axis and "out" shares
   one set of column lines down the ledger. */
.process-result__row dd { display: contents; }
.process-result__in,
.process-result__out {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 1.1;
  font-variant-numeric: lining-nums tabular-nums;
}
.process-result__in {
  color: rgba(253, 243, 226, 0.42);
  font-size: clamp(0.98rem, 1.7vw, 1.3rem);
  /* Set against the axis, not the label. Left-aligned in a column sized for
     "Mostly water", a short word such as "Soft" sat ~100px short of its line;
     right-aligned, every before-word meets its axis at the same distance and
     each row reads as one gesture: before, line, after. */
  text-align: right;
}
.process-result__out {
  color: #fdf3e2;
  font-size: clamp(1.12rem, 2.1vw, 1.7rem);
}
.process-result__axis {
  position: relative;
  display: block;
  height: 1px;
  background: linear-gradient(90deg, rgba(253, 243, 226, 0.12), var(--store-gold, #e7a51a));
}
.process-result__axis::after {
  position: absolute;
  top: 50%;
  right: -2px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--store-gold, #e7a51a);
  box-shadow: 0 0 0.6rem color-mix(in srgb, var(--store-gold, #e7a51a) 60%, transparent);
  content: "";
  transform: translateY(-50%);
}
/* Read aloud as "Texture: Soft to Crunchy"; the axis carries it visually. */
.process-result__to {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.process-result__note {
  margin: 0.9rem 0 0;
  max-width: 60ch;
  color: rgba(255, 255, 255, 0.56);
  font-family: var(--font-ui);
  font-size: clamp(0.6rem, 0.95vw, 0.68rem);
  line-height: 1.55;
}
.process-result__note + .process-result__note { margin-top: 0.35rem; }
.process-result__note span { color: var(--store-gold, #e7a51a); margin-right: 0.15em; }

/* Phones: the label rides above its pair, and the column heads are dropped --
   a dim word, a warming line and a bright word already say before and after. */
@media (max-width: 760px) {
  .process-result__cols { display: none; }
  .process-result__row {
    /* A fixed "in" column, not auto. Each row is its own grid, so auto sized the
       column to that row's own word and the axis and "out" value started at a
       different x after "Soft" than after "Mostly water": a ragged ledger. */
    grid-template-columns: minmax(0, 7.4rem) clamp(2rem, 9vw, 3.2rem) minmax(0, 1fr);
    grid-template-areas: "label label label" "in axis out";
    row-gap: 0.45rem;
    justify-content: start;
  }
  .process-result__row dt { grid-area: label; }
  .process-result__in { grid-area: in; }
  .process-result__axis { grid-area: axis; }
  .process-result__out { grid-area: out; }
}
