/* ════════════════════════════════════════════════════════════
   RECRUITING & DIRECT PLACEMENTS
   The `-caleb` redesign candidate, promoted into the canonical
   slot S128. Prefix `r-` kept throughout. The page it replaced is
   in _archive/services/recruiting-replaced-s128.html (its CSS and
   JS alongside it), and the split-screen page that one replaced
   is _archive/services/recruiting.html.

   Nine sections, alternating dark/grey without exception:
     hero · funnel · journey · find · place · speed · quotes ·
     video · Calendly
   The truncated-cone funnel (250,000 → 2,500 → 43) is the spine.
   ════════════════════════════════════════════════════════════ */

:root { --mono: "JetBrains Mono", ui-monospace, monospace; }

.reveal-delay-1 { transition-delay: 0.12s; }
.reveal-delay-2 { transition-delay: 0.22s; }
.reveal-delay-3 { transition-delay: 0.32s; }
.reveal-delay-4 { transition-delay: 0.44s; }

/* S01 · HERO — shared services formula: markup rendered by
   /js/svc-heroes.js, styles in /css/services/svc-hero.css */

/* ── S02 · THE FUNNEL ───────────────────────────────────────
   Headline + scroll canvas are one grey section: the headline
   makes the claim, the canvas below proves it. */
.r-funnel {
  background: var(--jg-dark-inlay);
  /* Explicit, so the global `section { padding-block: 11vh }` can't apply.
     No padding on top — the headline band carries its own.
     The bottom gap lets the funnel finish and clear before Positions
     starts; it sits outside #funnel, so it adds no scroll travel.
     Kept SHORT: combined with the canvas run-out below the apex it is
     the empty grey tail that trails the departing funnel — at 16vh the
     exit read as ~300px of dead scroll. */
  padding-top: 0;
  padding-bottom: clamp(56px, 8vh, 96px);
}

/* ---- headline band ----
   Content-sized: the headline sits directly on top of the funnel window.
   No runway needed anymore — the stations live INSIDE the funnel window
   and crop at its edge, so nothing can rise up into the headline's air. */
.intro-band {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: clamp(56px, 9vh, 110px) 2rem clamp(56px, 8vh, 96px);
  position: relative;
}

.intro-head {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.4rem, 6vw, 5.5rem);
  line-height: 0.95;
  text-transform: uppercase;
  color: var(--jg-light);
  position: relative;
  z-index: 1;
}

.intro-head em {
  font-style: normal;
  color: var(--jg-primary);
}

.intro-sub {
  max-width: 46ch;
  margin-top: 1.6rem;
  position: relative;
  z-index: 1;
}

.intro-band .rise {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity 0.8s ease, transform 0.9s cubic-bezier(0.16, 0.84, 0.44, 1);
}
.intro-band.visible .rise { opacity: 1; transform: none; }
.intro-band.visible .rise:nth-child(2) { transition-delay: 0.12s; }
.intro-band.visible .rise:nth-child(3) { transition-delay: 0.24s; }

/* ---- static funnel: NO pin, NO scroll-driven camera. The section is
   a tall standing diagram — the full cone with all three stations —
   that scrolls past like any other content. Only the time-driven
   ambient layer (candidates in, employee stars out) animates.
   Dominance (scale + brightness) still favours the station nearest
   the viewport centre as you scroll by. ---- */
#funnel {
  position: relative;
  height: 150vh;
  /* The truncated cone leaves structural blanks in its box: ~22% above
     the mouth and ~17% below the drain. The neighbours overlap them:
     pulling #funnel up tucks the mouth under the intro's copy, and the
     negative bottom brings the journey section in behind the drain. */
  margin-top: -26vh;
  margin-bottom: -18vh;
  /* Passive diagram (canvas + labels, nothing clickable). Its blank
     drain overlaps the next section via the negative margin, and being
     positioned it would otherwise steal that section's clicks — so let
     pointer events fall through to whatever sits beneath. */
  pointer-events: none;
}

/* Covers ALL of #funnel (canvas height = funnel height), which zeroes
   the JS camera offset — the whole cone is drawn in place. Still the
   crop box for stations and paint. */
#canvas-wrapper {
  position: absolute;
  inset: 0;
  width: 100%;
  pointer-events: none;
  overflow: hidden;
}

#funnel-canvas {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
}

/* Page-scoped nav fix: the funnel scrolls a giant cyan headline and huge
   stage numbers UNDER the fixed nav; at the sitewide rgba(...,0.92) +
   backdrop-blur they bleed through as teal/grey blotches in the chrome.
   Fully opaque here so bright content (and the departing 43's glow
   plate) can't dirty the nav on this page.
   (This file loads after styles.css, so equal specificity wins.) */
nav.scrolled { background: rgba(22, 23, 25, 1); }

/* ── STAGE STATIONS (text left · number in funnel right) ──────
   Absolute inside #canvas-wrapper — funnel coordinate space, not
   viewport space. The JS prints each station at its fixed depth of
   the funnel's height (no camera offset — the funnel is static), so
   text, numbers, and walls share one coordinate space. Anchored in
   the wrapper they also stack below the fixed nav and crop at the
   window's edges for free. */
.stage-row {
  position: absolute;
  left: 0; right: 0;
  top: 0;
  height: 0;
  /* Same content box as every other section: capped at the site wrap and
     centred. Children position in % of this box, and the canvas keys its
     funnel geometry to the same box in JS, so text, numbers, and walls
     all breathe with the wrap — only the section background bleeds. */
  max-width: var(--wrap-max);
  margin-inline: auto;
  z-index: 2;
  pointer-events: none;
  will-change: top, opacity;
}

.row-text {
  position: absolute;
  left: clamp(24px, 6vw, 96px);   /* the standard page gutter */
  width: 42%;
  transform: translateY(-50%);
  text-align: left;
}

.row-eyebrow {
  font-family: var(--mono);
  font-size: 0.65rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--jg-primary);
  margin-bottom: 0.9rem;
  opacity: 0.85;
}

.row-head {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.4rem, 2.6vw, 2.4rem);
  line-height: 1.05;
  text-transform: uppercase;
  color: var(--jg-light);
  margin-bottom: 1rem;
}

/* .prose carries family / weight / size / colour; this only tightens
   the leading. `p.` so it clears `p.prose`'s specificity. */
p.row-body {
  line-height: 1.65;
}

.row-connector {
  position: absolute;
  top: 0;
  height: 1px;
  transform: translateY(-50%);
  background: linear-gradient(to right, rgba(0,189,255,0.08), rgba(0,189,255,0.55));
}

.row-connector::after {
  content: '';
  position: absolute;
  right: -2px;
  top: 50%;
  transform: translateY(-50%);
  width: 5px;
  height: 5px;
  background: var(--jg-primary);
  border-radius: 50%;
}

.row-num {
  position: absolute;
  left: 75%;   /* the funnel's centreline — matches the canvas cx (gx(0.75)) */
  transform: translate(-50%, -50%);
  text-align: center;
  will-change: transform;
}

.num-value {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.6rem, 6.5vw, 6.5rem);
  line-height: 1;
  color: var(--jg-light);
  letter-spacing: -0.02em;
  white-space: nowrap;
  /* Tight glow on purpose: at 80px the halo extended far past the digits
     and bled through the translucent fixed nav as a grey smudge while the
     settled 43 rode off underneath it. */
  text-shadow: 0 0 32px rgba(0,189,255,0.10);
}

.num-label {
  font-family: var(--mono);
  font-size: clamp(0.6rem, 1vw, 0.8rem);
  color: var(--jg-primary);
  letter-spacing: 0.35em;
  text-transform: uppercase;
  margin-top: 0.6rem;
  opacity: 0.9;
}

/* ── S04 · POSITIONS WE FILL ────────────────────────────────── */
.r-positions {
  background: var(--jg-dark-inlay);
  padding: 100px 0;
  position: relative;
}

.r-positions__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
}

.r-positions__header {
  margin-bottom: 52px;
}

.r-positions__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(32px, 4.5vw, 58px);
  text-transform: uppercase;
  color: var(--jg-light);
  line-height: 1;
  margin: 0;
}

.r-positions__sub {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 300;
  color: rgba(244,244,244,0.5);
  letter-spacing: 0.02em;
  margin: 0 0 40px;
  font-style: italic;
}

/* ---- Carousel outer wrapper (arrows sit outside) ---- */
.r-carousel-outer {
  position: relative;
  padding: 0 64px;
}

.r-carousel {
  overflow: hidden;
  padding: 8px 2px 2px;
  margin-top: -8px;
}

.r-carousel__track {
  display: flex;
  gap: 20px;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Each card: 1/3 of viewport minus gaps */
.r-role {
  flex: 0 0 calc((100% - 40px) / 3);
  background: var(--jg-dark);
  border: 1px solid rgba(0,189,255,0.1);
  border-radius: 4px;
  padding: 40px 32px 36px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  transition: border-color 0.22s, transform 0.22s;
}

.r-role:hover {
  border-color: rgba(0,189,255,0.35);
  transform: translateY(-4px);
}

.r-role__icon {
  width: 88px;
  height: 88px;
  margin-bottom: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.r-role__icon svg {
  width: 100%;
  height: 100%;
}

.r-role__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(18px, 1.8vw, 24px);
  text-transform: uppercase;
  color: var(--jg-primary);
  line-height: 1.1;
  margin: 0 0 14px;
}

.r-role__desc {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 300;
  color: rgba(244,244,244,0.62);
  line-height: 1.65;
  margin: 0;
}

/* Side arrows */
.r-carousel__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  background: rgba(0,189,255,0.06);
  border: 1px solid rgba(0,189,255,0.28);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.2s, border-color 0.2s;
  color: rgba(244,244,244,0.6);
  z-index: 2;
}

.r-carousel__arrow:hover {
  background: rgba(0,189,255,0.14);
  border-color: var(--jg-primary);
  color: var(--jg-primary);
}

.r-carousel__arrow svg {
  width: 18px; height: 18px;
  stroke: currentColor; fill: none;
  stroke-width: 2; stroke-linecap: round; stroke-linejoin: round;
}

#rolesPrev { left: 0; }
#rolesNext { right: 0; }

/* Dots row below carousel */
.r-carousel__footer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 28px;
}

.r-carousel__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(244,244,244,0.18);
  border: none;
  padding: 0;
  cursor: pointer;
  transition: background 0.2s, transform 0.2s;
}

.r-carousel__dot.active {
  background: var(--jg-primary);
  transform: scale(1.5);
}

/* ── S07 · TESTIMONIALS — full-bleed scroll carousel ──────────
   Sandbox §7 winner (S128). The section runs edge to edge and the
   track scrolls inside it: --rt-gutter is the distance from the
   viewport edge to the content column, so a snapped card lands on
   the same gutter every other section uses while the next one
   bleeds past the right page edge as the swipe cue. */
.r-testimonials {
  --rt-pad: clamp(24px, 6vw, 96px);
  --rt-gutter: max(var(--rt-pad), calc(50vw - var(--wrap-max) / 2 + var(--rt-pad)));
  background: var(--jg-dark);
  padding: clamp(72px, 10vh, 112px) 0;
  position: relative;
  overflow: hidden;
}

.r-testimonials__top-rule {
  position: absolute;
  top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgba(0,189,255,0.35) 50%, transparent 100%);
}

.r-testimonials__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: var(--rt-pad);
}

/* Left-aligned, not centred: the header shares the gutter the first
   card snaps to, so the two read as one column. */
.r-testimonials__header {
  margin-bottom: 3rem;
}

.r-testimonials__label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--jg-primary);
  margin-bottom: 1.1rem;
}

.r-testimonials__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 3.4vw, 46px);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  color: var(--jg-light);
  line-height: 1;
  margin: 0;
}

.rt-carousel { position: relative; }

.rt-track {
  display: flex;
  gap: 24px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--rt-gutter);
  padding-inline: var(--rt-gutter);
  padding-bottom: 20px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: rgba(0,189,255,0.4) rgba(244,244,244,0.06);
}

.rt-track::-webkit-scrollbar { height: 6px; }
.rt-track::-webkit-scrollbar-track { background: rgba(244,244,244,0.06); border-radius: 3px; }
.rt-track::-webkit-scrollbar-thumb { background: rgba(0,189,255,0.4); border-radius: 3px; }
.rt-track::-webkit-scrollbar-thumb:hover { background: rgba(0,189,255,0.65); }

/* Two cards fill the content column exactly (minus the one gap
   between them), which forces the third to bleed off the edge. */
.r-testimonial {
  flex: 0 0 calc((min(100vw, var(--wrap-max)) - 2 * var(--rt-pad) - 24px) / 2);
  scroll-snap-align: start;
  box-sizing: border-box;
  background: var(--jg-dark-inlay);
  border: 1px solid rgba(0,189,255,0.1);
  border-radius: 4px;
  padding: 44px 40px 36px;
  position: relative;
  overflow: hidden;
  /* Cards stretch to the tallest quote; the attribution rides the
     bottom of each so the faces sit on one line across the track
     instead of floating wherever the copy happens to end. */
  display: flex;
  flex-direction: column;
}
.r-testimonial__attr { margin-top: auto; }

/* Large decorative quote mark */
.r-testimonial::before {
  content: '\201C';
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 160px;
  color: rgba(0,189,255,0.06);
  position: absolute;
  top: -16px;
  left: 20px;
  line-height: 1;
  pointer-events: none;
}

/* .prose carries family / weight / colour; the quote keeps only its
   own larger size and looser leading. Selector is `p.` so it clears
   `p.prose`'s specificity — a bare class would lose the line-height. */
p.r-testimonial__quote {
  font-size: clamp(17.5px, 1.35vw, 19px);
  line-height: 1.75;
  margin: 0 0 32px;
  position: relative;
  z-index: 1;
}

p.r-testimonial__quote em {
  font-style: italic;
  color: var(--jg-light);
  font-weight: 500;
}

.r-testimonial__attr {
  display: flex;
  align-items: center;
  gap: 16px;
  position: relative;
  z-index: 1;
}

.r-testimonial__photo {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  object-fit: cover;
  filter: grayscale(25%);
  border: 2px solid rgba(0,189,255,0.28);
  flex-shrink: 0;
}

/* Initials plate for a voice with no photo on file. */
.r-testimonial__photo--mono {
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0,189,255,0.08);
  font-family: var(--mono);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--jg-primary);
}

.r-testimonial__name {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  color: var(--jg-light);
  line-height: 1;
  margin-bottom: 5px;
}

.r-testimonial__role {
  font-family: var(--mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--jg-primary);
  opacity: 0.8;
}

/* ── S08 · VIDEO — paired with copy ─────────────────────────
   The play frame and the argument for pressing it, side by side
   (sandbox §8 winner). Frame left at 3fr so it stays the visual
   event; copy right at 2fr. Grey, following the dark testimonial
   scroller above it (S128). */
.r-video {
  background: var(--jg-dark-inlay);
  border-top: 1px solid rgba(244,244,244,0.06);
  position: relative;
}

.r-video__inner {
  max-width: var(--wrap-max);
  margin-inline: auto;
  display: grid;
  grid-template-columns: 3fr 2fr;
  align-items: stretch;
}

/* Left: the frame. Dotted field + centred play ring — a placeholder
   that reads as a video slot, not as a broken image. */
.r-video__visual {
  position: relative;
  min-height: clamp(280px, 40vw, 460px);
  background: linear-gradient(135deg, #1b2026, #121316);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  overflow: hidden;
}

.r-video__visual::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(244,244,244,0.05) 1px, transparent 1px);
  background-size: 24px 24px;
  opacity: 0.5;
}

.r-video__play {
  position: relative;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  border: 1px solid rgba(0,189,255,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.2s;
}

.r-video__play:hover { background: rgba(0,189,255,0.08); }
.r-video__play svg { margin-left: 3px; }

.r-video__visual-label {
  position: relative;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--jg-light);
  text-align: center;
  line-height: 1.6;
}

/* Right: the copy column. */
.r-video__copy {
  padding: clamp(40px, 5vw, 72px) clamp(28px, 4vw, 64px);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 20px;
}

.r-video__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(30px, 3.4vw, 48px);
  line-height: 1;
  text-transform: uppercase;
  color: var(--jg-light);
  margin: 0;
}

.r-video__h2 em { color: var(--jg-primary); font-style: normal; }

/* .prose carries size + colour; this only sets measure and rhythm. */
.r-video__body { line-height: 1.8; max-width: 44ch; margin: 0; }

.r-video__cta { align-self: flex-start; }

@media (max-width: 860px) {
  .r-video__inner { grid-template-columns: 1fr; }
}

/* ── S07 · CALENDLY / CTA ───────────────────────────────────── */
.r-calendly {
  background: var(--jg-dark);
  padding: 100px 0;
  position: relative;
  overflow: hidden;
}

.r-calendly__top-rule {
  position: absolute;
  top: 0; left: 0; right: 0; height: 1px;
  background: linear-gradient(90deg, transparent 0%, rgba(0,189,255,0.35) 50%, transparent 100%);
}

.r-calendly__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
}

.r-calendly__header {
  text-align: center;
  margin-bottom: 56px;
}

.r-calendly__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(40px, 6vw, 82px);
  text-transform: uppercase;
  color: var(--jg-light);
  line-height: 0.95;
  margin: 0 0 18px;
}

.r-calendly__h2 span { color: var(--jg-primary); }

.r-calendly__sub {
  max-width: 52ch;
  margin-inline: auto;
}

.r-calendly .calendly-inline-widget {
  max-width: 1000px;      /* deliberate cap — the booking widget doesn't scale past this */
  margin-inline: auto;
}

.r-calendly__note {
  display: block;
  text-align: center;
  margin-top: 24px;
  font-family: var(--mono);
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(0,189,255,0.45);
}

/* ── S09 · CTA ───────────────────────────────────────────────── */
.r-cta {
  background: var(--jg-dark);
  padding: 100px 0;
}

.r-cta__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
  text-align: center;
}

.r-cta__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(40px, 6vw, 82px);
  text-transform: uppercase;
  color: var(--jg-light);
  line-height: 0.95;
  margin: 0 0 18px;
}

.r-cta__h2 span { color: var(--jg-primary); }

.r-cta__sub {
  max-width: 52ch;
  margin-inline: auto;
  margin-bottom: 40px;
}

/* ── RESPONSIVE ─────────────────────────────────────────────── */
@media (max-width: 800px) {
  .r-testimonial-grid {
    grid-template-columns: 1fr;
  }

  /* One card fills the content column; the next bleeds past the
     edge as the swipe cue (the two-up split leaves ~160px cards
     at phone widths). */
  .r-testimonial {
    flex-basis: calc(100vw - 2 * var(--rt-pad) - 24px);
  }

  .r-carousel-outer { padding: 0 44px; }
  .r-role { flex: 0 0 100%; padding: 36px 24px 32px; }

  /* Two columns, tightened: text pulls in, the number rides further right
     so the digits stay inside the narrowing cone. Below 700px this stops
     working at all and the one-column block takes over. */
  .row-text { left: 6vw; width: 52vw; }
  .row-num { left: 82vw; }
}

/* ── PHONE FUNNEL · ONE COLUMN ───────────────────────────────
   Side-by-side dies here. Under 700px a 50vw text column pressed against
   the number left the headline running into the funnel wall, and the body
   copy had to be deleted outright to fit — mobile got three numbers and
   no argument.
   Instead the whole section becomes one column: the JS re-centres the cone
   and opens it to near-full width (MOUTH_*_1C / centreF), and each station
   stacks on that centreline — number, label, then its own copy directly
   beneath. The bridging connector is gone; there's no gap left to cross.
   The copy shortens rather than shrinks: `.row-body__more` drops the
   trailing sentence, because the 17.5px .prose floor is not negotiable.
   Everything that ISN'T prose (number, label, eyebrow, headline) resizes
   freely, and the stations spread to depth1c so three stacked blocks
   have air between them inside the same 150vh. */
@media (max-width: 700px) {
  .stage-row {
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    /* the row is printed at its depth; centre the whole stack on it */
    transform: translateY(-50%);
    padding-inline: 22px;
  }

  /* Number first, copy under it — the stat is what you scroll for. */
  .row-num {
    position: static;
    order: 0;
    left: auto;
    /* transform is JS-owned (dominance scale only in one-column mode) */
  }

  .row-text {
    position: static;
    order: 1;
    left: auto;
    width: 100%;
    max-width: 32ch;
    margin-top: 0.9rem;
    transform: none;
    text-align: center;
  }

  .row-connector { display: none; }
  .row-body__more { display: none; }

  /* Capped at 4rem: the stacks are ~204px tall at phone widths and sit
     ~43px apart, and every px the number grows near the 700px switch eats
     that gap. */
  .num-value { font-size: clamp(3rem, 13vw, 4rem); }
  .num-label { font-size: 0.6rem; letter-spacing: 0.28em; margin-top: 0.5rem; }

  .row-eyebrow { font-size: 0.58rem; letter-spacing: 0.2em; margin-bottom: 0.5rem; }
  .row-head { font-size: clamp(1.5rem, 6.6vw, 2rem); margin-bottom: 0.55rem; }
}

@media (max-width: 540px) {
  .r-testimonial { padding: 32px 24px 28px; }
}

@media (prefers-reduced-motion: reduce) {
  .r-carousel__track { transition: none; }
}


/* ════════════════════════════════════════════════════════════
   S03 · CANDIDATE JOURNEY — the five-stage spine, ported from
   sandbox2 Section 5 (Spine take, chip-less). Dark, so the page
   keeps its strict dark/grey alternation off the grey funnel above.
   Positioned + opaque on purpose: #funnel's -18vh bottom margin
   pulls this section up over the canvas run-out below the drain, and
   only a solid plate stops the funnel's grey tail showing through.
   Small top padding for the same reason — it absorbs that overshoot.
   Entrances ride the site-wide .reveal rig (main.js), so this
   block is layout-only.
   ════════════════════════════════════════════════════════════ */
.r-journey {
  position: relative;
  background: var(--jg-dark);
  padding: clamp(48px, 7vh, 80px) 0 clamp(72px, 10vh, 112px);
}

.r-journey__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
}

.cj-head { max-width: 880px; margin-bottom: clamp(40px, 6vh, 72px); }
.cj-head--center { margin-inline: auto; text-align: center; }

.cj-h2 {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  font-size: clamp(30px, 3.4vw, 52px);
  line-height: 1.02;
  letter-spacing: 0.01em;
  color: var(--jg-light);
  margin-bottom: 0.6rem;
}

.cj-sub { max-width: 58ch; }
.cj-head--center .cj-sub { margin-inline: auto; }

.cjs-list { list-style: none; margin: 0 auto; padding: 8px 0 4px; position: relative; max-width: 1120px; }

/* The rail is scroll-tracked: a dim base (::before) with a bright fill
   (::after) that grows top-down as you scroll. JS sets --cjs-p (0-1) on
   the list and toggles .lit on each item as the fill reaches it. */
.cjs-list::before {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  transform: translateX(-0.5px);
  background: rgba(244, 244, 244, 0.09);
}
.cjs-list::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  transform: translateX(-0.5px) scaleY(var(--cjs-p, 0));
  transform-origin: top;
  background: linear-gradient(to bottom, rgba(0, 189, 255, 0.9), rgba(0, 189, 255, 0.35));
  box-shadow: 0 0 8px rgba(0, 189, 255, 0.35);
  z-index: 0;
}

.cjs-item {
  position: relative;
  width: calc(50% - clamp(28px, 4vw, 56px));
  padding: 4px 0 clamp(28px, 4vh, 44px);
}
.cjs-item:nth-child(even) { margin-left: auto; }
/* Tight interleave, uniform rhythm: cards are equalised to one height
   (below), so a single pull gives the same diagonal step everywhere.
   Both terms track viewport width together, so the three same-side
   gaps (1/3, 2/4, 3/5) stay equal and collision-free at any width. */
.cjs-item + .cjs-item { margin-top: clamp(-120px, 5vw - 132px, -30px); }
.cjs-item:last-child { padding-bottom: 8px; }

/* node on the rail + connector to the card */
.cjs-item::before {
  content: "";
  position: absolute;
  top: 30px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(244, 244, 244, 0.18);
  border: 1.5px solid rgba(244, 244, 244, 0.3);
  box-shadow: none;
  transition: background 0.4s ease, border-color 0.4s ease, box-shadow 0.4s ease;
  z-index: 1;
}
.cjs-item.lit::before {
  background: var(--jg-primary);
  border-color: var(--jg-primary);
  box-shadow: 0 0 8px rgba(0, 189, 255, 0.45);
}
.cjs-item:nth-child(odd)::before  { right: calc(clamp(28px, 4vw, 56px) * -1 - 4.5px); }
.cjs-item:nth-child(even)::before { left:  calc(clamp(28px, 4vw, 56px) * -1 - 4.5px); }
.cjs-item::after {
  content: "";
  position: absolute;
  top: 34px;
  width: clamp(28px, 4vw, 56px);
  height: 1px;
  background: rgba(0, 189, 255, 0.22);
}
.cjs-item:nth-child(odd)::after  { right: calc(clamp(28px, 4vw, 56px) * -1); }
.cjs-item:nth-child(even)::after { left:  calc(clamp(28px, 4vw, 56px) * -1); }

.cjs-item--last.lit::before {
  box-shadow: 0 0 14px rgba(0, 189, 255, 0.65);
}

.cjs-card {
  background: rgba(244, 244, 244, 0.025);
  border: 1px solid rgba(244, 244, 244, 0.07);
  border-radius: 4px;
  padding: clamp(20px, 2.6vw, 32px);
}

.cjs-stage {
  display: block;
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--jg-primary);
  margin-bottom: 10px;
}

.cjs-h {
  font-family: var(--font-display);
  font-weight: 400;
  text-transform: uppercase;
  font-size: clamp(19px, 1.8vw, 26px);
  line-height: 1.08;
  color: var(--jg-light);
  margin-bottom: 10px;
}

@media (min-width: 600px) {
  .cjs-item { padding-bottom: 36px; }
  /* one card height ⇒ one step ⇒ equal gaps at every width */
  .cjs-card {
    min-height: clamp(220px, 430px - 10vw, 420px);
    display: flex;
    flex-direction: column;
  }
}

@media (max-width: 599px) {
  .cjs-list::before,
  .cjs-list::after { left: 4px; }
  .cjs-item,
  .cjs-item + .cjs-item,
  .cjs-item:nth-child(even) { width: auto; margin-left: 28px; margin-top: 0; }
  .cjs-item::before,
  .cjs-item:nth-child(even)::before { left: -28.5px; right: auto; }
  .cjs-item::after,
  .cjs-item:nth-child(even)::after { left: -24px; right: auto; width: 20px; }
}


/* ════════════════════════════════════════════════════════════
   S04 · HOW WE FIND TALENT — the numbered-principles list,
   ported from the canonical /services/recruiting `.s04` (S128).
   Renamed out of that page's `.s04`/`.principle*` names into this
   page's `r-` family, per the S125 rule that a ported section
   takes the host stylesheet's family rather than forking one.
   Grey, taking the alternation off the dark journey above it.
   Body copy rides `.prose` — the source's hardcoded
   rgba(244,244,244,0.55) / weight 300 were dropped.
   ════════════════════════════════════════════════════════════ */
.r-find {
  background: var(--jg-dark-inlay);
  padding: clamp(72px, 10vh, 112px) 0;
}

.r-find__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
}

/* Fixed 360px head column: the headline is a standing title beside
   the list, not a stacked intro — the list is what scrolls long. */
.r-find__grid {
  display: grid;
  grid-template-columns: 360px 1fr;
  gap: 6rem;
  align-items: start;
}

.r-find__label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--jg-primary);
  margin-bottom: 1.1rem;
}

.r-find__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 3vw, 44px);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1;
  color: var(--jg-light);
  margin: 0;
}

.r-find__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* Hairline rules between rows: top on every row, plus a bottom on
   the last, so the list closes as a block rather than trailing off. */
.r-principle {
  display: grid;
  grid-template-columns: 40px 1fr;
  gap: 0 1.25rem;
  align-items: baseline;
  padding: 1.85rem 0;
  border-top: 0.5px solid rgba(244,244,244,0.09);
}

.r-principle:last-child { border-bottom: 0.5px solid rgba(244,244,244,0.09); }

.r-principle__num {
  font-family: var(--mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--jg-primary);
  padding-top: 2px;
}

.r-principle__h {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 20px;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--jg-light);
  margin: 0 0 0.6rem;
}

.r-principle__b {
  line-height: 1.7;
  margin: 0;
  max-width: 62ch;
}

/* Below the two-column threshold the head stacks over the list. */
@media (max-width: 900px) {
  .r-find__grid { grid-template-columns: 1fr; gap: 2.5rem; }
}


/* ════════════════════════════════════════════════════════════
   S05 · WHAT WE PLACE — the categorised role chips, ported from
   the canonical /services/recruiting `.s06` (S128, sandbox §10
   "Pill list"). Renamed out of that page's .s06/.role-* names
   into this page's `r-` family, same rule as .r-find above.
   Dark, off the grey "How we find talent" section. Deliberately
   motionless past the entrance — it is the page's rest stop
   between the funnel and the speed rail.
   ════════════════════════════════════════════════════════════ */
.r-place {
  background: var(--jg-dark);
  padding: clamp(64px, 9vh, 104px) 0;
}

.r-place__wrap {
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
}

/* Fixed 320px intro column: the copy is a standing caption beside
   the list, and the chips take every pixel that's left. */
.r-place__grid {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 4rem;
  align-items: start;
}

.r-place__label {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--jg-primary);
  margin-bottom: 1.1rem;
}

.r-place__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 2.4vw, 32px);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 1.05;
  color: var(--jg-light);
  margin: 0 0 1rem;
}

/* .prose carries size + colour; this only sets rhythm. */
.r-place__body {
  line-height: 1.7;
  margin: 0;
}

.r-cats {
  display: flex;
  flex-direction: column;
}

/* Hairline per row plus one closing rule under the last, so the
   list reads as a block rather than trailing off — same treatment
   as .r-principle above. */
.r-cat {
  padding: 1.25rem 0;
  border-top: 0.5px solid rgba(244,244,244,0.09);
}
.r-cat:last-child { border-bottom: 0.5px solid rgba(244,244,244,0.09); }

.r-cat__label {
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--jg-primary);
  margin-bottom: 0.75rem;
}

.r-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
}

/* Pills, not teardrops: these are labels, not buttons. */
.r-chip {
  font-family: var(--font-body);
  font-size: 12.5px;
  font-weight: 400;
  color: var(--prose-color);
  background: rgba(255,255,255,0.03);
  border: 0.5px solid rgba(244,244,244,0.14);
  border-radius: 100px;
  padding: 0.4rem 0.95rem;
  white-space: nowrap;
  transition: color 0.2s, border-color 0.2s;
}
.r-chip:hover {
  color: var(--jg-light);
  border-color: rgba(0,189,255,0.4);
}

@media (max-width: 860px) {
  .r-place__grid { grid-template-columns: 1fr; gap: 2.5rem; }
}


/* ════════════════════════════════════════════════════════════
   S06 · BUILT TO MOVE QUICKLY — three numbers strung along a lit
   rail (supplied mockup, S128). The rail draws left→right on
   entry, the nodes pop on behind it, and one soft pulse travels
   the line on a slow loop — the only continuous motion in the
   block, and small and crisp rather than a glow wash.
   Grey, taking the alternation off the dark chip list above.
   ════════════════════════════════════════════════════════════ */
.r-speed {
  background: var(--jg-dark-inlay);
  padding: clamp(72px, 10vh, 104px) 0;
  position: relative;
  overflow: hidden;
}

/* No background texture: the section is flat grey. The slanted
   hairline weave was cut S129 — the rail is the only line here. */

.r-speed__wrap {
  position: relative;
  max-width: var(--wrap-max);
  margin-inline: auto;
  padding-inline: clamp(24px, 6vw, 96px);
}

/* No mono eyebrow here (cut S129) — the headline stands alone. */
.r-speed__h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(30px, 3.4vw, 52px);
  text-transform: uppercase;
  letter-spacing: 0.01em;
  line-height: 0.96;
  color: var(--jg-light);
  margin: 0;
  max-width: 18ch;
}
.r-speed__h2 em { font-style: normal; color: var(--jg-primary); }

.r-speed__rail-wrap {
  position: relative;
  margin-top: clamp(56px, 8vh, 84px);
}

/* The rail spans node-centre to node-centre: each column is 1/3 of
   the row, so the outer nodes sit at 1/6 in from either end. */
.r-speed__rail {
  position: absolute;
  top: 10px;
  left: 16.667%;
  right: 16.667%;
  height: 2px;
}

.r-speed__rail-line {
  position: absolute;
  inset: 0;
  background: linear-gradient(to right, rgba(0,189,255,0.35), var(--jg-primary));
  transform-origin: left;
  animation: r-speed-rail 0.9s ease 0.25s both;
}

/* One pulse, on its own clock — deliberately long-period so it
   reads as a signal passing, not a loading bar. */
.r-speed__pulse {
  position: absolute;
  top: 50%;
  left: 0;
  width: 96px;
  height: 18px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(0,189,255,0.85), rgba(0,189,255,0));
  filter: blur(3px);
  pointer-events: none;
  animation: r-speed-flow 7s ease-in-out 1.2s infinite;
}

@keyframes r-speed-rail {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

@keyframes r-speed-flow {
  0%   { left: 0%;   opacity: 0; }
  18%  { opacity: 0.4; }
  82%  { opacity: 0.4; }
  100% { left: 100%; opacity: 0; }
}

/* No column gap on purpose: with one, the columns are narrower than a
   third and their centres drift inward of the rail's 1/6 and 5/6
   anchors. Zero gap makes each column exactly a third, so the nodes
   land on the rail ends; the breathing room moves inside the cell. */
.r-speed__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
}

.r-stat {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-inline: clamp(8px, 1.5vw, 24px);
}

.r-stat__node {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 3px solid var(--jg-primary);
  background: var(--jg-dark-inlay);
  box-shadow: 0 0 16px 2px rgba(0,189,255,0.55);
  margin-bottom: 48px;
  transition: box-shadow 0.25s ease, transform 0.25s ease;
}
.r-stat:hover .r-stat__node {
  transform: scale(1.15);
  box-shadow: 0 0 22px 3px rgba(0,189,255,0.7);
}

.r-stat__figure { position: relative; }

/* Outlined ghost of the same digits, twice the size, sitting
   behind the figure. Pure decoration — aria-hidden in markup. */
.r-stat__ghost {
  position: absolute;
  left: 50%;
  top: 46%;
  transform: translate(-50%, -50%);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(120px, 14vw, 200px);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1.5px rgba(0,189,255,0.09);
  white-space: nowrap;
  pointer-events: none;
}

.r-stat__value-row {
  position: relative;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 8px;
}

.r-stat__value {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(64px, 7.5vw, 108px);
  line-height: 0.82;
  color: var(--jg-primary);
}

.r-stat__unit {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(20px, 2.1vw, 30px);
  text-transform: uppercase;
  color: var(--jg-active);
}
/* The per-cent sign is a glyph, not a word: bigger, tighter. */
.r-stat__unit--pct { font-size: clamp(26px, 2.9vw, 42px); text-transform: none; }
.r-stat__value-row:has(.r-stat__unit--pct) { gap: 4px; }

/* .prose carries size + colour; this only sets measure and rhythm. */
.r-stat__label {
  font-weight: 400;
  line-height: 1.45;
  margin: 22px 0 0;
  text-align: center;
  max-width: 22ch;
}

/* Phone widths: the rail can't span three columns that have
   stacked, so it goes and the stats become three stacked figures. */
@media (max-width: 700px) {
  .r-speed__grid { grid-template-columns: 1fr; gap: 48px; }
  .r-stat { padding-inline: 0; }
  .r-speed__rail { display: none; }
  .r-stat__node { margin-bottom: 28px; }
}

@media (prefers-reduced-motion: reduce) {
  .r-speed__pulse { display: none; }
  .r-speed__rail-line { animation: none; }
}
