body.impact-work-page { --cases-grey: #64647d; }
.work-scene::after {
  content: "";
  position: absolute;
  z-index: 3;
  right: 0;
  bottom: 0;
  left: 0;
  height: clamp(15rem, 42svh, 32rem);
  background: linear-gradient(to bottom, rgba(100, 100, 125, 0) 0%, rgba(100, 100, 125, .55) 50%, var(--cases-grey) 100%);
  pointer-events: none;
}
.impact-stories {
  position: relative;
  z-index: 2;
  /* Painted by the shared .impact-ground behind it and the quote
     (impact-intro.css), so the two can never disagree. */
  background: transparent;
  color: #f8f5fa;
  font-family: var(--font-ui, "Inter", Arial, sans-serif);
}
.impact-stories__head {
  --head-ink: color-mix(in srgb, #4c3074 calc((1 - var(--stories-ink, 1)) * 100%), #f8f5fa);
  position: sticky;
  z-index: 0;
  top: 0;
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100svh;
  padding: clamp(5rem, 8vh, 7rem) clamp(1.25rem, 4vw, 5rem) clamp(2rem, 5vh, 4rem);
  background: transparent;
  pointer-events: none;
}
/* The text fades but the monogram does not: the mark sits in the centre column,
   in the gutter between the two cards, and stays there the whole way down while
   the pairs pass either side of it. */
.impact-stories__eyebrow,
.impact-stories__head h2 span:first-child,
.impact-stories__head h2 span:last-child,
.impact-stories__head p:last-child { opacity: var(--case-title-opacity, 1); transition: opacity .1s linear; }
.impact-stories__eyebrow { margin: 0; color: var(--head-ink); font-size: .72rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; }
.impact-stories__head h2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(5rem, 10vw, 11rem) minmax(0, 1fr);
  align-items: center;
  gap: clamp(.5rem, 2vw, 2rem);
  margin: 0;
  color: var(--head-ink);
  font-weight: 600;
  line-height: .82;
  letter-spacing: -.085em;
  white-space: nowrap;
}
.impact-stories__head h2 span:first-child,
.impact-stories__head h2 span:last-child { font-size: clamp(3.4rem, 8.2vw, 11.5rem); }
/* 8.2vw is the widest the two words and the monogram can be set before the
   line runs off the screen. FEATURED PROJECTS is longer than the CASE
   STUDIES it replaced, and this tier — everything above 1600px — was still
   sized for the shorter pair, so both ends were being cut off. */
/* Both words hug the monogram, so the space either side of it is the grid gap
   and nothing else. Left as it was, the first word stretched across its column
   and sat against the far edge, which put it further from the mark than the
   second word — the mark was centred but did not look it. */
.impact-stories__head h2 span:first-child { justify-self: end; }
.impact-stories__head h2 span:last-child { justify-self: start; }
.impact-stories__mark {
  display: block;
  justify-self: center;
  width: clamp(4rem, 7vw, 8rem);
  height: clamp(7rem, 24vh, 16rem);
  position: relative;
  transition: transform .5s cubic-bezier(.22, 1, .36, 1);
}
/* The logo is the one set in Our Impact → Featured projects, shown as it is
   uploaded (the standard white mark) once the ground is purple. Under it, the
   official monogram in purple carries the mark while the ground is still
   white, and hands over as the words turn white. With no logo set, the
   monogram itself ends in white. */
.impact-stories__mark-ink,
.impact-stories__mark-logo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.impact-stories__mark-ink { color: color-mix(in srgb, #5f3c91 calc((1 - var(--stories-ink, 1)) * 100%), #fff); }
.impact-stories__mark-logo { object-fit: contain; opacity: var(--stories-ink, 1); }
.impact-stories__mark.has-logo .impact-stories__mark-ink { color: #5f3c91; opacity: calc(1 - var(--stories-ink, 1)); }
.impact-stories__head p:last-child { justify-self: center; max-width: 37rem; margin: 0; color: var(--head-ink); font-size: clamp(.9rem, 1vw, 1.05rem); line-height: 1.5; text-align: center; }
.impact-stories__stack { position: relative; z-index: 1; }
/* The pairs still stack and overlap — that sticky rise is the motion. What each
   pair no longer carries is its own copy of the section's gradient: that plate
   was a full-viewport rectangle sliding up behind the cards, and even in the
   same colour you read its leading edge as a boundary. Transparent now, so the
   section's gradient is one unbroken ground and the cards rise on their own. */
.impact-stories__pair {
  /* Sticky at every width: each pair pins and the next rises over it. On a
     phone the two stories of a pair are stacked rather than side by side, but
     the motion is the same — the projects come up the screen instead of the
     page going down past them. */
  position: sticky;
  top: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 4rem);
  align-content: center;
  min-height: 100svh;
  padding: clamp(5rem, 8vh, 7rem) clamp(1.25rem, 4vw, 5rem) clamp(4rem, 7vh, 6rem);
}
.impact-stories__pair:nth-child(2) { z-index: 2; }
.impact-stories__pair:nth-child(3) { z-index: 3; }
.impact-story { min-width: 0; }
.impact-story__button { display: block; width: 100%; padding: 0; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; cursor: pointer; text-decoration: none; }
.impact-story__image { display: block; width: 100%; aspect-ratio: 1.6; overflow: hidden; background: #e8e5e9; }
.impact-story__image img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .9s cubic-bezier(.22, 1, .36, 1), filter .6s ease; }
.impact-story__button:hover .impact-story__image img, .impact-story__button:focus-visible .impact-story__image img { transform: scale(1.045); filter: saturate(1.08); }
.impact-story__caption { display: flex; justify-content: space-between; gap: 1rem; align-items: start; padding: 1rem 0 .5rem; background: transparent; }
/* With no plate behind an arriving pair, its images cover the pair below but
   the captions do not — they sit in open space. So a caption hides itself once
   the pair above has reached it. */
.impact-story__caption.is-covered { visibility: hidden; opacity: 0; }
.impact-story__caption > span:first-child { display: grid; gap: .35rem; }
.impact-story__caption small { color: #e0d6e6; font-size: .7rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; }
.impact-story__caption strong { font-size: clamp(1.4rem, 2vw, 2.3rem); font-weight: 450; letter-spacing: -.045em; line-height: 1.08; }
.impact-story__caption em { color: #e0d6e6; font-size: .9rem; font-style: normal; line-height: 1.4; }
.impact-story__arrow { display: grid; place-items: center; flex: none; width: 2.7rem; height: 2.7rem; border: 1px solid #d9cde3; border-radius: 50%; color: #f8f5fa; font-size: 1.2rem; transition: color .3s, background .3s, transform .4s; }
.impact-story__button:hover .impact-story__arrow, .impact-story__button:focus-visible .impact-story__arrow { background: #f8f5fa; color: #443451; transform: rotate(45deg); }
.impact-story__button:focus-visible { outline: 2px solid #f8f5fa; outline-offset: 5px; }
.has-impact-case-cursor .impact-story__button { cursor: none; }
.impact-case-cursor {
  position: fixed;
  z-index: 80;
  top: 0;
  left: 0;
  display: grid;
  width: clamp(5rem, 6.3vw, 6rem);
  aspect-ratio: 1;
  place-items: center;
  border-radius: 50%;
  background: #f8f5fa;
  color: #443451;
  font: 700 .68rem/1 var(--font-ui, "Inter", sans-serif);
  letter-spacing: .12em;
  text-transform: uppercase;
  pointer-events: none;
  opacity: 0;
  transform: translate(-50%, -50%) scale(.7);
  transition: opacity .22s ease, transform .35s cubic-bezier(.22, 1, .36, 1);
}
.impact-case-cursor.is-visible { opacity: 1; transform: translate(-50%, -50%) scale(1); }
/* The logo wall, after the reference: an airy field on off-white with no rules
   or cards, every mark solid black at a common optical size, and far more room
   between the rows than between the columns.

   Flex rather than grid because 22 marks do not divide evenly: wrapping rows
   centre themselves, so the short last row sits in the middle instead of
   leaving a run of empty cells on the right. Each mark was pre-blackened with
   a transparent ground when it was brought over from the live site, so the
   JPEGs with white boxes behind them sit on the field like the PNGs do. */
.impact-clients { position: relative; z-index: 3; padding: clamp(4.5rem, 10vw, 10rem) clamp(1.25rem, 4vw, 5rem); background: #fff; }
.impact-clients p { margin: 0 0 clamp(3rem, 6vw, 6rem); color: #8a848f; font-size: .68rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; }
.impact-clients__logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  column-gap: clamp(1.25rem, 3vw, 2.75rem);
  row-gap: clamp(2.75rem, 6vw, 5.5rem);
}
/* Every logo at an even visual size: --logo-h is measured from each logo at
   build time (src/lib/logos.ts) — a square mark is 1 unit tall, a long
   wordmark less — so no logo reads smaller than its neighbours. The
   width/height attributes give the ratio only. */
.impact-clients__logos { --logo-unit: clamp(2.6rem, 4vw, 3.6rem); }
.impact-clients__logos img {
  display: block;
  flex: 0 0 auto;
  width: auto;
  height: calc(var(--logo-h, .6) * var(--logo-unit));
  object-fit: contain;
}

/* ——— The wall as two running rows ——— */
/* impact-clients.js rebuilds the field into two rows and fills each with as
   many copies of its set as the row needs. Each row travels exactly one copy's
   width and repeats, so a mark leaving the left edge is the same mark arriving
   at the right. The two rows run opposite ways at different speeds so the pair
   never reads as one block sliding. */
.impact-clients__logos.is-marquee { display: block; }
.impact-clients__row { width: 100%; overflow: hidden; }
.impact-clients__row + .impact-clients__row { margin-top: clamp(1.75rem, 4vw, 3.25rem); }
.impact-clients__loop {
  display: flex;
  width: max-content;
  animation: impact-clients-marquee 42s linear infinite;
  will-change: transform;
}
.impact-clients__row--reverse .impact-clients__loop { animation-duration: 52s; animation-direction: reverse; }
.impact-clients__group { display: flex; flex: 0 0 auto; align-items: center; }
.impact-clients__group > span {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  padding: 0 clamp(1rem, 3vw, 2.25rem);
}
.impact-clients__logos.is-marquee:hover .impact-clients__loop { animation-play-state: paused; }

@keyframes impact-clients-marquee {
  from { transform: translate3d(0, 0, 0); }
  to { transform: translate3d(calc(var(--clients-shift, 0px) * -1), 0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .impact-clients__loop { animation: none; }
}
@media (min-width: 900px) {
  .impact-stories__pair { position: sticky; top: 0; grid-template-columns: minmax(0, 1fr) clamp(8rem, 12vw, 14rem) minmax(0, 1fr); gap: 0; }
  .impact-stories__pair:first-child { z-index: 1; }
  .impact-story:first-child { grid-column: 1; }
  .impact-story:last-child { grid-column: 3; }
  .impact-story__image { aspect-ratio: 1.42; max-height: 52svh; }
}
@media (min-width: 900px) and (max-width: 1599px) {
  .impact-stories__head h2 span:first-child,
  .impact-stories__head h2 span:last-child { font-size: clamp(3rem, 8.2vw, 11.5rem); }
}
@media (max-width: 899px) {
  /* The head is a single-column grid, and a grid column sizes to its content's
     minimum — it will not shrink below it. FEATURED + the monogram + PROJECTS
     came to 365px inside a 320px content box at 360px wide, so the column grew
     and took the document with it: 25px of horizontal scroll on the narrower
     phones. minmax(0, 1fr) stops the column outgrowing its container, and the
     heading is sized so the three parts genuinely fit rather than being
     clipped. */
  .impact-stories__head { grid-template-columns: minmax(0, 1fr); }
  .impact-stories__head h2 { grid-template-columns: auto auto auto; gap: .3rem; justify-content: center; }
  .impact-stories__head h2 span:first-child,
  .impact-stories__head h2 span:last-child { font-size: clamp(1.75rem, 7vw, 5rem); }
  .impact-stories__mark { width: clamp(1.9rem, 5.5vw, 5rem); height: clamp(3.25rem, 11vh, 8rem); }

  /* The title is pinned and the projects travel over it.

     FEATURED PROJECTS and the monogram hold the middle of a screen of their own
     and stay there; the six projects come up from the bottom in a single
     column, one after another, and pass over the title on their way off the
     top. Not the desktop mechanic, where the pairs pin and rise under a
     monogram that sits in the gutter between two columns — here there is one
     column, nothing overlaps, and the title goes as the first project reaches
     it (impact-stories.js fades it on the first pair's position).

     So the pairs stop pinning and stop holding a screen each: at natural height
     their two stories simply join the column, which reads as the six in a line.
     The stack sits above the title rather than under it, which is the reverse
     of desktop — there the monogram has to stay visible between the columns. */
  .impact-stories__pair {
    position: relative;
    top: auto;
    z-index: auto;
    min-height: 0;
    padding: 0 1.25rem;
    gap: clamp(2.5rem, 7vh, 4.5rem);
  }
  .impact-stories__stack {
    z-index: 2;
    display: grid;
    gap: clamp(2.5rem, 7vh, 4.5rem);
    padding-bottom: clamp(3rem, 8vh, 5rem);
  }
  .impact-stories__head {
    position: sticky;
    top: 0;
    z-index: 0;
    min-height: 100lvh;
    padding-bottom: clamp(2rem, 5vh, 3.5rem);
  }
  /* Nothing overlaps here, so a caption is never covered. */
  .impact-story__caption.is-covered { visibility: visible; opacity: 1; }
  .impact-stories__mark { transition: opacity .45s ease, transform .5s cubic-bezier(.22, 1, .36, 1); }
  .impact-stories__head.is-cases .impact-stories__mark { opacity: 0; transform: translateY(-2rem) scale(.8); }

  /* The pairs keep stacking and rising exactly as they do on desktop: the two
     stories of a pair sit one above the other (the base rule is already a
     single column), and the three pairs overlap on scroll. Only the card's
     supporting copy is trimmed — the subtitle was a third line under a title
     that already says it, and the arrow disc only ever animated on hover. */
  .impact-story__caption { padding: .85rem 0 .5rem; }
  .impact-story__caption small { font-size: .62rem; letter-spacing: .1em; }
  .impact-story__caption strong { font-size: 1.35rem; line-height: 1.12; }
  .impact-story__caption em,
  .impact-story__arrow { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .impact-stories__head, .impact-stories__pair { position: relative; min-height: auto; }
  .impact-stories__mark { transition: none; }
  .impact-story__image img, .impact-story__arrow { transition: none; }
}
