/* Odenbridge — base styles
   Design source: docs/style-guide.md + UI mockups project scope.zip */

/* Only the display face is loaded — body copy is a system font, see --font-body. */
@font-face {
  font-family: 'Redaction';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(https://cdn.jsdelivr.net/fontsource/fonts/redaction@latest/latin-400-normal.woff2) format('woff2');
}

:root {
  --bg: #FAFAF8;
  --bg-alt: #F1F0EC;
  --bg-dark: #0A0A0A;
  --text: #111110;
  --text-muted: #57574F;
  --label: #7A7A74;
  --label-soft: #9A9A92;
  --text-on-dark: #FAFAF8;
  --text-on-dark-muted: rgba(250, 250, 248, .72);
  --border: rgba(0, 0, 0, .16);
  --border-soft: rgba(0, 0, 0, .1);
  --border-on-dark: rgba(250, 250, 248, .18);
  /* Helvetica by choice, not by fallback. It is what the site has always
     rendered as, and being a system face there is no webfont to fetch and no
     swap to reflow around. Windows has no Helvetica and resolves this to
     Arial, which is the intended stand-in. */
  --font-body: Helvetica, Arial, sans-serif;
  --font-display: 'Redaction', Georgia, serif;
  --max-width: 1400px;
  --gutter: 48px;
  --section-padding: 140px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 24px; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }

img { max-width: 100%; display: block; }

ul, ol { margin: 0; padding: 0; }

.wrap {
  width: 100%;
  /* `clip` rather than `hidden` so this stays a plain overflow guard instead of
     becoming a scroll container — `hidden` makes .wrap the nearest scrollport
     and silently breaks position:sticky anywhere inside it (the legal page's
     table of contents). Browsers without `clip` keep the `hidden` fallback and
     simply lose the stickiness. */
  overflow-x: hidden;
  overflow-x: clip;
}

.container {
  /* width:100% matters inside the flex hero — without it the container
     shrink-wraps to its content and margin:0 auto centers it. */
  width: 100%;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

/* ---------- Header / nav ---------- */

.site-header {
  position: relative;
  z-index: 50;
  background: transparent;
}

.nav {
  display: flex;
  align-items: center;
  gap: 40px;
  /* padding-block only — a `padding` shorthand here would override
     .container's horizontal gutter and pull the logo flush to the edge. */
  padding-top: 18px;
  padding-bottom: 18px;
}

.nav__logo { display: flex; align-items: center; gap: 12px; flex: none; }

.nav__links {
  margin-right: auto;
  display: flex;
  align-items: center;
  gap: 32px;
}

.nav__link {
  font-size: 14px;
  letter-spacing: .01em;
  color: var(--text-on-dark-muted);
  padding: 4px 0;
  border-bottom: 1px solid transparent;
  transition: color .2s, border-color .2s;
}
.nav__link:hover,
.nav__link.is-active {
  color: var(--text-on-dark);
  border-bottom-color: var(--text-on-dark);
}

.nav__toggle {
  display: none;
  margin-left: auto;
  background: none;
  border: 0;
  padding: 8px;
  cursor: pointer;
}
.nav__toggle svg { display: block; }

.btn {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 14px;
  font-weight: 500;
  padding: 11px 23px;
  border: 1px solid rgba(250, 250, 248, .55);
  background: transparent;
  color: var(--text-on-dark);
  white-space: nowrap;
  transition: background .2s, border-color .2s, color .2s;
}
.btn:hover {
  background: var(--text-on-dark);
  color: var(--bg-dark);
  border-color: var(--text-on-dark);
}
.btn--light {
  background: var(--text-on-dark);
  color: var(--bg-dark);
  border: 0;
}
.btn--light:hover { background: #fff; }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 16px;
  font-weight: 500;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--text);
  transition: gap .25s;
  align-self: start;
}
.link-arrow:hover { gap: 18px; }
.link-arrow--on-dark {
  border-bottom-color: rgba(250, 250, 248, .4);
  color: rgba(250, 250, 248, .75);
  transition: gap .25s, color .2s;
}
.link-arrow--on-dark:hover { color: var(--text-on-dark); }

/* Mobile full-screen menu overlay */
.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--bg-dark);
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 0 var(--gutter);
  opacity: 0;
  pointer-events: none;
  transform: translateY(-8px);
  transition: opacity .3s ease, transform .3s ease;
}
.nav-overlay.is-open { opacity: 1; pointer-events: auto; transform: none; }
.nav-overlay__links { display: flex; flex-direction: column; gap: 20px; }
.nav-overlay__links a {
  font-family: var(--font-display);
  font-size: clamp(32px, 10vw, 52px);
  color: var(--text-on-dark);
  letter-spacing: -.02em;
}
.nav-overlay__cta { margin-top: 40px; align-self: flex-start; }
.nav-overlay__close {
  position: absolute;
  top: 22px;
  right: var(--gutter);
  background: none;
  border: 0;
  color: var(--text-on-dark);
  padding: 8px;
  cursor: pointer;
}

/* ---------- Hero ---------- */

.hero-block {
  position: relative;
  overflow: hidden;
  background: var(--bg-dark);
}

.hero-pattern,
.hero-spotlight {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url('../assets/hero-pattern.jpg');
  background-size: cover;
  background-position: center;
  mix-blend-mode: screen;
}
.hero-pattern { opacity: .07; }
.hero-spotlight { opacity: 0; transition: opacity .4s ease; }

.hero {
  position: relative;
  z-index: 1;
  color: var(--text-on-dark);
  padding: 64px 0 96px;
  min-height: calc(100dvh - 98px);
  box-sizing: border-box;
  display: flex;
  align-items: flex-end;
}
.hero--short { min-height: calc(72dvh - 98px); }

.hero__headline {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(46px, 6.6vw, 104px);
  line-height: 1.02;
  letter-spacing: -.025em;
  margin: 0;
  max-width: 17ch;
  text-wrap: pretty;
}
.hero__headline--page {
  font-size: clamp(46px, 7vw, 110px);
  letter-spacing: -.028em;
  max-width: none;
}

/* Word-by-word hero reveal, driven by initHeroIntro(). Each word gets its own
   clipping box and its inner span is lifted up into view from below.
   overflow:hidden would otherwise slice descenders off at the baseline, so the
   clip box is opened downwards with padding-bottom and pulled back by an equal
   negative margin: the clipping region grows, the layout does not. The start
   offset has to clear that extra padding too, which is why it is 125% and not
   100% — at 100% the tops of the capitals would peek into the padding. */
.hero__headline.is-split .word {
  display: inline-block;
  overflow: hidden;
  padding-bottom: .16em;
  margin-bottom: -.16em;
}
.hero__headline.is-split .word__inner {
  display: inline-block;
  transform: translateY(125%);
  transition: transform 1s cubic-bezier(.22, .61, .36, 1);
}
.hero__headline.is-in .word__inner { transform: none; }

.hero__lede {
  margin: 0;
  font-size: 19px;
  line-height: 1.62;
  color: var(--text-on-dark-muted);
  max-width: 56ch;
}

/* ---------- Sections / shared blocks ---------- */

.section { background: var(--bg); padding: var(--section-padding) 0; }
.section--alt { background: var(--bg-alt); border-top: 1px solid rgba(0, 0, 0, .08); }
.section--dark { background: var(--bg-dark); color: var(--text-on-dark); }

.eyebrow {
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--label);
  font-weight: 500;
}
.eyebrow--on-dark { color: rgba(250, 250, 248, .5); }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.1fr);
  gap: 80px;
}

.lede {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(24px, 2.5vw, 36px);
  line-height: 1.3;
  letter-spacing: -.015em;
  text-wrap: pretty;
}

.body-text {
  margin: 0;
  font-size: 18px;
  line-height: 1.68;
  color: var(--text-muted);
  max-width: 64ch;
}
.body-text--on-dark { color: rgba(250, 250, 248, .66); }

h2.section-title {
  margin: 0 0 24px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(34px, 4.4vw, 64px);
  line-height: 1.06;
  letter-spacing: -.022em;
}

/* ---------- Capabilities ---------- */

.capabilities-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.1fr);
  gap: 80px;
  margin-bottom: 72px;
}
.capabilities-intro h2 {
  margin: 0;
  font-size: clamp(32px, 4vw, 58px);
  line-height: 1.08;
  letter-spacing: -.022em;
  color: var(--text);
  font-family: var(--font-display);
  font-weight: 400;
}

.capabilities-intro__text { display: flex; flex-direction: column; gap: 20px; margin-bottom: 28px; }

.capability__framing {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(19px, 1.8vw, 23px);
  line-height: 1.4;
  letter-spacing: -.01em;
}

.capabilities-list { border-top: 1px solid var(--border); }
.capability {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.9fr);
  gap: 80px;
  padding: 56px 0;
  border-bottom: 1px solid var(--border);
}
.capability__heading { display: flex; flex-direction: column; gap: 14px; }
.capability__heading h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 3vw, 42px);
  letter-spacing: -.02em;
}
.capability__body { display: flex; flex-direction: column; gap: 26px; max-width: 760px; }
.capability__services {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--border-soft);
}
.capability__services li {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 2px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 15px;
  letter-spacing: .01em;
  transition: padding-left .25s;
}
.capability__services li:hover { padding-left: 12px; }
/* hairline icons that match the 1px rules around them: 1.5 units in a 24 unit
   viewBox lands just above 1px once scaled down to 18px */
.svc-icon {
  flex: none;
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--label-soft);
  transition: color .25s;
}
.capability__services li:hover .svc-icon { color: var(--text); }

/* ---------- Work / case studies ---------- */

/* The cards and filters run on two grounds now: the dark band on the homepage
   and the light /work/ page. Rather than a second set of --on-dark rules, every
   colour below goes through these tokens. The light values are the default and
   .section--dark swaps them, so one set of rules serves both. */
.section {
  --work-title: var(--text);
  --work-body: var(--text-muted);
  --work-quiet: var(--label);
  --work-line: var(--border);
  --work-frame: rgba(0, 0, 0, .03);
  --work-pill-idle: var(--text-muted);
  --work-pill-hover-line: rgba(0, 0, 0, .34);
  --work-pill-on-bg: var(--text);
  --work-pill-on-fg: var(--bg);
}
.section--dark {
  --work-title: var(--text-on-dark);
  --work-body: rgba(250, 250, 248, .74);
  --work-quiet: rgba(250, 250, 248, .5);
  --work-line: var(--border-on-dark);
  --work-frame: rgba(250, 250, 248, .04);
  --work-pill-idle: rgba(250, 250, 248, .66);
  --work-pill-hover-line: rgba(250, 250, 248, .4);
  --work-pill-on-bg: var(--text-on-dark);
  --work-pill-on-fg: var(--bg-dark);
}

/* Two up on desktop. The cards carry a lot of copy, so the column gap is wide
   enough that two neighbouring paragraphs never read as one. */
.work-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 88px 56px;
  align-items: start;
}
.work-card { display: flex; flex-direction: column; gap: 32px; }
/* Filtered out. Kept in the DOM so the reveal state and images survive. */
.work-card[hidden] { display: none; }
.work-cta { margin-top: 72px; }

/* ---------- Work filters ---------- */

.work-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 56px;
  padding-bottom: 32px;
  border-bottom: 1px solid var(--work-line);
}
.work-filter {
  font: inherit;
  font-size: 14px;
  line-height: 1;
  color: var(--work-pill-idle);
  background: transparent;
  border: 1px solid var(--work-line);
  border-radius: 999px;
  padding: 11px 20px;
  cursor: pointer;
  transition: color .2s, background .2s, border-color .2s;
}
.work-filter:hover { color: var(--work-title); border-color: var(--work-pill-hover-line); }
.work-filter.is-active {
  background: var(--work-pill-on-bg);
  border-color: var(--work-pill-on-bg);
  color: var(--work-pill-on-fg);
}
.work-empty {
  margin: 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--work-body);
}
.work-empty a { color: var(--work-title); border-bottom: 1px solid var(--work-pill-hover-line); }
.work-empty a:hover { border-bottom-color: var(--work-title); }
.work-empty[hidden] { display: none; }
/* Sits in the slot the "Read the case study" link occupies on a published card,
   and carries the same box so the two cards line up. No underline: a dead rule
   under unlinked text reads as a link that has broken. Greyed a step below the
   body copy so it reads as a state rather than an action, at the same .5 the
   on-dark eyebrows use (5.1:1 on --bg-dark, so it still clears AA). Doubled up
   on the selector to outspecify .work-card__content p, which sets the same
   properties. */
.work-card__content .work-card__soon {
  align-self: start;
  margin-top: 8px;
  font-size: 16px;
  font-weight: 500;
  padding-bottom: 6px;
  color: var(--work-quiet);
}
.work-card__image {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--work-line);
  background: var(--work-frame);
}
.work-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* The hover-played animation, laid over the still it replaces. Added by
   initWorkMotion on first hover, so the file is never fetched for a visitor
   who does not ask for it. */
.work-card__motion {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .3s;
}
.work-card__motion.is-playing { opacity: 1; }
/* for case studies still awaiting artwork */
.work-card__image--placeholder {
  background-image: repeating-linear-gradient(135deg, rgba(250, 250, 248, .1) 0 1px, transparent 1px 11px);
  display: flex;
  align-items: flex-end;
  padding: 26px;
}
.work-card__image--placeholder span {
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: rgba(250, 250, 248, .62);
  background: rgba(10, 10, 10, .6);
  border: 1px solid rgba(250, 250, 248, .2);
  border-radius: 6px;
  padding: 8px 12px;
}
.work-card__body {
  display: flex;
  flex-direction: column;
  gap: 28px;
  padding-top: 28px;
  border-top: 1px solid var(--work-line);
}
.work-card__title {
  margin: 0;
  color: var(--work-title);
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(28px, 2.4vw, 38px);
  letter-spacing: -.02em;
}
.work-card__content { display: flex; flex-direction: column; gap: 22px; }
.work-card__content p { margin: 0; font-size: 17px; line-height: 1.66; color: var(--work-body); }
/* The case-study link takes its colour from the same tokens, so the card needs
   no --on-dark modifier and the markup is identical on both grounds. */
.work-card__content .link-arrow { color: var(--work-body); border-bottom-color: var(--work-line); }
.work-card__content .link-arrow:hover { color: var(--work-title); border-bottom-color: var(--work-title); }

/* ---------- Testimonials ---------- */

.testimonials { border-top: 1px solid var(--border); }
.testimonial {
  margin: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.1fr);
  gap: 80px;
  padding: 56px 0;
  border-bottom: 1px solid var(--border);
}
.testimonial__meta { display: flex; flex-direction: column; gap: 6px; }
.testimonial__meta img {
  width: 104px;
  height: 104px;
  margin-bottom: 14px;
  border-radius: 999px;
  object-fit: cover;
  filter: grayscale(1) contrast(1.05);
}
.testimonial__name { font-family: var(--font-display); font-size: 24px; letter-spacing: -.015em; }
.testimonial__role { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--label); font-weight: 500; }
.testimonial__project { font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--label-soft); font-weight: 500; }
.testimonial__quote {
  margin: 0;
  max-width: 820px;
  font-family: var(--font-display);
  font-size: clamp(24px, 2.6vw, 38px);
  line-height: 1.28;
  letter-spacing: -.015em;
  text-wrap: pretty;
}

/* ---------- Why Odenbridge ---------- */

.why-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border-top: 1px solid var(--border);
}
.why-grid__item {
  /* the outer edge padding is zeroed on each column so the text sits flush
     with the page gutter, like every other section */
  padding: 44px 56px 44px 0;
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.why-grid__item:nth-child(2n) { padding: 44px 0 44px 56px; border-right: 0; }
/* an odd final card sits alone on its row, so it spans the full width with the
   heading in the left column and the body in the right. The 112px gap is the
   two 56px gutters of the columns above it, so the text lines up. With an even
   number of cards the grid closes on its own and this never applies. */
.why-grid__item:nth-child(odd):last-child {
  grid-column: 1 / -1;
  border-right: 0;
  padding: 44px 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 112px;
  align-items: start;
}
.why-grid__item h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 2.2vw, 30px);
  line-height: 1.22;
  letter-spacing: -.018em;
  max-width: 24ch;
}
.why-grid__item p { margin: 0; font-size: 17px; line-height: 1.68; color: var(--text-muted); max-width: 52ch; }
/* ---------- Process (About page) ---------- */

.process-list { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border-soft); }
.process-item {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr) minmax(0, 1.6fr);
  gap: 40px;
  align-items: baseline;
  padding: 34px 12px;
  border-bottom: 1px solid var(--border-soft);
  transition: background .25s, padding-left .25s;
}
.process-item:hover { background: rgba(0, 0, 0, .035); padding-left: 24px; }
.process-item__num { font-size: 13px; letter-spacing: .1em; color: #8A8A82; }
.process-item h3 { margin: 0; font-family: var(--font-display); font-weight: 400; font-size: clamp(22px, 2.2vw, 30px); letter-spacing: -.015em; }
.process-item p { margin: 0; font-size: 17px; line-height: 1.62; color: var(--text-muted); max-width: 52ch; }

/* ---------- Beliefs (About page) ---------- */

.beliefs-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--border);
}
.belief {
  padding: 44px;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.belief:last-child { border-right: 0; }
.belief h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(22px, 2.1vw, 28px);
  line-height: 1.22;
  letter-spacing: -.018em;
}
.belief p { margin: 0; font-size: 17px; line-height: 1.66; color: var(--text-muted); }

/* ---------- Footer CTA ---------- */

.cta-footer {
  position: relative;
  overflow: hidden;
  background: var(--bg-dark);
  color: var(--text-on-dark);
  padding: 150px 0 48px;
}
.cta-footer__pattern {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: url('../assets/hero-pattern.jpg');
  background-size: cover;
  background-position: center;
  opacity: .07;
  mix-blend-mode: screen;
}
.cta-footer__inner { position: relative; z-index: 1; }
.cta-footer h2 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(44px, 7.4vw, 124px);
  line-height: 1;
  letter-spacing: -.03em;
  max-width: 15ch;
  text-wrap: pretty;
}
.cta-footer__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 56px;
  align-items: end;
  margin-top: 64px;
  padding-bottom: 110px;
}
.cta-footer__row p { margin: 0; font-size: 19px; line-height: 1.62; color: rgba(250, 250, 248, .7); max-width: 52ch; }
.cta-footer__cta {
  justify-self: end;
  gap: 14px;
  font-size: 16px;
  padding: 19px 33px;
  transition: background .25s, border-color .25s, color .25s, gap .25s;
}
.cta-footer__cta:hover { gap: 20px; }

.cta-footer__links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 28px;
  padding-bottom: 28px;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(250, 250, 248, .55);
}
.cta-footer__links a { transition: color .2s; }
.cta-footer__links a:hover { color: var(--text-on-dark); }

.cta-footer__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 28px;
  padding-top: 32px;
  border-top: 1px solid var(--border-on-dark);
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: rgba(250, 250, 248, .55);
}
.cta-footer__meta a { transition: color .2s; }
.cta-footer__meta a:hover { color: var(--text-on-dark); }
.cta-footer__copyright { margin-left: auto; }

/* ---------- Bottom sticky nav ---------- */

.bottom-nav {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: flex;
  justify-content: center;
  padding: 0 var(--gutter) 24px;
  pointer-events: none;
  opacity: 0;
  transform: translateY(140%);
  transition: opacity .35s ease, transform .45s cubic-bezier(.22, .61, .36, 1);
}
.bottom-nav.is-visible { pointer-events: auto; opacity: 1; transform: none; }
.bottom-nav__inner {
  display: flex;
  align-items: center;
  gap: 28px;
  background: rgba(10, 10, 10, .92);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(250, 250, 248, .18);
  padding: 12px 12px 12px 22px;
}
.bottom-nav__links { display: flex; align-items: center; gap: 26px; }
.bottom-nav__links a {
  font-size: 14px;
  color: rgba(250, 250, 248, .72);
  padding: 4px 0;
  border-bottom: 1px solid transparent;
  transition: color .2s, border-color .2s;
}
.bottom-nav__links a:hover,
.bottom-nav__links a.is-active {
  color: var(--text-on-dark);
  border-bottom-color: var(--text-on-dark);
}
.bottom-nav__cta {
  background: var(--text-on-dark);
  color: var(--bg-dark);
  font-size: 14px;
  font-weight: 500;
  padding: 11px 22px;
  white-space: nowrap;
  transition: background .2s;
}
.bottom-nav__cta:hover { background: #fff; }

/* ---------- Responsive ---------- */

@media (max-width: 1024px) {
  :root { --section-padding: 96px; }
  .split,
  .capabilities-intro,
  .capability,
  .testimonial,
  .cta-footer__row {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .why-grid,
  .beliefs-grid,
  .work-grid { grid-template-columns: 1fr; }
  .work-grid { gap: 72px; }
  .why-grid__item,
  .belief { border-right: 0; }
  /* stacked: both columns go full-bleed, so no inner gutter either side.
     Selector matches :nth-child(2n) specificity so it actually wins. */
  .why-grid__item,
  .why-grid__item:nth-child(2n) { padding: 44px 0; }
  /* an odd final card's side-by-side split stacks too */
  .why-grid__item:nth-child(odd):last-child { grid-template-columns: 1fr; gap: 18px; }
  .belief { border-bottom: 1px solid var(--border); }
  .belief:last-child { border-bottom: 0; }
  .process-item { grid-template-columns: 48px 1fr; }
  .process-item p { grid-column: 1 / -1; max-width: none; }
  .cta-footer__cta { justify-self: start; }
}

@media (max-width: 640px) {
  :root { --gutter: 24px; --section-padding: 72px; }
  .hero__headline { max-width: none; }
  .nav__links,
  .site-header .btn { display: none; }
  .nav__toggle { display: block; }
  .capability { gap: 24px; }
  .work-filters { gap: 8px; margin-bottom: 44px; }
  .work-filter { font-size: 13px; padding: 10px 16px; }
  .process-item { grid-template-columns: 1fr; gap: 8px; }
  .bottom-nav { padding: 0 16px 16px; }
  .bottom-nav__links { display: none; }
  .bottom-nav__inner { gap: 16px; }
}


/* ---------- Page transition ---------- */
/* A dark panel wipes upward over the outgoing page, the ODB mark spins like a
   slot machine, then the panel carries on in the same direction to uncover the
   next page. The mark is split into three reels, one per logo glyph: each reel
   is a clipped column holding a vertical strip of glyph copies, and spinning is
   just a translateY on that strip.

   The reel widths and aspect ratios come straight off the logo geometry. Each
   glyph keeps its own slice of the original 86x35 viewBox, so the three reels
   sitting flush side by side reproduce the header mark exactly. The viewBoxes
   are opened up vertically (y -1.5, height 37 against glyphs that span 0-34.07)
   so that no edge sits on the clipping boundary and picks up a shaved hairline.

   The incoming page has to paint with the panel already covering it, or the new
   page flashes before the panel lifts. That is what the inline script in <head>
   handles: it sets data-pt on <html> before the body renders, and the rules
   below dress the panel from the very first frame. It only sets that attribute
   when the transition should actually run, so with JS off — or under reduced
   motion — the panel is never shown at all. */
.pt {
  position: fixed;
  inset: 0;
  z-index: 200; /* above .nav-overlay (100) and .bottom-nav (60) */
  display: none;
  pointer-events: none;
}
[data-pt] .pt,
.pt.is-active { display: block; }

.pt__panel {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-dark);
  transform: translateY(100%);
  transition: transform .46s cubic-bezier(.65, 0, .35, 1);
  will-change: transform;
}
/* Covering: the state an incoming page paints in, and the state an outgoing
   page animates to. */
[data-pt] .pt__panel,
.pt__panel.is-covering { transform: none; }
/* Leaving: same direction again, travelling off the top. initPageTransition()
   swaps the attribute for classes before it ever adds this, but the rule is
   kept below the covering ones so it still wins on equal specificity. */
.pt__panel.is-leaving {
  transform: translateY(-100%);
  transition: transform .54s cubic-bezier(.65, 0, .35, 1);
}

.pt__mark {
  display: flex;
  align-items: flex-start;
  width: clamp(79px, 12vw, 139px);
}
/* aspect-ratio holds each reel to exactly one glyph tall; the rest of the strip
   overflows and is clipped. align-items:flex-start keeps the flex row from
   stretching them back out to match the tallest. */
.pt__reel { flex: none; overflow: hidden; min-height: 0; }
.pt__reel--o { width: 39.535%; aspect-ratio: 34.0721 / 37; }
.pt__reel--d,
.pt__reel--b { width: 30.232%; aspect-ratio: 26.055 / 37; }
.pt__strip { display: block; will-change: transform; }
.pt__glyph { display: block; width: 100%; height: auto; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  [data-reveal] { transition: none !important; }
  /* initHeroIntro() bails out before splitting, so these are belt-and-braces
     in case a split heading is ever rendered another way. */
  .hero__headline .word__inner { transform: none !important; transition: none !important; }
  /* The page transition never starts under reduced motion — the inline <head>
     script leaves data-pt unset and clicks navigate normally — but hide the
     panel outright in case it is ever activated another way. */
  .pt { display: none !important; }
}


/* ---------- Legal / policy pages ---------- */

/* Same column split as .split, but the left rail is a sticky table of contents
   rather than a one-line label, so it needs align-items:start to stick. */
.legal {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.1fr);
  gap: 80px;
  align-items: start;
}

.legal__toc { position: sticky; top: 40px; }
.legal__toc ol {
  list-style: none;
  margin: 22px 0 0;
  padding: 0;
  border-top: 1px solid var(--border-soft);
}
.legal__toc li { border-bottom: 1px solid var(--border-soft); }
.legal__toc a {
  display: flex;
  gap: 14px;
  padding: 10px 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--text-muted);
  transition: color .2s, padding-left .2s;
}
.legal__toc a:hover { color: var(--text); padding-left: 8px; }
.legal__toc-num { flex: none; width: 18px; font-size: 12px; color: var(--label-soft); }

.legal__body {
  display: flex;
  flex-direction: column;
  gap: 72px;
  max-width: 800px;
  /* the wide table's min-width would otherwise set this column's floor */
  min-width: 0;
}

.legal-section {
  /* clears the sticky-free header but keeps anchor jumps off the very edge */
  scroll-margin-top: 40px;
}
.legal-section__num {
  display: block;
  margin-bottom: 14px;
  font-size: 12px;
  letter-spacing: .1em;
  color: var(--label-soft);
}
.legal-section h2 {
  margin: 0 0 22px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(26px, 2.8vw, 38px);
  line-height: 1.12;
  letter-spacing: -.02em;
}
.legal-section h3 {
  margin: 36px 0 14px;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 21px;
  letter-spacing: -.012em;
  color: var(--text);
}
.legal-section p {
  margin: 0 0 18px;
  font-size: 17px;
  line-height: 1.72;
  color: var(--text-muted);
}
.legal-section > p:last-child,
.legal-section p:last-child { margin-bottom: 0; }
.legal-section strong { color: var(--text); font-weight: 500; }

.legal-link {
  color: var(--text);
  border-bottom: 1px solid var(--border);
  transition: border-color .2s;
}
.legal-link:hover { border-bottom-color: var(--text); }

.legal-list {
  list-style: none;
  margin: 0 0 18px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.legal-list li {
  position: relative;
  padding-left: 24px;
  font-size: 17px;
  line-height: 1.72;
  color: var(--text-muted);
}
.legal-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .82em;
  width: 10px;
  height: 1px;
  background: var(--label-soft);
}
.legal-list--numbered { counter-reset: legal-item; }
.legal-list--numbered li { counter-increment: legal-item; padding-left: 34px; }
.legal-list--numbered li::before {
  content: counter(legal-item, decimal-leading-zero);
  top: 0;
  width: auto;
  height: auto;
  background: none;
  font-size: 12px;
  line-height: 2.45;
  color: var(--label-soft);
}
.legal-list__lead { color: var(--text); font-weight: 500; }

.legal-note {
  margin: 0 0 18px;
  padding: 26px 30px;
  background: var(--bg-alt);
  border-left: 1px solid var(--border);
}
.legal-note .eyebrow { display: block; margin-bottom: 14px; }
.legal-note .legal-list { margin-bottom: 0; }

/* Wide table: scrolls inside its own box so the page body never does. */
.legal-table-wrap {
  margin: 0 0 18px;
  overflow-x: auto;
  border-top: 1px solid var(--border);
  /* a flex item defaults to min-width:auto, which would size this to the
     table's 640px min-width and push the overflow onto the page instead of
     keeping it inside this box */
  min-width: 0;
}
.legal-table {
  width: 100%;
  min-width: 640px;
  border-collapse: collapse;
  text-align: left;
}
.legal-table th {
  padding: 16px 24px 16px 0;
  vertical-align: top;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--label);
  border-bottom: 1px solid var(--border);
}
.legal-table td {
  padding: 20px 24px 20px 0;
  vertical-align: top;
  font-size: 15px;
  line-height: 1.62;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-soft);
}
.legal-table td:first-child { color: var(--text); }
.legal-table th:last-child,
.legal-table td:last-child { padding-right: 0; }
.legal-table tr:last-child td { border-bottom: 0; }

.legal-contact {
  margin-top: 26px;
  padding-top: 26px;
  border-top: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.legal-contact a { font-family: var(--font-display); font-size: 24px; letter-spacing: -.015em; }
.legal-contact a:hover { color: var(--text-muted); }

@media (max-width: 1024px) {
  /* minmax(0, 1fr), not 1fr: a bare 1fr floors at min-content, so the wide
     table inside would widen the whole column rather than scroll in place. */
  .legal { grid-template-columns: minmax(0, 1fr); gap: 40px; }
  .legal__toc { position: static; }
  .legal__toc ol {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 40px;
    border-bottom: 1px solid var(--border-soft);
  }
  .legal__body { gap: 56px; }
}

@media (max-width: 640px) {
  .legal__toc ol { grid-template-columns: 1fr; }
  .legal-note { padding: 22px 24px; }
}

/* Styled like .eyebrow but deliberately not that class: initHeroIntro() claims
   the hero's .eyebrow as the first beat of the opening sequence, and this line
   sits below the lede — animating it first would run the hero bottom-up. */
.hero__updated {
  margin: 0;
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  font-weight: 500;
  color: rgba(250, 250, 248, .5);
}

/* ---------- Figure with source caption ---------- */

/* sits as the last item of a flex column, so the column's gap does most of
   the spacing work — this only tops it up. */
.figure { margin: 16px 0 0; }
.figure img {
  width: 100%;
  height: auto;
  border-radius: 14px;
  border: 1px solid var(--border-soft);
}
.figure figcaption {
  margin-top: 20px;
  font-size: 13px;
  line-height: 1.62;
  color: var(--label);
  max-width: 70ch;
}
.figure figcaption a {
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-soft);
  transition: color .2s, border-color .2s;
}
.figure figcaption a:hover { color: var(--text); border-bottom-color: var(--text); }

/* ---------- 404 ---------- */

/* Nothing follows the hero on this page, so the dark block has to carry the
   whole viewport — otherwise the page ends a few dozen pixels short and leaves
   a strip of the light body background under it. The header keeps its natural
   height and the hero takes the remainder. */
.hero-block--full {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}
.hero-block--full .hero {
  flex: 1;
  min-height: 0;
}

.notfound-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px 28px;
  margin-top: 44px;
}
.notfound-links a:not(.btn) {
  font-size: 14px;
  letter-spacing: .01em;
  color: var(--text-on-dark-muted);
  padding-bottom: 3px;
  border-bottom: 1px solid transparent;
  transition: color .2s, border-color .2s;
}
.notfound-links a:not(.btn):hover {
  color: var(--text-on-dark);
  border-bottom-color: var(--text-on-dark);
}
.notfound-links .btn { margin-right: 12px; }

/* ---------- Case study ---------- */

/* Meta bar under the case-study hero. Sits inside the dark hero block, so it
   borrows the on-dark tokens. auto-fit rather than a fixed column count: the
   number of credited disciplines varies per project and the row should close
   itself rather than leave a gap where a fifth item would have gone. */
.cs-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 30px 40px;
  margin: 60px 0 0;
  padding-top: 34px;
  border-top: 1px solid var(--border-on-dark);
}
.cs-meta > div { display: flex; flex-direction: column; gap: 10px; }
.cs-meta dt {
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--label-soft);
}
.cs-meta dd { margin: 0; font-size: 16px; line-height: 1.5; color: var(--text-on-dark); }

/* Asset placeholders.
   Every image on this page is a slot waiting for a real asset. A blank grey box
   would ship as an unidentifiable hole, so each placeholder states what belongs
   in it — when the screens arrive, the label is the brief for cropping them.
   Delete the class and drop in an <img> with the same aspect ratio. */
.cs-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 24px;
  border-radius: 14px;
  border: 1px dashed var(--border);
  background-color: var(--bg-alt);
  background-image: repeating-linear-gradient(135deg, rgba(0, 0, 0, .05) 0 1px, transparent 1px 12px);
  color: var(--label);
}
.cs-ph span {
  max-width: 32ch;
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: .1em;
  text-transform: uppercase;
}
.cs-ph--wide { aspect-ratio: 16 / 9; }
.cs-ph--screen { aspect-ratio: 10 / 19; }
.cs-ph--doc { aspect-ratio: 3 / 4; }
.cs-ph--map { aspect-ratio: 21 / 10; }
.cs-ph--on-dark {
  border-color: var(--border-on-dark);
  background-color: rgba(250, 250, 248, .04);
  background-image: repeating-linear-gradient(135deg, rgba(250, 250, 248, .09) 0 1px, transparent 1px 12px);
  color: var(--text-on-dark-muted);
}

/* A placeholder that holds a paragraph of brief rather than a one-line caption:
   no fixed ratio, and set as running text instead of as a caps label. */
.cs-ph--note {
  aspect-ratio: auto;
  max-width: 76ch;
  padding: 44px;
  text-align: left;
  justify-content: flex-start;
}
.cs-ph--note span {
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.7;
  letter-spacing: normal;
  text-transform: none;
}

/* Screen sets. Phone screens are tall, so three across is the most that stays
   legible at container width; two for a before/after pair. */
.cs-screens {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  margin-top: 40px;
}
.cs-screens--two { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cs-screens figcaption,
.cs-figcaption {
  margin-top: 18px;
  font-size: 13px;
  line-height: 1.62;
  color: var(--label);
  max-width: 70ch;
}

/* Decisions — the spine of the piece. Numbered like the About page process
   list, but each one carries its own screens, so it is a block rather than a
   table row: heading in the left column, argument and evidence below it,
   indented to the heading's text edge so the number column reads as a margin. */
.cs-decisions { border-top: 1px solid var(--border); }
.cs-decision { border-bottom: 1px solid var(--border); padding: 56px 0; }
.cs-decision__head {
  display: grid;
  grid-template-columns: 120px minmax(0, 1fr);
  gap: 40px;
  align-items: baseline;
}
.cs-decision__num { font-size: 13px; letter-spacing: .1em; color: #8A8A82; }
.cs-decision__head h3 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(24px, 2.7vw, 38px);
  line-height: 1.16;
  letter-spacing: -.02em;
  max-width: 24ch;
}
.cs-decision__body {
  margin: 26px 0 0 160px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.cs-decision__body p { margin: 0; font-size: 18px; line-height: 1.68; color: var(--text-muted); max-width: 62ch; }

/* Pull quote. These are merchants' own words and they are the evidence the
   piece rests on, so they get display type rather than being folded into a
   paragraph. Attribution is by trade and town — never by name. */
.cs-quote { margin: 0; }
.cs-quote blockquote {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(23px, 3vw, 40px);
  line-height: 1.26;
  letter-spacing: -.02em;
  max-width: 20ch;
}
.cs-quote--wide blockquote { max-width: 26ch; }
.cs-quote figcaption {
  margin-top: 26px;
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--label);
}
.cs-quote--on-dark blockquote { color: var(--text-on-dark); }
.cs-quote--on-dark figcaption { color: var(--label-soft); }

/* Caveat block. Used once, for the courtesy-bias note — a claim against our own
   evidence needs to look deliberate, not like body copy that wandered off. */
.cs-note {
  margin-top: 52px;
  padding: 30px 34px;
  border-left: 2px solid var(--border);
  background: var(--bg-alt);
  border-radius: 0 12px 12px 0;
}
.cs-note p { margin: 0; font-size: 16px; line-height: 1.7; color: var(--text-muted); max-width: 66ch; }

/* Scope counts and outcome figures. */
.cs-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 40px;
  margin-top: 56px;
  padding-top: 40px;
  border-top: 1px solid var(--border-on-dark);
}
.cs-stat__num {
  display: block;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(38px, 4.4vw, 60px);
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--text-on-dark);
}
.cs-stat__label {
  display: block;
  margin-top: 16px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-on-dark-muted);
  max-width: 26ch;
}

/* Foot of the piece: credits, then the way on to the next case study. */
.cs-credits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 34px 40px;
  margin: 0;
  padding-top: 40px;
  border-top: 1px solid var(--border);
}
.cs-credits > div { display: flex; flex-direction: column; gap: 10px; }
.cs-credits dt {
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--label);
}
.cs-credits dd { margin: 0; font-size: 16px; line-height: 1.55; color: var(--text); }


/* ---------- Case study: light hero ---------- */

/* Case studies open on white. The rest of the site leads with the dark block
   because the first thing it has to say is who we are; here the first thing is
   the work, and a black band above it turns the opening screen back into brand
   furniture. Inverting the background means inverting every on-dark token the
   header and hero borrow — nav, logo, button, meta bar — so they are collected
   here rather than left to the defaults further up. */
.hero-block--light { background: var(--bg); }
.hero-block--light .hero { color: var(--text); }
.hero-block--light .hero__lede { color: var(--text-muted); }

/* The logo and burger carry currentColor in this page's markup, so the colour
   comes from here rather than from a hard-coded fill in the SVG. */
.hero-block--light .nav__logo,
.hero-block--light .nav__toggle { color: var(--text); }
.hero-block--light .nav__link { color: var(--text-muted); }
.hero-block--light .nav__link:hover,
.hero-block--light .nav__link.is-active {
  color: var(--text);
  border-bottom-color: var(--text);
}
.hero-block--light .btn { border-color: rgba(0, 0, 0, .3); color: var(--text); }
.hero-block--light .btn:hover {
  background: var(--text);
  color: var(--bg);
  border-color: var(--text);
}

.hero-block--light .cs-meta { border-top-color: var(--border); }
.hero-block--light .cs-meta dt { color: var(--label); }
.hero-block--light .cs-meta dd { color: var(--text); }

/* A document hero rather than a viewport-filling one. .hero is a flex box with
   a dvh min-height that bottom-aligns its contents — right for a landing page
   that opens on a single line of type, wrong for a masthead with a six-item
   meta list under it, which should simply start at the top and take the height
   it needs. */
.hero--doc {
  display: block;
  min-height: 0;
  /* No bottom padding: the section below opens with the full --section-padding,
     and adding to it here would leave a hole between the meta bar and the first
     image that no other gap on the page matches. */
  padding: 72px 0 0;
}
.hero--doc .hero__headline { margin-top: 30px; }
.hero--doc .hero__lede {
  margin-top: 32px;
  font-size: clamp(19px, 1.5vw, 22px);
  max-width: 52ch;
}

/* ---------- Case study: type scale ---------- */

/* One scale for the whole piece. Before this, every section heading carried its
   own inline clamp() and the running text arrived at five different measures
   (800px, 64ch, 62ch, 58ch, 52ch) with eight different gaps between
   paragraphs. Two measures now: --cs-measure for a prose column that owns the
   full content width, --cs-measure-tight for text that sits in a grid cell or
   under a heading. The column owns the measure, not each paragraph. */
.cs-page {
  --cs-measure: 66ch;
  --cs-measure-tight: 58ch;
  --cs-para-gap: 26px;
}

/* Section header: eyebrow in the margin column, heading and optional
   standfirst in the main one. Replaces .split plus a per-section inline
   margin-bottom that was 48px, 56px or 64px depending on the section. */
.cs-head { margin-bottom: 64px; }
.cs-head__main { display: flex; flex-direction: column; gap: 24px; }

/* Text that follows a section header has to start on the same left edge as the
   heading it belongs to, not at the container gutter — otherwise the running
   text jumps between two left edges as you scroll. Same grid as .split, with
   everything in the second column, so the two are guaranteed to line up.
   Images stay outside it and run the full container width. */
.cs-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2.1fr);
  gap: 80px;
}
.cs-body > * { grid-column: 2; }
/* A section with no heading of its own (Context) puts its eyebrow straight into
   the margin column, so it lines up with the ones that do. */
.cs-body > .eyebrow { grid-column: 1; }

.cs-title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(30px, 3.6vw, 52px);
  line-height: 1.1;
  letter-spacing: -.022em;
  max-width: 22ch;
  text-wrap: pretty;
}

/* The sentence that sits under a section heading and sets up what follows.
   Same size as body copy, so it reads as the first paragraph rather than as a
   third level of heading. */
.cs-standfirst {
  margin: 0;
  font-size: 18px;
  line-height: 1.68;
  color: var(--text-muted);
  max-width: var(--cs-measure-tight);
}

/* Running prose. Everything inside inherits the column's measure — the
   per-element max-widths on .body-text and friends are cleared so there is one
   place the line length is decided. .lede is display type and needs a much
   shorter line than 66ch of 18px text, so it keeps its own. */
.cs-prose {
  display: flex;
  flex-direction: column;
  gap: var(--cs-para-gap);
  max-width: var(--cs-measure);
}
.cs-prose > * { max-width: none; }
.cs-prose .lede { max-width: 24ch; }
.cs-prose strong { color: var(--text); font-weight: 500; }

/* .why-grid is shared with the home page, where its cells sit at 17px. Here it
   carries findings that read as body copy, so it joins the rest of the running
   text at 18px rather than being the one paragraph size that is different. */
.cs-page .why-grid__item p { font-size: 18px; }

/* Figures sit between prose blocks and need the same clearance wherever they
   appear, rather than the 36px / 40px / 48px the inline styles were using. */
/* The Design section opens with the uplift itself before the numbered list, so
   its intro block and figure have to clear the decisions below them. */
.cs-body--intro { margin-bottom: 56px; }
.cs-figure--intro { margin-bottom: 64px; }
.cs-figure { margin: 56px 0 0; }
.cs-figure:first-child { margin-top: 0; }
/* With the copy cut back to a few sentences, the screens are the argument. A
   figure inside a decision pulls back out of the body's text indent and runs
   the full container width, so the type sits in a column and the work does not. */
.cs-decision__body .cs-figure { margin-top: 40px; margin-left: -160px; }

/* The hero image runs straight into the section below it. */
.section--flush-bottom { padding-bottom: 0; }

@media (max-width: 1024px) {
  .cs-decision__head { grid-template-columns: 90px minmax(0, 1fr); gap: 28px; }
  .cs-decision__body { margin-left: 118px; }
  .cs-decision__body .cs-figure { margin-left: -118px; }
  .cs-screens { gap: 18px; }
  /* The eyebrow column collapses at this width, so the heading no longer has a
     margin beside it and can take the full measure. */
  .cs-head { margin-bottom: 48px; }
  .cs-body { grid-template-columns: minmax(0, 1fr); gap: 24px; }
  .cs-body > *,
  .cs-body > .eyebrow { grid-column: 1; }
  .cs-title { max-width: 26ch; }
  .hero--doc { padding: 56px 0 72px; }
}

@media (max-width: 640px) {
  .cs-meta { gap: 24px 28px; margin-top: 44px; }
  .cs-page { --cs-para-gap: 22px; }
  .cs-head { margin-bottom: 40px; }
  .cs-title { max-width: none; }
  .cs-prose .lede { max-width: none; }
  .cs-figure { margin-top: 40px; }
  .hero--doc { padding: 40px 0 56px; }
  .hero--doc .hero__headline { margin-top: 22px; }
  .hero--doc .hero__lede { margin-top: 24px; }
  .cs-decision { padding: 40px 0; }
  .cs-decision__head { grid-template-columns: 1fr; gap: 12px; }
  .cs-decision__head h3 { max-width: none; }
  .cs-decision__body { margin-left: 0; }
  .cs-decision__body .cs-figure { margin-left: 0; }
  .cs-quote blockquote,
  .cs-quote--wide blockquote { max-width: none; }
  /* Three tall phones at phone width leaves each about 90px across, which is
     unreadable. One per row, full width. */
  .cs-screens,
  .cs-screens--two { grid-template-columns: 1fr; gap: 20px; }
  .cs-note { padding: 24px 22px; }
}
