/* ==========================================================================
   Externo - Homepage  (xo-*)

   Dark editorial rebuild. Ink canvas, gold accent, one cream chapter.
   The page argues from proof: real project imagery leads, capability
   follows. Loads after style.css and only touches xo-* classes (plus a
   handful of explicit overrides for the shared footer and the legacy
   booking-button class), so every other page is untouched.

   Order: tokens → base → primitives → header → hero → proof → clients
        → work → impact → light chapter (do + process) → journal
        → start → footer bridge → motion/responsive
   ========================================================================== */

/* ------------------------------------------------------------------ tokens */
:root {
  /* ink family - the page canvas and its raised surfaces */
  --xo-ink: #0b0b0d;
  --xo-ink-2: #101013;
  --xo-ink-3: #16161a;
  --xo-ink-4: #1e1e24;

  /* foreground on ink */
  --xo-snow: #f6f4f1;
  --xo-dim: rgba(246, 244, 241, 0.66);
  --xo-faint: rgba(246, 244, 241, 0.42);
  --xo-line: rgba(246, 244, 241, 0.13);
  --xo-line-soft: rgba(246, 244, 241, 0.07);

  /* brand */
  --xo-gold: #ffc13d;
  --xo-gold-deep: #f2a900;
  --xo-cream: #fff6e6;

  /* light chapter */
  --xo-lite: #fff6e6;
  --xo-lite-ink: #0e0e0e;
  --xo-lite-dim: #575c63;
  --xo-lite-line: rgba(14, 14, 14, 0.15);
  --xo-lite-line-soft: rgba(14, 14, 14, 0.08);

  /* type */
  --xo-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  --xo-body: "Urbanist", ui-sans-serif, system-ui, sans-serif;

  /* metrics */
  --xo-gutter: clamp(20px, 4.2vw, 72px);
  --xo-max: 1500px;
  /* Bands stack directly on each other, so the visible gap between two
     sections is twice this. Tuned so that gap lands near 180px, not 300. */
  --xo-band: clamp(56px, 6.2vw, 104px);
  --xo-radius: 18px;
  --xo-radius-sm: 12px;
  --xo-header-h: 88px;

  /* motion */
  --xo-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --xo-ease-io: cubic-bezier(0.76, 0, 0.24, 1);

  /* the injected page-veil scrollbar reads these */
  --xo-sb-track: #0b0b0d;
  --xo-sb-thumb: #f2a900;
}

/* -------------------------------------------------------------------- base */
html.xo-home {
  background: var(--xo-ink);
  scroll-padding-top: calc(var(--xo-header-h) + 24px);
}

body.xo-body {
  margin: 0;
  background: var(--xo-ink);
  color: var(--xo-snow);
  font-family: var(--xo-body);
  font-size: 17px;
  line-height: 1.6;
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* style.css's global `img { display:block }` outranks the UA [hidden] rule */
body.xo-body [hidden] {
  display: none !important;
}

body.xo-body ::selection {
  background: var(--xo-gold);
  color: #0b0b0d;
}

body.xo-body :focus-visible {
  outline: 2px solid var(--xo-gold);
  outline-offset: 3px;
  border-radius: 4px;
}

/* Inline SVG with only a viewBox has no intrinsic size and falls back to
   300x150, which silently blows apart any flex row it sits in. Every icon
   here is sized by its own rule; this is the floor under all of them. */
:where(body.xo-body svg:not([width]):not([height])) {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
}

.xo-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.xo-skip {
  position: absolute;
  z-index: 100;
  top: 10px;
  left: 10px;
  padding: 12px 20px;
  border-radius: 999px;
  background: var(--xo-gold);
  color: #0b0b0d;
  font: 700 14px/1 var(--xo-body);
  transform: translateY(-160%);
  transition: transform 0.25s var(--xo-ease);
}

.xo-skip:focus-visible {
  transform: translateY(0);
}

/* -------------------------------------------------------------- primitives */
.xo-shell {
  width: min(100% - var(--xo-gutter) * 2, var(--xo-max));
  margin-inline: auto;
}

.xo-band {
  position: relative;
  padding-block: var(--xo-band);
}

/* every ink section shares the canvas; only these two lift off it */
.xo-band-raised {
  background: var(--xo-ink-2);
}

.xo-band-lite {
  background: var(--xo-lite);
  color: var(--xo-lite-ink);
}

.xo-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  color: var(--xo-gold);
  font: 700 12px/1 var(--xo-body);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.xo-eyebrow::before {
  width: 22px;
  height: 1px;
  background: currentColor;
  content: "";
}

.xo-band-lite .xo-eyebrow {
  color: #8f6400; /* AA-safe gold on cream */
}

/* --- section head: eyebrow, title, lede, side link -----------------------
   Both tracks are minmax(0, …): an `auto` second column would take its
   max-content width and starve the title into one word per line. */
.xo-head {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  align-items: end;
  gap: 28px clamp(32px, 4vw, 72px);
  padding-bottom: clamp(40px, 5vw, 76px);
}

/* No ch-based cap here: `ch` would resolve against this element's inherited
   body size, not the display size of the title inside it, and crush the
   column. The grid track above is the measure. */
.xo-head-copy {
  min-width: 0;
}

.xo-head-lede {
  max-width: 46ch;
  margin: 18px 0 0;
  color: var(--xo-dim);
  font-size: clamp(1rem, 1.15vw, 1.15rem);
  line-height: 1.62;
}

.xo-band-lite .xo-head-lede {
  color: var(--xo-lite-dim);
}

/* the "All projects →" style link that closes a section head */
.xo-head-cta {
  margin: 20px 0 0;
}

.xo-title {
  margin: 20px 0 0;
  font-family: var(--xo-display);
  font-size: clamp(2.15rem, 4.4vw, 4.1rem);
  font-weight: 500;
  line-height: 1.02;
  letter-spacing: -0.032em;
  text-wrap: balance;
}

/* --- links --------------------------------------------------------------- */
.xo-link {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding-bottom: 6px;
  color: inherit;
  font: 700 15px/1 var(--xo-body);
  white-space: nowrap;
}

.xo-link::after {
  position: absolute;
  right: 0;
  bottom: 0;
  left: 0;
  height: 1px;
  background: currentColor;
  opacity: 0.28;
  content: "";
  transition: opacity 0.3s var(--xo-ease);
}

.xo-link:hover::after,
.xo-link:focus-visible::after {
  opacity: 1;
}

.xo-link svg {
  width: 15px;
  height: 15px;
  transition: transform 0.35s var(--xo-ease);
}

.xo-link:hover svg {
  transform: translateX(5px);
}

/* --- buttons ------------------------------------------------------------- */
.xo-btn {
  position: relative;
  display: inline-flex;
  width: auto;
  height: auto;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 18px 32px;
  border: 1.5px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  font: 700 15px/1 var(--xo-body);
  letter-spacing: 0.005em;
  text-align: center;
  cursor: pointer;
  isolation: isolate;
  overflow: hidden;
  transition: color 0.35s var(--xo-ease), border-color 0.35s var(--xo-ease),
    background-color 0.35s var(--xo-ease);
  will-change: transform;
}

.xo-btn > span {
  position: relative;
  z-index: 2;
}

/* the wipe that fills each button from the bottom on hover */
.xo-btn::before {
  position: absolute;
  z-index: 1;
  inset: 0;
  background: var(--xo-btn-fill, var(--xo-gold));
  transform: translateY(101%);
  content: "";
  transition: transform 0.45s var(--xo-ease-io);
}

.xo-btn:hover::before,
.xo-btn:focus-visible::before {
  transform: translateY(0);
}

.xo-btn-gold {
  background: var(--xo-gold);
  border-color: var(--xo-gold);
  color: #0b0b0d;
  --xo-btn-fill: #fff;
}

.xo-btn-gold:hover,
.xo-btn-gold:focus-visible {
  border-color: #fff;
}

.xo-btn-ghost {
  border-color: var(--xo-line);
  color: var(--xo-snow);
  --xo-btn-fill: var(--xo-snow);
}

.xo-btn-ghost:hover,
.xo-btn-ghost:focus-visible {
  border-color: var(--xo-snow);
  color: #0b0b0d;
}

.xo-btn-ink {
  background: #0b0b0d;
  border-color: #0b0b0d;
  color: var(--xo-snow);
  --xo-btn-fill: var(--xo-gold);
}

.xo-btn-ink:hover,
.xo-btn-ink:focus-visible {
  color: #0b0b0d;
}

/* the legacy booking-modal class ships its own width/height/skin - neutralise
   it wherever it rides along with .xo-btn (the trigger is delegated in
   script.js, so the class has to stay on the element). */
.xo-btn.ext-capsule-meet-btn {
  display: inline-flex;
  width: auto;
  height: auto;
  font-family: var(--xo-body);
  font-size: 15px;
  font-weight: 700;
  transition: color 0.35s var(--xo-ease), border-color 0.35s var(--xo-ease),
    background-color 0.35s var(--xo-ease);
}

.xo-btn.ext-capsule-meet-btn:hover {
  transform: none; /* GSAP owns the magnetic drift */
}

.xo-btn-gold.ext-capsule-meet-btn {
  background: var(--xo-gold);
  border-color: var(--xo-gold);
  color: #0b0b0d;
}

.xo-btn-gold.ext-capsule-meet-btn:hover {
  background: var(--xo-gold);
  border-color: #fff;
}

.xo-btn-ink.ext-capsule-meet-btn,
.xo-btn-ink.ext-capsule-meet-btn:hover {
  background: #0b0b0d;
  border-color: #0b0b0d;
}

/* ------------------------------------------------------------------ header */
.xo-header {
  position: fixed;
  z-index: 60;
  top: 0;
  right: 0;
  left: 0;
  display: flex;
  height: var(--xo-header-h);
  align-items: center;
  justify-content: space-between;
  /* Must resolve to the same left edge as .xo-shell. The shell is
     min(100% - 2*gutter, --xo-max) centred, so its inset is the gutter while
     the viewport is narrow and the centring offset once it is wider. Adding
     the gutter on top of that offset (as this once did) pushed the header a
     full gutter inside the content on screens above --xo-max. */
  padding-inline: max(var(--xo-gutter), (100% - var(--xo-max)) / 2);
  transition: transform 0.5s var(--xo-ease), background-color 0.4s ease,
    border-color 0.4s ease, height 0.4s var(--xo-ease);
  border-bottom: 1px solid transparent;
}

.xo-header.is-scrolled {
  height: 72px;
  background: rgba(11, 11, 13, 0.72);
  border-bottom-color: var(--xo-line-soft);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
}

.xo-header.is-hidden {
  transform: translateY(-102%);
}

/* over the cream chapter the bar flips to ink-on-light */
.xo-header.is-lite.is-scrolled {
  background: rgba(255, 246, 230, 0.78);
  border-bottom-color: var(--xo-lite-line-soft);
}

.xo-header-logo {
  position: relative;
  display: block;
  line-height: 0;
}

.xo-header-logo img {
  width: 124px;
  height: auto;
  transition: opacity 0.3s ease;
}

.xo-logo-snow {
  position: absolute;
  top: 0;
  left: 0;
}

/* white wordmark by default (ink page); ink wordmark over the cream chapter */
.xo-logo-ink {
  opacity: 0;
}

.xo-header.is-lite .xo-logo-ink {
  opacity: 1;
}

.xo-header.is-lite .xo-logo-snow {
  opacity: 0;
}

.xo-header-tools {
  display: flex;
  align-items: center;
  gap: 12px;
}

.xo-header-hire {
  padding: 13px 24px;
}

.xo-menu-toggle {
  position: relative;
  display: grid;
  width: 48px;
  height: 48px;
  place-items: center;
  padding: 0;
  border: 1.5px solid var(--xo-line);
  border-radius: 50%;
  background: transparent;
  color: var(--xo-snow);
  cursor: pointer;
  transition: border-color 0.3s ease, background-color 0.3s ease, color 0.3s ease;
  will-change: transform;
}

.xo-header.is-lite .xo-menu-toggle {
  border-color: var(--xo-lite-line);
  color: var(--xo-lite-ink);
}

.xo-menu-toggle:hover {
  border-color: var(--xo-gold);
  background: var(--xo-gold);
  color: #0b0b0d;
}

.xo-menu-box {
  display: grid;
  width: 18px;
  gap: 5px;
}

.xo-menu-box span {
  display: block;
  height: 1.5px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 0.3s var(--xo-ease);
}

.xo-menu-toggle:hover .xo-menu-box span:first-child {
  transform: translateX(3px);
}

.xo-menu-toggle:hover .xo-menu-box span:last-child {
  transform: translateX(-3px);
}

/* --- scroll progress ----------------------------------------------------- */
.xo-progress {
  position: fixed;
  z-index: 61;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: var(--xo-gold);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

/* -------------------------------------------------------------------- hero */
.xo-hero {
  position: relative;
  padding-top: calc(var(--xo-header-h) + clamp(56px, 8vw, 116px));
  padding-bottom: clamp(56px, 7vw, 104px);
  overflow: hidden;
}

.xo-hero-bg {
  position: absolute;
  z-index: 0;
  inset: 0;
  pointer-events: none;
}

/* fine dot lattice, fading out downward */
.xo-hero-bg::before {
  position: absolute;
  inset: 0;
  background-image: radial-gradient(rgba(246, 244, 241, 0.13) 1px, transparent 1px);
  background-size: 34px 34px;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
  mask-image: linear-gradient(180deg, #000 0%, transparent 78%);
  content: "";
}

/* warm glow behind the headline */
.xo-hero-bg::after {
  position: absolute;
  top: -28%;
  right: -10%;
  width: min(1100px, 90vw);
  height: min(1100px, 90vw);
  background: radial-gradient(
    circle,
    rgba(255, 193, 61, 0.16) 0%,
    rgba(255, 193, 61, 0.05) 42%,
    transparent 68%
  );
  content: "";
}

/* the brand mark, cropped off the right edge */
.xo-hero-mark {
  position: absolute;
  z-index: 0;
  top: 50%;
  right: calc(var(--xo-gutter) * -1);
  width: clamp(320px, 34vw, 560px);
  color: var(--xo-snow);
  opacity: 0.05;
  transform: translateY(-54%);
  pointer-events: none;
}

.xo-hero-mark svg {
  display: block;
  width: 100%;
  height: auto;
}

.xo-hero-inner {
  position: relative;
  z-index: 1;
}

.xo-hero-title {
  max-width: 15ch;
  margin: clamp(22px, 2.4vw, 34px) 0 0;
  font-family: var(--xo-display);
  font-size: clamp(3rem, 8vw, 7.4rem);
  font-weight: 500;
  line-height: 0.96;
  letter-spacing: -0.042em;
}

/* the gold word, with the brand scribble beneath it */
.xo-hl {
  position: relative;
  display: inline-block;
  color: var(--xo-gold);
  font-style: normal;
}

.xo-scribble {
  position: absolute;
  right: 0;
  bottom: -0.14em;
  left: 0;
  width: 100%;
  height: 0.16em;
  color: var(--xo-gold-deep);
  overflow: visible;
}

.xo-scribble path {
  stroke-dasharray: 240;
  stroke-dashoffset: 240;
}

.xo-hero-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
  align-items: end;
  gap: 36px clamp(40px, 6vw, 110px);
  margin-top: clamp(34px, 4vw, 56px);
}

.xo-hero-sub {
  max-width: 44ch;
  margin: 0;
  color: var(--xo-dim);
  font-size: clamp(1.05rem, 1.35vw, 1.32rem);
  line-height: 1.58;
}

.xo-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: flex-start;
}

/* ------------------------------------------------------------- proof rail */
.xo-proof {
  position: relative;
  z-index: 1;
  margin-top: clamp(48px, 6vw, 88px);
}

.xo-proof-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--xo-line-soft);
  margin-bottom: 22px;
}

.xo-proof-label {
  margin: 0;
  color: var(--xo-faint);
  font: 700 12px/1 var(--xo-body);
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

.xo-proof-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
}

.xo-proof-card {
  display: block;
  color: inherit;
}

.xo-proof-media {
  position: relative;
  display: block;
  aspect-ratio: 16 / 10;
  border: 1px solid var(--xo-line-soft);
  border-radius: var(--xo-radius-sm);
  background: var(--xo-ink-3);
  overflow: hidden;
}

.xo-proof-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.01);
  transition: transform 0.7s var(--xo-ease), filter 0.5s ease;
  filter: saturate(0.86) brightness(0.9);
}

.xo-proof-card:hover .xo-proof-media img,
.xo-proof-card:focus-visible .xo-proof-media img {
  transform: scale(1.06);
  filter: saturate(1) brightness(1);
}

.xo-proof-meta {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding-top: 12px;
}

.xo-proof-name {
  margin: 0;
  font-family: var(--xo-display);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: -0.01em;
}

.xo-proof-tag {
  color: var(--xo-faint);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ----------------------------------------------------------- client band */
.xo-clients {
  padding-block: clamp(44px, 5vw, 76px);
  border-top: 1px solid var(--xo-line-soft);
  border-bottom: 1px solid var(--xo-line-soft);
  overflow: hidden;
}

.xo-clients-label {
  margin: 0 0 30px;
  color: var(--xo-faint);
  font: 700 12px/1 var(--xo-body);
  letter-spacing: 0.18em;
  text-align: center;
  text-transform: uppercase;
}

.xo-marquee {
  position: relative;
  display: flex;
  width: 100%;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}

.xo-marquee-track {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: clamp(48px, 5vw, 86px);
  padding-right: clamp(48px, 5vw, 86px);
  animation: xo-slide 46s linear infinite;
  will-change: transform;
}

.xo-marquee:hover .xo-marquee-track {
  animation-play-state: paused;
}

.xo-marquee-track img {
  width: auto;
  height: 38px;
  flex: 0 0 auto;
  /* These logos ship with an opaque white plate baked in, so a silhouette
     filter flattens each one into a blob. Desaturating and then inverting
     drops the plate to pure black (invisible on the ink canvas) and lifts the
     dark artwork to light - one monochrome family, detail intact. brightness
     is multiplicative, so it lifts the mark without lifting the plate. */
  filter: grayscale(1) invert(1) brightness(1.5);
  opacity: 0.72;
  transition: opacity 0.3s ease;
}

.xo-marquee-track img:hover {
  opacity: 1;
}

@keyframes xo-slide {
  to {
    transform: translate3d(-100%, 0, 0);
  }
}

/* -------------------------------------------------------------------- work */
.xo-work-list {
  display: grid;
  gap: clamp(28px, 3.4vw, 56px);
}

.xo-work-pair {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(28px, 3.4vw, 56px);
}

.xo-work-card {
  display: block;
  color: inherit;
}

.xo-work-media {
  position: relative;
  aspect-ratio: 16 / 10;
  border: 1px solid var(--xo-line-soft);
  border-radius: var(--xo-radius);
  background: var(--xo-ink-3);
  overflow: hidden;
}

.xo-work-lead .xo-work-media {
  aspect-ratio: 21 / 9;
}

.xo-work-media img,
.xo-work-media video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.xo-work-media img {
  filter: saturate(0.9) brightness(0.94);
  transform: scale(1.005);
  transition: transform 0.8s var(--xo-ease), filter 0.5s ease, opacity 0.4s ease;
}

.xo-work-media video {
  opacity: 0;
  transition: opacity 0.45s ease;
}

.xo-work-card:hover .xo-work-media img,
.xo-work-card:focus-visible .xo-work-media img {
  transform: scale(1.045);
  filter: saturate(1) brightness(1);
}

.xo-work-card.is-playing .xo-work-media video {
  opacity: 1;
}

/* corner badge that slides in on hover */
.xo-work-open {
  position: absolute;
  z-index: 2;
  right: 16px;
  bottom: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 18px;
  border-radius: 999px;
  background: var(--xo-gold);
  color: #0b0b0d;
  font: 700 13px/1 var(--xo-body);
  white-space: nowrap;
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.35s var(--xo-ease), transform 0.35s var(--xo-ease);
}

.xo-work-open svg {
  width: 14px;
  height: 14px;
}

.xo-work-card:hover .xo-work-open,
.xo-work-card:focus-visible .xo-work-open {
  opacity: 1;
  transform: translateY(0);
}

/* Without hover there is no way to reveal the badge, and a tablet at 900px
   wide is still a touch device - so key off the input, not the width. Must
   sit after the rule it overrides: same specificity, source order decides. */
@media (hover: none) {
  .xo-work-open {
    opacity: 1;
    transform: none;
  }
}

.xo-work-body {
  display: grid;
  gap: 12px;
  padding-top: 22px;
}

.xo-work-side {
  display: grid;
  align-content: start;
  gap: 14px;
}

.xo-work-lead .xo-work-body {
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  gap: 12px clamp(32px, 5vw, 80px);
}

.xo-work-tag {
  color: var(--xo-gold);
  font: 700 12px/1 var(--xo-body);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.xo-work-lead .xo-work-tag {
  grid-column: 1 / -1;
}

.xo-work-name {
  margin: 0;
  font-family: var(--xo-display);
  font-size: clamp(1.35rem, 2vw, 1.95rem);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.024em;
}

.xo-work-lead .xo-work-name {
  font-size: clamp(1.7rem, 3vw, 2.9rem);
}

.xo-work-result {
  max-width: 50ch;
  margin: 0;
  color: var(--xo-dim);
  font-size: 1rem;
  line-height: 1.6;
}

.xo-work-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 4px 0 0;
  margin: 0;
  list-style: none;
}

.xo-work-facts li {
  padding: 7px 14px;
  border: 1px solid var(--xo-line);
  border-radius: 999px;
  color: var(--xo-dim);
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

/* ------------------------------------------------------------------ impact */
/* No band padding of its own - it sits in the gap the work and journal bands
   already leave, marked off by one hairline. */
.xo-impact-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--xo-line);
}

.xo-stat {
  padding: clamp(28px, 3vw, 44px) clamp(18px, 2vw, 36px);
  border-left: 1px solid var(--xo-line-soft);
}

.xo-stat:first-child {
  padding-left: 0;
  border-left: 0;
}

.xo-stat-fig {
  display: block;
  margin: 0;
  color: var(--xo-gold);
  font-family: var(--xo-display);
  font-size: clamp(2.4rem, 4.6vw, 4rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}

.xo-stat-label {
  max-width: 24ch;
  margin: 14px 0 0;
  color: var(--xo-dim);
  font-size: 0.95rem;
  line-height: 1.5;
}

/* --------------------------------------------------- light chapter: what we do */
.xo-do-list {
  display: grid;
  border-top: 1px solid var(--xo-lite-line-soft);
}

.xo-do-row {
  position: relative;
  display: grid;
  grid-template-columns: 84px minmax(0, 1.05fr) minmax(0, 1.35fr) 48px;
  align-items: center;
  gap: 24px;
  padding: clamp(22px, 2.4vw, 32px) clamp(14px, 1.6vw, 26px);
  border-bottom: 1px solid var(--xo-lite-line-soft);
  color: var(--xo-lite-ink);
  isolation: isolate;
  transition: color 0.35s var(--xo-ease), padding-left 0.4s var(--xo-ease);
}

/* the ink sheet that wipes up behind a row on hover */
.xo-do-row::before {
  position: absolute;
  z-index: -1;
  inset: 0;
  background: var(--xo-lite-ink);
  transform: scaleY(0);
  transform-origin: 50% 100%;
  content: "";
  transition: transform 0.42s var(--xo-ease-io);
}

.xo-do-row:hover,
.xo-do-row:focus-visible {
  color: var(--xo-cream);
  padding-left: clamp(24px, 2.6vw, 42px);
}

.xo-do-row:hover::before,
.xo-do-row:focus-visible::before {
  transform: scaleY(1);
}

.xo-do-no {
  color: #8f6400;
  font: 700 13px/1 var(--xo-body);
  letter-spacing: 0.12em;
  transition: color 0.35s var(--xo-ease);
}

.xo-do-row:hover .xo-do-no {
  color: var(--xo-gold);
}

.xo-do-name {
  margin: 0;
  font-family: var(--xo-display);
  font-size: clamp(1.15rem, 1.9vw, 1.72rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.022em;
}

.xo-do-blurb {
  margin: 0;
  color: var(--xo-lite-dim);
  font-size: 1rem;
  line-height: 1.55;
  transition: color 0.35s var(--xo-ease);
}

.xo-do-row:hover .xo-do-blurb {
  color: rgba(255, 246, 230, 0.72);
}

.xo-do-go {
  display: grid;
  width: 42px;
  height: 42px;
  place-items: center;
  border: 1px solid var(--xo-lite-line);
  border-radius: 50%;
  justify-self: end;
  transition: transform 0.4s var(--xo-ease), border-color 0.35s ease,
    background-color 0.35s ease, color 0.35s ease;
}

.xo-do-go svg {
  width: 15px;
  height: 15px;
}

.xo-do-row:hover .xo-do-go {
  border-color: var(--xo-gold);
  background: var(--xo-gold);
  color: #0b0b0d;
  transform: rotate(-45deg);
}

/* ------------------------------------------------- light chapter: process */
.xo-process {
  padding-top: clamp(56px, 6vw, 96px);
  margin-top: clamp(56px, 6vw, 96px);
  border-top: 1px solid var(--xo-lite-line-soft);
}

.xo-steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(20px, 2.4vw, 40px);
  padding: 0;
  margin: 0;
  list-style: none;
  counter-reset: xo-step;
}

.xo-step {
  position: relative;
  padding-top: 26px;
  border-top: 2px solid var(--xo-lite-ink);
  counter-increment: xo-step;
}

.xo-step::before {
  position: absolute;
  top: -2px;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--xo-gold-deep);
  content: "";
  transition: width 0.7s var(--xo-ease);
}

.xo-step.is-in::before {
  width: 100%;
}

.xo-step-no {
  display: block;
  color: #8f6400;
  font: 700 12px/1 var(--xo-body);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.xo-step-name {
  margin: 14px 0 10px;
  font-family: var(--xo-display);
  font-size: clamp(1.15rem, 1.7vw, 1.5rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: -0.02em;
}

.xo-step-text {
  margin: 0;
  color: var(--xo-lite-dim);
  font-size: 0.98rem;
  line-height: 1.58;
}

/* ----------------------------------------------------------------- journal */
.xo-journal-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 2.6vw, 44px);
}

.xo-post {
  display: grid;
  align-content: start;
  gap: 16px;
  color: inherit;
}

.xo-post-media {
  aspect-ratio: 16 / 10;
  border: 1px solid var(--xo-line-soft);
  border-radius: var(--xo-radius-sm);
  background: var(--xo-ink-3);
  overflow: hidden;
}

.xo-post-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.9) brightness(0.9);
  transition: transform 0.7s var(--xo-ease), filter 0.5s ease;
}

.xo-post:hover .xo-post-media img,
.xo-post:focus-visible .xo-post-media img {
  transform: scale(1.05);
  filter: saturate(1) brightness(1);
}

.xo-post-info {
  display: grid;
  gap: 9px;
}

.xo-post-tag {
  color: var(--xo-faint);
  font: 700 12px/1 var(--xo-body);
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.xo-post-title {
  margin: 0;
  font-family: var(--xo-display);
  font-size: clamp(1.1rem, 1.5vw, 1.4rem);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-wrap: balance;
}

.xo-post:hover .xo-post-title {
  color: var(--xo-gold);
}

/* ------------------------------------------------------------------- start */
/* the shared footer opens with its own curve, so this band closes tighter */
.xo-start {
  padding-bottom: clamp(48px, 5vw, 84px);
}

.xo-start-top {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  align-items: end;
  gap: 34px clamp(40px, 6vw, 100px);
}

.xo-start-title {
  max-width: 16ch;
  margin: 18px 0 0;
  font-family: var(--xo-display);
  font-size: clamp(2.3rem, 5.2vw, 4.6rem);
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.038em;
}

.xo-start-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 26px;
}

/* ---------------------------------------------------------- footer bridge */
/* The shared footer's curve and its top band are painted white - they assume a
   white page above. On this ink page, repaint both in the page colour: the
   curve becomes a mask so it lands on the exact same ink, with no seam. */
body.xo-body .ext-footer-cta::before {
  background-image: none;
  background-color: var(--xo-ink);
  -webkit-mask: url("../images/common/footer-top-vector.svg") top center / 100% 100% no-repeat;
  mask: url("../images/common/footer-top-vector.svg") top center / 100% 100% no-repeat;
}

body.xo-body .ext-footer-cta::after {
  background: var(--xo-ink);
}

/* the shared footer keeps its own type stack */
body.xo-body .ext-site-footer,
body.xo-body .ext-booking-modal {
  font-family: var(--ext-font-primary, "Space Grotesk", ui-sans-serif, system-ui, sans-serif);
}

/* the fixed header is out of flow, so a scroll lock still needs the measured
   scrollbar width padded back in (site-menu.js owns --ext-sbw) */
html.xm-lock .xo-header,
body.ext-booking-lock .xo-header {
  padding-right: calc(
    max(var(--xo-gutter), (100% - var(--xo-max)) / 2) + var(--ext-sbw, 0px)
  );
}

/* ------------------------------------------------------- reveal base state */
/* JS clears these once ScrollTrigger takes over; without JS they never apply. */
html.xo-js [data-xo-reveal] {
  opacity: 0;
  transform: translateY(28px);
}

html.xo-js [data-xo-fade] {
  opacity: 0;
}

/* ------------------------------------------------------------- responsive */
@media (max-width: 1180px) {
  .xo-do-row {
    grid-template-columns: 64px minmax(0, 1fr) 42px;
    gap: 18px;
  }

  .xo-do-blurb {
    grid-column: 2 / 3;
    padding-top: 4px;
  }

  .xo-do-name {
    grid-column: 2 / 3;
  }

  .xo-do-no {
    grid-column: 1 / 2;
    grid-row: 1 / 3;
    align-self: start;
    padding-top: 6px;
  }

  .xo-do-go {
    grid-column: 3 / 4;
    grid-row: 1 / 3;
  }
}

@media (max-width: 1024px) {
  .xo-hero-foot {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 28px;
  }

  .xo-proof-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .xo-work-lead .xo-work-body {
    grid-template-columns: minmax(0, 1fr);
  }

  .xo-steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 32px 24px;
  }

  .xo-impact-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .xo-stat {
    border-left: 0;
    border-top: 1px solid var(--xo-line-soft);
    padding-inline: 0 24px;
  }

  .xo-stat:first-child {
    border-top: 1px solid var(--xo-line-soft);
  }

  .xo-journal-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .xo-post:last-child {
    display: none; /* keep the row even at two-up */
  }

  .xo-start-top {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }
}

@media (max-width: 860px) {
  .xo-head {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
  }

  .xo-head-copy {
    max-width: none;
  }

  .xo-work-pair {
    grid-template-columns: minmax(0, 1fr);
  }

  .xo-work-lead .xo-work-media {
    aspect-ratio: 16 / 10;
  }

  .xo-hero-mark {
    top: auto;
    bottom: 8%;
    width: 60vw;
    opacity: 0.04;
    transform: none;
  }
}

@media (max-width: 640px) {
  :root {
    --xo-header-h: 74px;
  }

  body.xo-body {
    font-size: 16px;
  }

  .xo-header-hire {
    padding: 12px 18px;
    font-size: 14px;
  }

  .xo-hero-title {
    max-width: none;
    font-size: clamp(2.7rem, 12.5vw, 4rem);
  }

  .xo-hero-actions .xo-btn {
    flex: 1 1 100%;
  }

  .xo-proof-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
  }

  .xo-proof-tag {
    display: none;
  }

  .xo-impact-grid,
  .xo-steps,
  .xo-journal-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .xo-post:last-child {
    display: grid;
  }

  .xo-do-row {
    grid-template-columns: 44px minmax(0, 1fr) 36px;
    gap: 14px;
    padding-inline: 0;
  }

  .xo-do-row:hover,
  .xo-do-row:focus-visible {
    padding-left: 12px;
  }

  .xo-do-go {
    width: 34px;
    height: 34px;
  }

  .xo-work-open {
    right: 10px;
    bottom: 10px;
    padding: 9px 14px;
    font-size: 12px;
  }

  .xo-marquee-track img {
    height: 30px;
  }
}

/* ==========================================================================
   Preloader
   Ported from launch.externo.io and retinted for the ink page: the overlay is
   the same colour as the hero behind it, so the reveal reads as the mark
   dissolving rather than one screen swapping for another.

   The overlay is display:none until the gate in <head> adds html.xo-preloading
   - so a dead script, a blocked CDN or no scripting at all leaves a normal
   page here, never a black rectangle nobody can dismiss.
   ========================================================================== */
.xo-pre {
  display: none;
}

html.xo-preloading .xo-pre {
  /* the radius of the hole punched through the overlay; GSAP tweens it */
  --xo-hole: 0px;

  position: fixed;
  inset: 0;
  /* Above the page-veil's own hold layer, below its sheets: if a click starts
     a page transition mid-preload, the veil still wins. */
  z-index: 2147482000;
  display: grid;
  place-items: center;
  background: var(--xo-ink);
  -webkit-mask-image: radial-gradient(circle at 50% 50%, transparent var(--xo-hole), #000 calc(var(--xo-hole) + 1px));
  mask-image: radial-gradient(circle at 50% 50%, transparent var(--xo-hole), #000 calc(var(--xo-hole) + 1px));
}

/* Hold the page still underneath. html already carries scrollbar-gutter:stable
   (style.css), so locking here costs no sideways jump when it unlocks. */
html.xo-preloading,
html.xo-preloading body {
  overflow: hidden;
}

.xo-pre-icon {
  display: block;
  /* clamped against both axes so a short landscape phone can't crop it */
  width: max(58px, min(9vw, 14vh, 104px));
  height: auto;
  /* the ring overshoots its own box on the way in */
  overflow: visible;
}

.xo-pre-e {
  fill: var(--xo-snow);
}

.xo-pre-ring {
  fill: var(--xo-gold);
}

/* --------------------------------------------------------- reduced motion */
@media (prefers-reduced-motion: reduce) {
  /* The gate in <head> already refuses to arm the preloader here. This is for
     the case where the setting is switched on while the page is open - the
     overlay must come down at once, and take the scroll lock with it. */
  html.xo-preloading .xo-pre {
    display: none;
  }

  html.xo-preloading,
  html.xo-preloading body {
    overflow: visible;
  }

  .xo-marquee-track {
    animation: none;
  }

  html.xo-js [data-xo-reveal],
  html.xo-js [data-xo-fade] {
    opacity: 1;
    transform: none;
  }

  .xo-scribble path {
    stroke-dashoffset: 0;
  }

  .xo-step::before {
    width: 100%;
  }

  body.xo-body *,
  body.xo-body *::before,
  body.xo-body *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
