/* ============================================================
   Inner pages — white from the very top (hero included), then a
   soft dissolve into the live sky just before the footer, which
   keeps the sky + grass ending. One shared system for work /
   case-study / blog / blog-post / solutions / about; contact
   stays fully in the sky (no sheet).
   Loads AFTER style.css and only overrides/extends it.
   ============================================================ */

:root {
  --ink: var(--black);
  --ink-soft: rgba(27, 27, 27, .62);
  --ink-faint: rgba(27, 27, 27, .42);
  --line: rgba(27, 27, 27, .1);
  --paper: #fff;
  --paper-dim: #f4f7fb;
}

/* iOS 26 status-bar tint sampler (injected by js/inner.js statusTint()).
   Safari 26 colours its floating status-bar glass from the background-color
   PROPERTY of a fixed element near the top edge — not theme-color, not
   scrolled pixels, not a border. .header is fixed but transparent, so without
   this the glass sampled the white sheet and the blue inset scrolled away.
   This solid-blue strip is the thing Safari samples: 8px tall at the very top
   (hidden under the status bar) and above .header (z-index) so it wins. Shown
   only on iOS — the @supports trio is iOS-Safari-only — so desktop never gets
   a stray blue line. Don't give it opacity:0 (Safari then ignores it); toggle
   display. Note: only HTML's background-color is safe for the page (it's
   propagated to the fixed viewport canvas); never put a background on BODY —
   the body box is document-height and scrolls, dragging the colour with it. */
/* Status-bar inset fill. iOS 26's floating "Liquid Glass" status bar samples
   the pixels behind it; on a white page that's white, so the bar goes
   see-through. This fixed strip paints solid blue across the top safe area so
   the glass always samples blue. NOT gated behind an @supports query (the old
   one evaluated false on iOS 26 → strip was display:none → see-through) and it
   self-collapses to 0 height where there's no inset (desktop), so it's safe to
   leave unconditional. Fixed, so it never scrolls away. */
.status-tint {
  display: block;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: env(safe-area-inset-top, 0px);
  background-color: var(--inset-fill);
  z-index: 200;
  pointer-events: none;
}

/* ---------- Page hero (base = on sky, used by contact) ---------- */
.page-hero {
  min-height: 52svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  text-align: center;
  padding-top: calc(var(--header-height) + var(--safe-top) + 56px);
  padding-bottom: clamp(52px, 8vh, 96px);
}
.page-hero--tall { min-height: 72svh; }
.page-eyebrow {
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  opacity: .8;
  margin-bottom: 22px;
}
.page-title {
  font-size: clamp(2.5rem, 5.2vw, 4.25rem);
  letter-spacing: -.045em;
  max-width: 18ch;
  margin-inline: auto;
}
.page-sub {
  margin: 20px auto 0;
  max-width: 52ch;
  font-size: 1.125rem;
  line-height: 1.55;
  opacity: .88;
}
.page-hero .hero-stats { margin-top: 52px; }
/* action row for utility pages (404): primary button + arrow link */
.page-hero-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 18px 32px;
  margin-top: 36px;
}
/* meta row for articles: author dot date dot read time */
.page-meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 26px;
  font-size: .9rem;
  opacity: .85;
}
.page-meta i {
  font-style: normal;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: currentColor;
  opacity: .6;
}

/* ---------- The sheet: now the whole page surface ---------- */
.sheet {
  position: relative;
  width: 100%;
  background: var(--paper);
  color: var(--ink);
  /* the sheet is the page's reading surface — clip overflowing deco clouds etc.
     `clip`, not `hidden`: a hidden box is still a programmatic scroll container,
     so anchor jumps (#audit), scroll anchoring, or find-on-page can scroll the
     sheet internally and permanently clip the hero under the fixed header —
     user touch can never scroll it back. `clip` can't be scrolled at all. */
  overflow: hidden;
  overflow: clip;
}

/* hero lives inside the sheet — ink on white, more compact than the
   old sky hero since there's no backdrop to showcase */
.sheet .page-hero,
.sheet .page-hero--tall {
  min-height: 0;
  justify-content: flex-start;
  padding-top: calc(var(--header-height) + var(--safe-top) + clamp(64px, 9vh, 110px));
  padding-bottom: clamp(28px, 4vh, 48px);
}
.sheet .page-eyebrow { color: var(--altitude); opacity: 1; }
.sheet .page-sub { opacity: 1; }
.sheet .page-meta { color: var(--ink-soft); opacity: 1; }
/* case-study hero stats, re-inked */
.sheet .hero-stats .stat-num { opacity: 1; }
.sheet .hero-stats .stat-num em { color: var(--altitude); }
.sheet .hero-stats .stat-label { color: var(--ink-soft); opacity: 1; }
.sheet .hero-stats .stat-divider { background: var(--line); }

/* ---------- Sky footer: CSS-only sky for the sheet pages ----------
   Sheet sub pages don't load the WebGL canvases at all (676KB three.js
   plus a permanent render loop, for a sky the sheet hides until the
   footer). This wrapper paints the footer sky itself: a gradient
   sampled from the live shader at footer scroll depth, with drifting
   .deco-cloud photo sprites. Homepage + contact keep the real canvases. */
.sky-footer {
  position: relative;
  /* clip, not hidden — same scroll-container trap as .sheet above */
  overflow: hidden;
  overflow: clip;
  /* pale haze at the very top (hidden under the white dissolve) so the
     fade lands on near-white blue instead of full-saturation sky; back
     to the true sky color before the CTA text starts (px stops keep the
     haze band fixed regardless of footer height) */
  background: linear-gradient(180deg,
    #97c1e9 0px,
    #5e9cda 200px,
    #3382cf 380px,
    #2677c8 520px,
    #2b87dc 100%);
}
/* clouds sit under the fade/CTA/footer so the white dissolve covers them */
.sky-footer > .deco-cloud { z-index: 0; }
.sky-footer > :not(.deco-cloud) { position: relative; z-index: 1; }

/* ---------- White → sky dissolve above the footer ---------- */
.sky-fade {
  position: relative;
  height: clamp(220px, 34vh, 400px);
  /* smoothstep alpha ramp — eases out of solid white and into the sky
     with no visible gradient "kinks" (Mach bands) at the stops */
  background: linear-gradient(180deg,
    var(--paper) 0%,
    rgba(255, 255, 255, .97) 10%,
    rgba(255, 255, 255, .9) 20%,
    rgba(255, 255, 255, .78) 30%,
    rgba(255, 255, 255, .65) 40%,
    rgba(255, 255, 255, .5) 50%,
    rgba(255, 255, 255, .35) 60%,
    rgba(255, 255, 255, .22) 70%,
    rgba(255, 255, 255, .1) 80%,
    rgba(255, 255, 255, .03) 90%,
    rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
}
/* the bottom edge of the dissolve billows: two static layers of the
   photo puff sprite hang off the white so the page bottom reads as the
   underside of a cloud bank, not a flat gradient line. The sprite is far
   taller than the fade band, so without a mask the box edge slices every
   puff along a hard horizontal line — the mask dissolves the layer to
   transparent well before its own bottom edge, and the boxes extend past
   the fade into the blue so the dissolve has room to breathe. Tops need
   no mask: white puffs over the near-opaque white are invisible. */
.sky-fade::before,
.sky-fade::after {
  content: "";
  position: absolute;
  left: -6%;
  right: -6%;
  background-repeat: no-repeat;
  pointer-events: none;
  /* ramp in at the top as well: the layers start inside the fade and the
     mask fades them in from nothing, so the gray sprite shading never
     meets the white page along a clipped edge */
  -webkit-mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, #000 42%, #000 58%, rgba(0,0,0,0) 94%);
  mask-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, #000 42%, #000 58%, rgba(0,0,0,0) 94%);
}
/* Both layers mix cloud-photo.png with its mirrored copy
   (cloud-photo-flip.png) at strongly contrasted sizes, staggered heights
   and uneven gaps — equal sizes at one height read as a repeated
   wallpaper border (rejected look, worst on mobile), CSS can't flip or
   rotate individual background layers, so the variety must come from
   the second asset + irregular placement. */
/* back layer — bigger, fainter; dissolves first, higher in the fade */
.sky-fade::before {
  top: 0;
  bottom: -22%;
  opacity: .75;
  background-image:
    url("../assets/cloud-photo.png"),
    url("../assets/cloud-photo-flip.png"),
    url("../assets/cloud-photo.png");
  background-size: 78% auto, 50% auto, 62% auto;
  background-position: 4% 72%, 56% 84%, 108% 62%;
}
/* front layer — smaller puffs reaching lowest into the blue, clear of the CTA */
.sky-fade::after {
  top: 8%;
  bottom: -42%;
  background-image:
    url("../assets/cloud-photo-flip.png"),
    url("../assets/cloud-photo.png"),
    url("../assets/cloud-photo-flip.png"),
    url("../assets/cloud-photo.png");
  background-size: 46% auto, 28% auto, 22% auto, 42% auto;
  background-position: -6% 84%, 32% 98%, 54% 78%, 94% 92%;
}
/* narrow screens: the desktop spread squeezes into a row of identical
   small puffs — swap to fewer, larger, overlapping ones */
@media (max-width: 720px) {
  .sky-fade::before {
    background-image:
      url("../assets/cloud-photo.png"),
      url("../assets/cloud-photo-flip.png");
    background-size: 115% auto, 88% auto;
    background-position: -35% 70%, 115% 82%;
  }
  .sky-fade::after {
    background-image:
      url("../assets/cloud-photo-flip.png"),
      url("../assets/cloud-photo.png"),
      url("../assets/cloud-photo-flip.png");
    background-size: 72% auto, 50% auto, 62% auto;
    background-position: -12% 88%, 58% 100%, 118% 84%;
  }
}
.sheet ::selection { background: var(--altitude); color: var(--white); }
.sheet p { color: rgba(27, 27, 27, .8); }
.sheet .u-h2-large { color: var(--ink); }

/* sections inside the sheet share one rhythm */
.sheet-section {
  max-width: var(--content-width);
  margin: 0 auto;
  padding: clamp(64px, 8.5vw, 120px) var(--row-margin);
}
.sheet-section + .sheet-section { padding-top: 0; }
.sheet-head { max-width: 720px; margin: 0 auto 56px; text-align: center; }
.sheet-head .u-h2-large { font-size: clamp(2rem, 3.5vw, 3.25rem); }
.sheet-head p { margin-top: 18px; }
.kicker {
  display: block;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--altitude);
  margin-bottom: 18px;
}

/* word-cascade on white: same mechanic, dim words read as light grey */
.sheet [data-words] .w { opacity: .14; }
.sheet [data-words] .w.on { opacity: 1; }

/* ---------- Buttons on white ---------- */
.btn-outline-ink { border-color: rgba(27, 27, 27, .3); color: var(--ink); }
.btn-outline-ink:hover { border-color: var(--ink); }
.btn-outline-ink::after {
  background:
    radial-gradient(120% 120% at 100% 0%, rgba(76, 150, 247, .25) 0%, transparent 70%),
    radial-gradient(120% 120% at 0% 100%, rgba(76, 150, 247, .25) 0%, transparent 70%);
}

/* arrow link — quiet inline CTA used on cards and section feet */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: .92rem;
  font-weight: 500;
  color: var(--ink);
}
.link-arrow svg { width: 15px; height: 15px; transition: translate .3s cubic-bezier(.22,1,.36,1); }
.link-arrow:hover svg { translate: 4px 0; }
/* case-study CTAs ("View case" / "Read the case study" / "See the case study")
   are underlined to read as links; other link-arrow CTAs stay plain. */
.case-card .link-arrow,
.case-featured-body .link-arrow,
.link-arrow[href*="case-study"] {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}

/* ---------- Header flips to ink while over the sheet ----------
   js/inner.js toggles body.on-sheet via ScrollTrigger. Everything the
   header shows in white gets an ink counterpart; the altitude scrim
   fades out so the blur reads as frosted white. */
.header .nav-item > a,
.header .btn,
.logo-svg,
.menu-toggle span { transition: color .45s ease, filter .45s ease, background-color .45s ease, border-color .45s ease; }
.header::after { transition: opacity .45s ease; }

body.on-sheet .header::after { opacity: 0; }
/* white pages paint NO blue in the header: the status bar is coloured by
   .status-tint, so the header's safe-area strip + seam-bridge gradient would
   otherwise show as an extra blue band below the status bar on the sheet.
   Keep the border-top WIDTH (it still pushes the nav below the notch) but make
   it transparent, and drop the blue gradient. */
body.on-sheet .header {
  border-top-color: transparent;
  background: none;
}
body.on-sheet .header .nav-item > a { color: var(--ink); }
/* header-scoped: the footer logo is also a .logo-svg and must stay white
   (visible on mobile, where the flight is disabled) */
body.on-sheet .header .logo-svg { filter: brightness(0); }
body.on-sheet .menu-toggle span { background: var(--ink); }
body.on-sheet .header .btn-primary { background: var(--ink); color: var(--white); border-color: var(--ink); }
/* hover mirrors .btn-dark: stays ink, sky glow blooms inside */
body.on-sheet .header .btn-primary::after {
  background:
    radial-gradient(120% 120% at 100% 0%, rgba(125, 182, 255, .8) 0%, rgba(76, 150, 247, .3) 35%, transparent 75%),
    radial-gradient(120% 120% at 0% 100%, rgba(5, 99, 233, .85) 0%, rgba(5, 99, 233, .35) 35%, transparent 75%);
}
body.on-sheet .header .btn-primary:hover {
  background: var(--ink);
  color: var(--white);
  border-color: rgba(76, 150, 247, .7);
}
/* mobile menu overlay is sky — over it, the toggle and logo go back to white */
body.menu-open .menu-toggle span { background: var(--white) !important; }
body.menu-open .header .logo-svg { filter: none !important; }

/* current page gets a persistent nav underline */
.nav-item > a.is-current span::after { transform: scaleX(1); }

/* ---------- Footer logo + flight ----------
   logoFlight (js/main.js) also picks up .logo-foot, so inner pages get
   the same header→footer glide as the homepage. While the flight clone
   is docked in the header (.is-docked) it must follow the on-sheet
   ink-flip above — it's the white SVG sitting on the white sheet
   otherwise. Once it departs it flies over the footer sky, so it goes
   back to white even if the header itself is still over the sheet. */
.logo-foot { width: min(300px, 50vw); color: var(--white); }
.logo-flight { transition: filter .45s ease; }
body.on-sheet .logo-flight.is-docked { filter: brightness(0); }
/* mobile menu overlay is sky — same release as the real header logo */
body.menu-open .logo-flight { filter: none !important; }

/* ============================================================
   Components on the sheet
   ============================================================ */

/* ---------- Tiles (the white-page card voice) ---------- */
.tile {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 28px;
}
.tile-dim { background: var(--paper-dim); border-color: transparent; }
.tile h5 { font-weight: 500; font-size: 1.1rem; margin-bottom: 10px; }
.tile p { font-size: .92rem; line-height: 1.6; }

/* ---------- Tags ---------- */
.tag {
  display: inline-block;
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--altitude);
}

/* ---------- Case study cards ---------- */
.case-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
}
.case-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 30px 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  transition: background-color .4s ease, box-shadow .4s ease, border-color .4s ease;
}
/* Quiet surface: the card doesn't move — it warms up. A faint NEUTRAL
   grey fill (no blue tint), the hairline darkens a touch, and the arrow
   advances. Deliberately restrained. */
.case-card:hover {
  background: rgba(27, 27, 27, .02);
  border-color: rgba(27, 27, 27, .17);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .03);
}
.case-card:hover .link-arrow svg { translate: 4px 0; }
.case-stat {
  font-family: "Geist", Arial, sans-serif;
  font-weight: 600;
  font-size: clamp(2.6rem, 3.6vw, 3.6rem);
  line-height: 1;
  color: var(--altitude);
  letter-spacing: -.005em;
}
.case-stat em {
  font-family: "Geist", Arial, sans-serif;
  font-style: italic;
  font-weight: 500;
  font-size: .5em;
  margin-left: .06em;
}
.case-card h3 { font-weight: 500; font-size: 1.15rem; letter-spacing: -.02em; }
.case-card p { font-size: .92rem; line-height: 1.6; flex-grow: 1; }
.case-card .link-arrow { margin-top: 4px; }

/* three varying-type stats per card */
.cc-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.cc-stat { display: flex; flex-direction: column; gap: 4px; }
.cc-num {
  font-family: "Geist", Arial, sans-serif;
  font-weight: 600;
  font-size: clamp(1.45rem, 2.1vw, 1.85rem);
  line-height: 1;
  color: var(--ink);
  letter-spacing: -.01em;
}
.cc-num em {
  font-family: "Geist", Arial, sans-serif;
  font-style: italic;
  font-weight: 500;
  font-size: .52em;
  margin-left: .04em;
}
.cc-lab {
  font-size: .64rem;
  line-height: 1.25;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--ink-soft);
}

/* featured case — one wide split card above the grid */
.case-featured {
  display: grid;
  grid-template-columns: 1.1fr .9fr;
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
  padding: clamp(32px, 4.5vw, 64px);
  margin-bottom: 16px;
  border-radius: calc(var(--radius-card) + 6px);
  background: var(--paper-dim);
}
.case-featured h3 {
  font-size: clamp(1.8rem, 2.8vw, 2.6rem);
  font-weight: 400;
  letter-spacing: -.04em;
  line-height: 1.08;
  margin: 14px 0 16px;
}
.case-featured .case-stat { font-size: clamp(4rem, 7vw, 6.5rem); }
.case-featured-body p { max-width: 46ch; }
.case-featured-body .link-arrow { margin-top: 26px; }
/* the featured visual: a quiet white stat figure (no panel, no photos) —
   accent rule divides the story from the numbers, the onboarding jump
   (240 → 600+) carries the proof instead of a stock sky. */
.case-featured-visual {
  position: relative;
  align-self: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-left: clamp(22px, 2.6vw, 40px);
  border-left: 1px solid var(--line);
}
.case-featured-visual .case-stat {
  color: var(--altitude);
  display: flex;
  align-items: flex-start;
}
.case-featured-visual .case-stat em { color: var(--altitude); }
.case-stat-label {
  display: block;
  font-family: "Geist", Arial, sans-serif;
  font-size: .95rem;
  color: var(--ink-soft);
  margin-top: 8px;
}
.case-progress { margin-top: clamp(24px, 3.2vw, 36px); }
.case-progress-lab {
  display: block;
  font-family: "Geist", Arial, sans-serif;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--ink-soft);
  margin-bottom: 12px;
}
.case-progress-row {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: "Geist", Arial, sans-serif;
}
.cp-from, .cp-to {
  font-weight: 600;
  font-size: clamp(1.7rem, 2.5vw, 2.2rem);
  line-height: 1;
  letter-spacing: -.01em;
}
.cp-from { color: var(--ink-soft); }
.cp-to { color: var(--altitude); }
.cp-arrow { width: 26px; height: 26px; color: var(--altitude); flex: none; }

/* ---------- Decorative photo-sprite clouds (CSS, not canvas) ----------
   the same cloud-photo.png the WebGL layer uses, dropped into gradient
   panels so the cloud moments inside the sheet match the live sky. */
.deco-cloud {
  position: absolute;
  pointer-events: none;
  user-select: none;
  opacity: .9;
  filter: brightness(1.1) saturate(1.05);
  animation: cloudDrift 16s ease-in-out infinite alternate;
}
.deco-cloud--2 { animation-duration: 22s; animation-delay: -8s; }
@keyframes cloudDrift {
  from { translate: -2.5% 0; }
  to   { translate: 2.5% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .deco-cloud { animation: none; }
}

/* ---------- Sky CTA: the closing pitch floats in the live sky ----------
   sits between the sheet's sky-fade dissolve and the footer, so the
   page's one sky moment is the real thing — no boxed gradient copy.
   Word cascade + colors come from the site's default sky styles. */
.sky-cta {
  position: relative;
  max-width: var(--content-width);
  margin: 0 auto;
  /* extra top clearance so the pitch floats in clear blue below the cloud bank */
  padding: clamp(88px, 14vh, 180px) var(--row-margin) 0;
  text-align: center;
  color: var(--white);
}
.sky-cta .u-h2-large { color: var(--white); font-size: clamp(2rem, 3.6vw, 3.25rem); }
.sky-cta-sub { max-width: 46ch; margin: 18px auto 0; color: rgba(255, 255, 255, .92); }
.sky-cta .btn { margin-top: 32px; }

/* ---------- Stats row in ink (sheet variant of .hero-stats) ---------- */
.stat-row-ink { display: flex; align-items: center; justify-content: center; gap: clamp(28px, 5vw, 72px); }
.stat-row-ink .stat-num { color: var(--ink); opacity: 1; }
.stat-row-ink .stat-num em { color: var(--altitude); }
.stat-row-ink .stat-label { color: var(--ink-soft); opacity: 1; }
.stat-row-ink .stat-divider { background: var(--line); }

/* ---------- Numbered solution / process blocks ---------- */
.sol-block {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: clamp(28px, 5vw, 80px);
  padding: clamp(44px, 5.5vw, 72px) 0;
  border-top: 1px solid var(--line);
}
.sol-block:last-of-type { border-bottom: 1px solid var(--line); }
.sol-no {
  font-family: "Geist", Arial, sans-serif;
  font-weight: 600;
  font-size: clamp(3rem, 5vw, 4.6rem);
  line-height: .9;
  color: rgba(5, 99, 233, .16);
  letter-spacing: -.005em;
}
.sol-head h3 {
  font-size: clamp(1.7rem, 2.6vw, 2.4rem);
  font-weight: 400;
  letter-spacing: -.04em;
  line-height: 1.1;
  margin-top: 14px;
  max-width: 14ch;
}
.sol-head .tag { margin-top: 18px; }
.sol-body > p { font-size: 1.05rem; line-height: 1.65; max-width: 56ch; }
.sol-points { list-style: none; margin-top: 26px; display: flex; flex-direction: column; gap: 12px; }
.sol-points li {
  position: relative;
  padding-left: 26px;
  font-size: .95rem;
  line-height: 1.55;
  color: rgba(27, 27, 27, .78);
}
.sol-points li::before {
  content: "";
  position: absolute;
  left: 0; top: .52em;
  width: 12px; height: 7px;
  border-left: 1.6px solid var(--altitude);
  border-bottom: 1.6px solid var(--altitude);
  rotate: -45deg;
}
.sol-proof {
  margin-top: 30px;
  display: inline-flex;
  align-items: baseline;
  gap: 12px;
  padding: 14px 18px;
  border-radius: 12px;
  background: var(--paper-dim);
  font-size: .9rem;
  color: var(--ink-soft);
}
.sol-proof b {
  font-family: "Geist", Arial, sans-serif;
  font-weight: 600;
  font-size: 1.6rem;
  color: var(--altitude);
  letter-spacing: 0;
}
.sol-body .link-arrow { margin-top: 28px; }

/* ---------- Solutions catalog (full list, grouped by engagement) ---------- */
.catalog-group { margin-top: 56px; }
.catalog-group:first-of-type { margin-top: 0; }
.catalog-label {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 18px;
}
.catalog-label .tag { white-space: nowrap; }
.catalog-label::after { content: ""; flex: 1; height: 1px; background: var(--line); }

/* ---------- Step list (case study "how it works") ---------- */
.steps { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.step {
  padding: 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
}
.step-no {
  font-family: "Geist", Arial, sans-serif;
  font-weight: 600;
  font-size: 1.5rem;
  color: var(--altitude);
  display: block;
  margin-bottom: 14px;
}
.step h4 { font-weight: 500; font-size: 1.05rem; margin-bottom: 8px; }
.step p { font-size: .92rem; line-height: 1.6; }

/* ---------- Case study layout: overview + facts rail ---------- */
.cs-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: clamp(32px, 5vw, 80px);
  align-items: start;
}
.cs-facts {
  position: sticky;
  top: calc(var(--header-height) + var(--safe-top) + 24px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  overflow: hidden;
}
.cs-fact { padding: 18px 22px; border-bottom: 1px solid var(--line); }
.cs-fact:last-child { border-bottom: 0; }
.cs-fact dt {
  font-size: .72rem;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--ink-faint);
  margin-bottom: 5px;
}
.cs-fact dd { font-size: .95rem; line-height: 1.5; }

/* result metric cards */
.result-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.result-card {
  padding: 30px 28px;
  border-radius: var(--radius-card);
  background: var(--paper-dim);
}
.result-card .case-stat { display: block; margin-bottom: 12px; }
.result-card p { font-size: .92rem; line-height: 1.55; }

/* prev/next case footer nav */
.cs-nav { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.cs-nav a {
  padding: 26px 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  transition: background-color .4s ease, box-shadow .4s ease, border-color .4s ease;
}
/* standardized card hover — matches .case-card (neutral, no blue glow) */
.cs-nav a:hover {
  background: rgba(27, 27, 27, .02);
  border-color: rgba(27, 27, 27, .17);
  box-shadow: 0 1px 2px rgba(0, 0, 0, .03);
}
.cs-nav a span { display: block; font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; color: var(--ink-faint); margin-bottom: 8px; }
.cs-nav a b { font-weight: 500; font-size: 1.05rem; letter-spacing: -.01em; }
.cs-nav .cs-nav-next { text-align: right; }

/* ---------- Pull quote ---------- */
.pullquote {
  max-width: 760px;
  margin: 0 auto;
  text-align: center;
}
.pullquote blockquote {
  font-family: "Geist", Arial, sans-serif;
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.5rem, 2.8vw, 2.2rem);
  line-height: 1.35;
  letter-spacing: -.01em;
  color: var(--ink);
}
.pullquote figcaption { margin-top: 22px; font-size: .9rem; color: var(--ink-soft); }
.pullquote figcaption b { font-weight: 500; color: var(--ink); }

/* ---------- Blog cards ---------- */
.post-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }
.post-card { display: flex; flex-direction: column; border-radius: var(--radius-card); }
.post-thumb {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-card);
  overflow: hidden;
  margin-bottom: 18px;
}
/* each thumb is its own patch of sky — colour is set per card via
   --sky-a (deep) / --sky-b (light) / optional --sky-hi (highlight, e.g. warm);
   the *pattern* is a separate knob: add a .pat-* class to vary the layout. */
.post-thumb-sky {
  position: absolute;
  inset: 0;
  /* derived deep tones, shared by every pattern */
  --sky-deep: color-mix(in srgb, var(--sky-a) 88%, #001b4d);
  --sky-deeper: color-mix(in srgb, var(--sky-a) 96%, #001233);
  --sky-glow: var(--sky-hi, color-mix(in srgb, var(--sky-b) 62%, #fff));
  transition: scale .6s cubic-bezier(.22,1,.36,1);
  /* default = "dawn"; un-classed cards (e.g. related posts) still render */
  background:
    radial-gradient(120% 95% at 18% 12%, var(--sky-b) 0%, transparent 56%),
    radial-gradient(115% 105% at 88% 20%, var(--sky-a) 0%, transparent 60%),
    radial-gradient(135% 125% at 60% 106%, var(--sky-glow) 0%, transparent 55%),
    linear-gradient(var(--sky-angle, 180deg), var(--sky-deep), var(--sky-deeper));
}
.post-card:hover .post-thumb-sky { scale: 1.04; }

/* ---- background pattern variants (colour stays card-controlled) ---- */
/* A · dawn — soft glow from the upper-left (same as default) */
.pat-dawn { /* inherits the default background above */ }
/* B · sweep — a diagonal shaft of light */
.pat-sweep {
  background:
    linear-gradient(118deg, transparent 28%, color-mix(in srgb, var(--sky-b) 78%, #fff) 50%, transparent 72%),
    radial-gradient(130% 120% at 88% 100%, var(--sky-deeper) 0%, transparent 58%),
    linear-gradient(150deg, var(--sky-a), var(--sky-deep));
}
/* C · halo — a centred glow ringed by a soft vignette */
.pat-halo {
  background:
    radial-gradient(66% 58% at 50% 40%, var(--sky-b) 0%, transparent 62%),
    radial-gradient(150% 150% at 50% 50%, transparent 42%, var(--sky-deeper) 100%),
    linear-gradient(180deg, var(--sky-a), var(--sky-deep));
}
/* D · rise — light (or golden) rising from the bottom edge */
.pat-rise {
  background:
    radial-gradient(140% 92% at 50% 122%, var(--sky-glow) 0%, transparent 56%),
    radial-gradient(120% 105% at 50% 128%, var(--sky-b) 28%, transparent 72%),
    linear-gradient(180deg, var(--sky-deeper), var(--sky-a));
}
/* E · aurora — soft conic sweeps */
.pat-aurora {
  background:
    radial-gradient(115% 115% at 50% 48%, transparent 32%, var(--sky-deeper) 96%),
    conic-gradient(from 200deg at 38% 34%, var(--sky-b), transparent 24%, var(--sky-a) 54%, transparent 80%, var(--sky-b)),
    linear-gradient(160deg, var(--sky-a), var(--sky-deep));
}
/* F · contour — faint topographic rings over a gradient */
.pat-contour {
  background:
    repeating-radial-gradient(circle at 24% 128%, transparent 0 19px, rgba(255,255,255,.11) 19px 21px),
    radial-gradient(120% 100% at 22% 8%, var(--sky-b) 0%, transparent 54%),
    linear-gradient(165deg, var(--sky-a), var(--sky-deeper));
}

/* film grain — the ElevenLabs texture, pushed harder */
.post-thumb::after {
  content: "";
  position: absolute;
  inset: -15%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.72' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: .58;
  mix-blend-mode: overlay;
  pointer-events: none;
  z-index: 1;
}
/* Direction A: abstract sky mesh — no cloud sprite in the card thumbnail */
.post-thumb .deco-cloud { display: none; }

/* per-post focal overlay — abstract but relevant, sits above the grain */
.thumb-cover {
  position: absolute;
  inset: 0;
  z-index: 2;
  padding: clamp(16px, 2.4vw, 26px);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  color: #fff;
  pointer-events: none;
}
/* subtle bottom scrim keeps the focal text legible over any pattern */
.thumb-cover::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(to top, rgba(2, 12, 40, .34) 0%, transparent 44%);
}
.thumb-mark {
  position: absolute;
  top: clamp(15px, 2.2vw, 22px);
  left: clamp(15px, 2.2vw, 24px);
  height: 15px;
  width: auto;
  opacity: .92;
  filter: drop-shadow(0 1px 10px rgba(0, 20, 60, .35));
}
.thumb-figure { font-family: "Geist", sans-serif; line-height: 1; }
/* big stat (a number or short token) */
.thumb-figure .fig-lead {
  display: block;
  font-weight: 500;
  letter-spacing: -.035em;
  font-size: clamp(2.4rem, 5.4vw, 3.6rem);
  text-shadow: 0 2px 26px rgba(0, 18, 55, .3);
}
/* concept phrase variant — for posts with no headline number */
.thumb-figure.is-phrase .fig-lead {
  font-size: clamp(1.5rem, 3vw, 2rem);
  letter-spacing: -.02em;
  max-width: 11ch;
}
.thumb-figure .fig-sub {
  display: block;
  margin-top: .7em;
  font-size: .76rem;
  letter-spacing: .08em;
  text-transform: uppercase;
  font-weight: 500;
  opacity: .9;
}
/* featured card runs a touch larger */
.post-featured .thumb-figure .fig-lead { font-size: clamp(3rem, 5vw, 4.4rem); }
.post-card .tag { margin-bottom: 10px; }
.post-card h3 {
  font-weight: 500;
  font-size: 1.2rem;
  letter-spacing: -.02em;
  line-height: 1.3;
  transition: color .25s;
}
.post-card:hover h3 { color: var(--altitude); }
.post-card p { margin-top: 10px; font-size: .92rem; line-height: 1.6; flex-grow: 1; }
.post-meta { margin-top: 16px; display: flex; align-items: center; gap: 8px; font-size: .8rem; color: var(--ink-faint); }
.post-meta i { font-style: normal; width: 3px; height: 3px; border-radius: 50%; background: currentColor; opacity: .6; }

/* featured post — wide split */
.post-featured {
  display: grid;
  grid-template-columns: 1.05fr .95fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: center;
  margin-bottom: 56px;
}
.post-featured .post-thumb { aspect-ratio: 16 / 11; margin-bottom: 0; }
.post-featured h3 { font-size: clamp(1.7rem, 2.7vw, 2.4rem); font-weight: 400; letter-spacing: -.035em; line-height: 1.12; }
.post-featured p { font-size: 1rem; max-width: 48ch; }
.post-featured .link-arrow { margin-top: 24px; }

/* newsletter band */
.news-band {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 32px;
  align-items: center;
  padding: clamp(32px, 4vw, 48px);
  border-radius: calc(var(--radius-card) + 6px);
  background: var(--paper-dim);
}
.news-band h3 { font-size: clamp(1.4rem, 2.2vw, 1.9rem); font-weight: 400; letter-spacing: -.03em; }
.news-band p { margin-top: 8px; font-size: .95rem; }
.news-form { display: flex; gap: 10px; }
.news-form input {
  font: inherit;
  font-size: .9rem;
  width: min(300px, 60vw);
  padding: 0 16px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--paper);
  color: var(--ink);
  outline: none;
  transition: border-color .25s;
}
.news-form input:focus { border-color: var(--accent); }

/* ---------- Article prose ---------- */
.prose {
  max-width: 680px;
  margin: 0 auto;
  font-size: 1.0625rem;
  line-height: 1.75;
}
.prose > * + * { margin-top: 1.35em; }
.prose h2 {
  font-weight: 500;
  font-size: 1.65rem;
  letter-spacing: -.03em;
  line-height: 1.25;
  margin-top: 2.2em;
}
.prose h3 { font-weight: 500; font-size: 1.25rem; letter-spacing: -.02em; margin-top: 1.8em; }
.prose a { color: var(--altitude); text-decoration: underline; text-underline-offset: 3px; }
.prose ul, .prose ol { padding-left: 1.3em; display: flex; flex-direction: column; gap: .5em; }
.prose ul li::marker { color: var(--altitude); }
.prose blockquote {
  font-family: "Geist", Arial, sans-serif;
  font-style: italic;
  font-weight: 500;
  font-size: 1.35rem;
  line-height: 1.45;
  padding-left: 24px;
  border-left: 2px solid var(--altitude);
  color: var(--ink);
}
.prose figure { margin-block: 2.2em; }
.prose figcaption { margin-top: 12px; font-size: .82rem; color: var(--ink-faint); text-align: center; }
.prose .article-sky {
  position: relative;
  aspect-ratio: 16 / 8;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: linear-gradient(195deg, #1a61d1, #57a8ef 70%, #9ed0f6);
}
.prose .article-sky .deco-cloud { width: 64%; left: 50%; top: 54%; transform: translate(-50%, -50%); }

/* author row under the article */
.author-row {
  max-width: 680px;
  margin: 56px auto 0;
  padding-top: 32px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 16px;
}
.avatar {
  width: 52px; height: 52px;
  border-radius: 50%;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(160deg, #1a61d1, #57a8ef);
  color: var(--white);
  font-weight: 500;
  font-size: 1.05rem;
  object-fit: cover;
}
.author-row b { display: block; font-weight: 500; font-size: .98rem; }
.author-row span { font-size: .85rem; color: var(--ink-soft); }

/* ---------- About: team + values ---------- */
.team-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; max-width: 860px; margin: 0 auto; }
.team-card { border: 1px solid var(--line); border-radius: var(--radius-card); overflow: hidden; }
.team-photo {
  position: relative;
  aspect-ratio: 1 / 1;
  background: linear-gradient(170deg, #1a61d1, #2e8de4 55%, #79bdf2);
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.team-photo .deco-cloud { width: 88%; bottom: -18%; }
.team-photo .team-headshot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 12%;
}
/* soften where the photo meets the white caption */
.team-photo::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 22%;
  z-index: 2;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff);
  pointer-events: none;
}
.team-photo .team-initial {
  position: relative;
  z-index: 1;
  font-family: "Geist", Arial, sans-serif;
  font-weight: 600;
  font-size: clamp(4.5rem, 8vw, 7rem);
  color: rgba(255, 255, 255, .92);
  line-height: 1;
  margin-bottom: -2%;
}
.team-card figcaption { padding: 20px 24px; }
.team-card b { display: block; font-weight: 500; font-size: 1.1rem; }
.team-card span { font-size: .88rem; color: var(--ink-soft); }
.team-card figcaption p { margin-top: 12px; font-size: .9rem; color: var(--ink-soft); line-height: 1.55; }
.team-li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 14px;
  color: var(--ink-soft);
  transition: color .2s;
}
.team-li:hover { color: var(--ink); }
.team-li svg { width: 15px; height: 15px; flex-shrink: 0; }
.team-card .team-li span { font-size: .85rem; color: inherit; }
.values-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }

/* logo marquee on white (about page): force the client SVGs to ink */
.sheet .marquee-inner img { filter: brightness(0); opacity: .55; }

/* ---------- Testimonials page ---------- */
/* the home reviews live on the dark sky as glass cards; on the white sheet
   we flip the same .review-card markup to ink-on-paper */
.sheet .review-card {
  background: var(--paper);
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(27, 27, 27, .04), 0 20px 44px -30px rgba(27, 27, 27, .55);
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.sheet .review-card::before { color: var(--altitude); opacity: .14; }
.sheet .review-card blockquote { color: var(--ink); }
.sheet .review-card figcaption { border-top-color: var(--line); }
.sheet .review-name { color: var(--ink); }
.sheet .review-role { color: var(--ink-soft); opacity: 1; }
/* client SVGs are built white for the dark home page — ink them for paper */
.sheet .review-logo { filter: brightness(0); opacity: .55; }

/* one hero testimonial, then a masonry wall of the rest so the uneven
   quote lengths pack without gaps */
.testi-featured { max-width: 820px; margin: 0 auto clamp(16px, 2.2vw, 28px); }
.testi-featured.review-card { padding: clamp(30px, 4vw, 46px); }
.testi-wall { columns: 3; column-gap: 16px; }
.testi-wall .review-card { break-inside: avoid; margin: 0 0 16px; }

@media (max-width: 900px) { .testi-wall { columns: 2; } }
@media (max-width: 600px) { .testi-wall { columns: 1; } }

/* ---------- Contact page (lives in the sky, no sheet) ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  gap: clamp(36px, 5vw, 88px);
  align-items: start;
  max-width: var(--content-width);
  margin: 0 auto;
}
.contact-intro h1 { font-size: clamp(2.4rem, 4.2vw, 3.6rem); letter-spacing: -.045em; }
.contact-intro > p { margin-top: 20px; max-width: 42ch; font-size: 1.1rem; line-height: 1.55; opacity: .9; }
.contact-cards { margin-top: 40px; display: flex; flex-direction: column; gap: 12px; }
.contact-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 20px 24px;
  border-radius: var(--radius-card);
  background: rgba(255, 255, 255, .16);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid rgba(255, 255, 255, .22);
}
.contact-card span { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; opacity: .7; }
.contact-card b { font-weight: 500; font-size: 1.05rem; }
.contact-card small { font-size: .85rem; opacity: .8; }
a.contact-card { transition: background-color .3s; }
a.contact-card:hover { background: rgba(255, 255, 255, .24); }
/* the homepage form card, un-centred for the grid */
.contact-grid .cta-form { margin: 0; width: 100%; }
.contact-faq { max-width: 780px; margin: 0 auto; }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 1024px) {
  .case-grid { grid-template-columns: repeat(2, 1fr); }
  .post-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
  .case-featured,
  .post-featured,
  .sol-block,
  .cs-grid,
  .contact-grid,
  .news-band { grid-template-columns: 1fr; }
  .cs-facts { position: static; order: -1; }
  .steps, .result-grid, .values-grid, .team-grid { grid-template-columns: 1fr; }
  .cs-nav { grid-template-columns: 1fr; }
  .cs-nav .cs-nav-next { text-align: left; }
  .sol-no { font-size: 2.6rem; }
  .sol-head h3 { max-width: none; }
  .case-featured-visual {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-left: 0;
    padding-top: 28px;
  }
}

@media (max-width: 768px) {
  .page-hero { min-height: 46svh; padding-top: calc(var(--header-height) + var(--safe-top) + 40px); }
  .page-hero--tall { min-height: 64svh; }
  .page-title { font-size: clamp(2.1rem, 8.4vw, 2.7rem); }
  .page-sub { font-size: 1rem; }
  .sheet-head { margin-bottom: 40px; }
  .sheet-head .u-h2-large { font-size: clamp(1.9rem, 7.8vw, 2.6rem); }
  .case-grid, .post-grid { grid-template-columns: 1fr; }
  .case-featured { padding: 26px 22px; }
  .prose { font-size: 1rem; }
  .news-form { flex-direction: column; }
  .news-form input { width: 100%; }
  .stat-row-ink { flex-wrap: wrap; gap: 20px; }
  /* 16px floor: anything smaller makes iOS Safari zoom on focus */
  .news-form input { font-size: 16px; }
}
