/* ==========================================================================
   How we work (after kota.co.uk's framework)
   A title, a row of pills for the five steps and one card per step: its
   motion scene on the left (process-scenes.css), its name and words on the
   right. The rail layout (.is-rail, process.js)
   holds the stage (sticky) while the page's scroll moves the cards sideways,
   one step at a time, then lets go and the page carries on down. The ink
   pill slides and stretches from step to step with the scroll. Without the
   script, with reduced motion, or on a screen too short for the rail, the
   cards are a plain column.
   ========================================================================== */

.process {
  --vh: 100svh;
  --tab-h: 44px;
  position: relative;
  z-index: 2; /* over the next section, so the cards' shadow fades out on it */
  background: var(--bone);
}

@supports not (height: 100svh) {
  .process {
    --vh: 100vh;
  }
}

/* Paper grain, as on the rest of the page. */
.process::before {
  content: "";
  position: absolute;
  inset: 0;
  background: url("../assets/textures/grain.webp") repeat;
  background-size: 160px 160px;
  opacity: 0.55;
  pointer-events: none;
}

.process__stage {
  position: relative;
  padding: clamp(88px, 14vh, 160px) 0 clamp(88px, 14vh, 160px);
}

.process__stage > * {
  position: relative;
}

/* ------------------------------------------------------------------ head */

.process__head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: start;
  gap: 16px;
  padding: 0 var(--gutter);
}

.process__label {
  grid-column: 1;
  padding-top: 0.6em;
  color: var(--text-mute);
}

.process__index {
  grid-column: 3;
  justify-self: end;
  padding-top: 0.6em;
  color: var(--text-mute);
}

.process__title {
  grid-column: 2;
  font-size: clamp(1.75rem, min(8.2vw, 10.2vh), 7rem);
  font-stretch: var(--wdth-display);
  font-weight: 500;
  line-height: 0.94;
  letter-spacing: -0.012em;
  text-align: center;
  text-transform: uppercase;
  white-space: nowrap;
  font-synthesis: none;
}

/* Each word rises out of its own mask (process.js arms it, then plays it in view). */
.process__mask {
  display: inline-block;
  overflow: clip;
  padding: 0.08em 0.03em 0.06em;
  margin: -0.08em -0.03em -0.06em;
  vertical-align: top;
}

.process__mask > span {
  display: inline-block;
}

.process__count {
  display: inline-block;
  margin: 0.9em 0 0 0.7em;
  vertical-align: top;
  color: var(--text-mute);
}

/* ------------------------------------------------------------------ pills */

.process__nav {
  display: flex;
  margin-top: clamp(14px, 2.4vh, 26px);
  padding: 0 var(--gutter);
  overflow-x: auto;
  scrollbar-width: none;
}

.process__nav::-webkit-scrollbar {
  display: none;
}

.process__tabs {
  position: relative;
  display: flex;
  gap: 8px;
  margin: 0 auto;
}

.process__tab,
.process__ink > span {
  display: inline-flex;
  flex: none;
  align-items: center;
  height: var(--tab-h);
  padding: 0 clamp(16px, 1.25vw, 22px);
  border-radius: 999px;
  font-size: clamp(0.8125rem, 0.72rem + 0.3vw, 0.9375rem);
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
}

.process__tab {
  color: var(--ink);
  background: rgb(255 255 255 / 0.92);
  box-shadow: inset 0 0 0 1px rgb(17 17 17 / 0.06);
  transition:
    background-color 300ms ease,
    scale 240ms var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) and (pointer: fine) {
  .process__tab:hover {
    background: #fff;
  }
}

.process__tab:active {
  scale: 0.96;
}

.process__tab:focus-visible {
  outline-offset: 3px;
  border-radius: 999px;
}

/* The ink pill: a white-on-ink copy of the row, cut to the active step by a
   rounded clip (process.js), so the pill slides and stretches between steps
   and the words invert exactly at its edges. */
.process__ink {
  position: absolute;
  inset: 0;
  display: flex;
  gap: 8px;
  color: #fff;
  background: var(--ink);
  border-radius: 999px;
  clip-path: inset(0 calc(100% - var(--ink-r, 0px)) 0 var(--ink-l, 0px) round 999px);
  pointer-events: none;
}

/* ------------------------------------------------------------------ cards */

.process__rail {
  margin-top: clamp(20px, 3vh, 32px);
  padding: 0 var(--gutter);
}

.process__track {
  display: grid;
  gap: clamp(16px, 2vw, 28px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.pstep__card {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 52fr) minmax(0, 48fr);
  min-height: clamp(440px, 64vh, 640px);
  border-radius: 18px clamp(56px, 6vw, 118px) 18px 18px;
  overflow: hidden;
  isolation: isolate;
  background: rgb(255 255 255 / 0.82);
  box-shadow:
    inset 0 0 0 1px rgb(17 17 17 / 0.05),
    var(--shadow-lift);
}

/* The picture. Its art is wider than the box, so it can drift (parallax)
   without showing an edge. The number shows until the scene is built. */
.pstep__media {
  position: relative;
  overflow: hidden;
  background: var(--media, #1b4dff);
}

.pstep:nth-child(2) .pstep__media,
.pstep:nth-child(4) .pstep__media {
  --media: #111111;
}

.pstep:nth-child(3) .pstep__media {
  --media: #ece8e1;
}

.pstep__art {
  position: absolute;
  inset: 0 -22%;
}

.pstep__num {
  position: absolute;
  left: 50%;
  top: 50%;
  font-size: clamp(5rem, 12vw, 12rem);
  font-stretch: var(--wdth-display);
  font-weight: 500;
  line-height: 1;
  color: rgb(255 255 255 / 0.9);
  transform: translate(-50%, -50%);
}

.pstep:nth-child(3) .pstep__num {
  color: var(--ink);
}

.pstep__media.has-scene .pstep__num {
  display: none;
}

.pstep__body {
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-content: start;
  gap: clamp(16px, 2.2vh, 28px);
  min-width: 0;
  padding: clamp(24px, 2.6vw, 48px) clamp(24px, 2.8vw, 52px) clamp(24px, 2.6vw, 44px);
}

.pstep__title {
  font-size: clamp(2.125rem, min(3.6vw, 6.4vh), 4.5rem);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.04em;
}

.pstep__mask {
  display: inline-block;
  overflow: clip;
  padding: 0.08em 0.04em 0.1em;
  margin: -0.08em -0.04em -0.1em;
  vertical-align: top;
}

.pstep__mask > span {
  display: inline-block;
}

.pstep__n {
  display: inline-block;
  margin: 0.35em 0 0 0.6em;
  vertical-align: top;
  color: var(--text-mute);
}

/* The services the scene cycles through, in step with it; the one showing
   is ink, with its time running out along its foot. */
.pstep__for {
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  align-items: center;
  gap: 6px;
}

.pstep__for-label {
  flex-basis: 100%;
  margin-bottom: 4px;
  color: var(--text-mute);
}

.pchip {
  position: relative;
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 12px;
  border-radius: 999px;
  overflow: hidden;
  color: rgb(17 17 17 / 0.62);
  background: rgb(255 255 255 / 0.55);
  box-shadow: inset 0 0 0 1px rgb(17 17 17 / 0.08);
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
  transition:
    color 300ms ease,
    background-color 300ms ease,
    box-shadow 300ms ease;
  -webkit-tap-highlight-color: transparent;
}

@media (hover: hover) and (pointer: fine) {
  .pchip:hover {
    color: var(--ink);
    background: #fff;
  }
}

.pchip.is-on {
  color: #fff;
  background: var(--ink);
  box-shadow: none;
}

.pchip::after {
  content: "";
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: 5px;
  height: 1.5px;
  border-radius: 2px;
  background: rgb(255 255 255 / 0.7);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

.pchip.is-on::after {
  animation: pchip-beat var(--beat, 5s) linear forwards;
}

@keyframes pchip-beat {
  to {
    transform: scaleX(1);
  }
}

.pstep__text {
  max-width: 35ch;
  font-size: clamp(1rem, 0.88rem + 0.42vw, 1.375rem);
  line-height: 1.38;
  letter-spacing: -0.012em;
  text-wrap: pretty;
}

/* Washes a card out as it leaves the middle (process.js sets its opacity). */
.pstep__veil {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--bone);
  opacity: 0;
  pointer-events: none;
}

/* ------------------------------------------------------------------ list layout (default) */

.process:not(.is-rail) .process__nav {
  display: none;
}

@media (max-width: 769px) {
  .process:not(.is-rail) .pstep__card {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
    border-radius: 16px 56px 16px 16px;
  }

  .process:not(.is-rail) .pstep__media {
    aspect-ratio: 1 / 0.86;
  }

  /* The desktop's three parts, kept: the label and index share a row (as
     the services' head does), the title centred under them. */
  .process__head {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "label index"
      "title title";
    align-items: baseline;
    gap: clamp(16px, 2.6vh, 24px) 16px;
  }

  .process__label {
    grid-area: label;
    padding-top: 0;
  }

  .process__index {
    grid-area: index;
    padding-top: 0;
  }

  .process__title {
    grid-area: title;
    justify-self: center;
  }
}

/* ------------------------------------------------------------------ rail layout */

.process.is-rail .process__pin {
  height: calc(var(--vh) + var(--travel, 420vh));
}

.process.is-rail .process__stage {
  position: sticky;
  top: 0;
  display: grid;
  grid-template-rows: auto auto minmax(0, 1fr);
  grid-template-columns: minmax(0, 1fr);
  height: var(--vh);
  padding: calc(var(--header-compact) + clamp(8px, 2.2vh, 28px)) 0 clamp(14px, 3.2vh, 36px);
  /* Clipped sideways only (the rail's travel): a clip at the foot cut the
     cards' shadow off in a hard line as the stage scrolled away. */
  overflow: hidden;
  overflow: clip visible;
}

.process.is-rail .process__rail {
  container: rail / size;
  min-height: 0;
  margin-top: clamp(14px, 2.8vh, 32px);
  padding: 0;
}

.process.is-rail .process__track {
  --card-w: min(78cqw, 1560px);
  --card-h: min(100cqh, calc(var(--card-w) / 1.3));
  --rail-gap: 9cqw; /* wide enough that no neighbour shows at rest */
  display: flex;
  align-items: center;
  gap: var(--rail-gap);
  height: 100%;
  padding-left: calc(50cqw - var(--card-w) / 2);
  will-change: transform;
}

.process.is-rail .pstep {
  flex: none;
  width: var(--card-w);
  height: var(--card-h);
}

.process.is-rail .pstep__card {
  height: 100%;
  min-height: 0;
  transform-origin: 50% 50%;
}

/* Narrow rails (phones, portrait tablets): the picture above the words. */
@container rail (max-width: 769px) {
  .process.is-rail .process__track {
    --card-w: 88cqw;
    --card-h: 100cqh;
    --rail-gap: 9cqw;
  }

  /* The card is as tall as its picture (the scene's shape) and words, up to
     the rail's height; the picture gives way first. */
  .process.is-rail .pstep {
    height: auto;
    max-height: 100%;
  }

  .process.is-rail .pstep__card {
    display: flex;
    flex-direction: column;
    height: auto;
    max-height: 100cqh;
    border-radius: 16px 52px 16px 16px;
  }

  .process.is-rail .pstep__media {
    flex: 0 1 auto;
    min-height: 120px;
    aspect-ratio: 640 / 540;
  }

  .pstep__body {
    flex: none;
    grid-template-rows: auto auto auto;
    gap: 12px;
    padding: 18px 20px 20px;
  }

  .pstep__title {
    font-size: clamp(1.875rem, 8cqw, 2.5rem);
  }

  .pstep__text {
    font-size: clamp(0.9375rem, 3.9cqw, 1.0625rem);
  }
}

/* Short screens: the chips fold to the one showing, then the head shrinks. */
@media (max-height: 760px), (max-width: 769px) {
  .process.is-rail .pstep__for-label,
  .process.is-rail .pchip:not(.is-on) {
    display: none;
  }
}

@media (max-width: 769px) {
  /* The rail keeps the label row too, a little tighter (the picture gives
     way for it). */
  .process.is-rail .process__head {
    row-gap: clamp(12px, 1.8vh, 18px);
  }

  .process {
    --tab-h: 38px;
  }

  .process__nav {
    padding: 0 12px;
  }

  .process__tabs,
  .process__ink {
    gap: 4px;
  }

  .process__tab,
  .process__ink > span {
    padding: 0 11px;
    font-size: 12.5px;
  }
}

@media (max-height: 560px) {
  .process {
    --tab-h: 36px;
  }

  .process.is-rail .process__label,
  .process.is-rail .process__index {
    display: none;
  }

  .process.is-rail .process__title {
    font-size: clamp(1.75rem, 9vh, 3rem);
  }

  .process.is-rail .pstep__body {
    gap: 10px;
    padding: 18px 22px;
  }

  .process.is-rail .pstep__title {
    font-size: clamp(1.5rem, 7.5vh, 2.25rem);
  }

  .process.is-rail .pstep__text {
    font-size: 0.875rem;
    line-height: 1.34;
  }
}

/* ------------------------------------------------------------------ reveal */

/* The first time it comes into view (process.js arms it, so without the
   script nothing hides): the title's words rise, the pills rise and the
   rail rises into place. */
.process.is-armed .process__mask > span {
  transform: translateY(110%);
  transition: transform 1150ms var(--ease-out) calc(var(--i, 0) * 80ms);
}

.process.is-armed .process__label,
.process.is-armed .process__index,
.process.is-armed .process__count {
  opacity: 0;
  transition: opacity 900ms ease 300ms;
}

.process.is-armed .process__tabs {
  opacity: 0;
  translate: 0 14px;
  transition:
    opacity 700ms ease 250ms,
    translate 1000ms var(--ease-out) 250ms;
}

.process.is-armed .process__rail {
  opacity: 0;
  translate: 0 70px;
  transition:
    opacity 900ms ease 320ms,
    translate 1300ms var(--ease-out) 320ms;
}

.process.is-in .process__mask > span {
  transform: none;
}

.process.is-in .process__label,
.process.is-in .process__index,
.process.is-in .process__count,
.process.is-in .process__tabs,
.process.is-in .process__rail {
  opacity: 1;
  translate: none;
  scale: none;
}

/* A card's words play in as it arrives, and reset (instantly, off screen)
   once it has left, so they play again next time. */
.process.is-armed .pstep .pstep__mask > span {
  transform: translateY(108%);
}

.process.is-armed .pstep .pstep__n,
.process.is-armed .pstep .pchip,
.process.is-armed .pstep .pstep__for-label {
  opacity: 0;
}

.process.is-armed .pstep .pstep__text {
  opacity: 0;
  translate: 0 18px;
}

.process.is-armed .pstep.is-shown .pstep__mask > span {
  transform: none;
  transition: transform 1100ms var(--ease-out) 80ms;
}

.process.is-armed .pstep.is-shown .pstep__n,
.process.is-armed .pstep.is-shown .pstep__for-label {
  opacity: 1;
  transition: opacity 700ms ease 350ms;
}

.process.is-armed .pstep.is-shown .pchip {
  opacity: 1;
  transition:
    opacity 600ms ease calc(300ms + var(--c, 0) * 60ms),
    color 300ms ease,
    background-color 300ms ease,
    box-shadow 300ms ease;
}

.process.is-armed .pstep.is-shown .pstep__text {
  opacity: 1;
  translate: none;
  transition:
    opacity 800ms ease 260ms,
    translate 1100ms var(--ease-out) 260ms;
}

@media (prefers-reduced-motion: reduce) {
  .process *,
  .process *::before,
  .process *::after {
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
  }

  /* The services don't cycle on their own here, so no timer runs out. */
  .pchip::after {
    display: none;
  }
}

/* Phones: the site's section rhythm (--sec-top / --sec-bot / --sec-end, tokens.css),
   so every gap between two sections reads the same. */
@media (max-width: 719px) {
  /* The rail: a little paper after the pin, so the gap to the next section
     matches the others (the stage's own foot stays tight for the cards). */
  .process.is-rail {
    padding-bottom: clamp(44px, 8vh, 64px);
  }

  .process:not(.is-rail) .process__stage {
    padding-top: var(--sec-top);
    padding-bottom: var(--sec-bot);
  }
}
