@import url('https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@400;500;600&display=swap');

:root {
  --gh-navy: #041E42;
  --gh-violet: #654EA3;
  --gh-mid-blue: #326295;
  --gh-ice-blue: #DDE5ED;
  --gh-gold: #FFC845;
  --gh-charcoal: #333F48;
  --gh-near-black: #101820;
  --gh-white: #FFFFFF;
  --gh-black: #000000;

  --font-heading: 'Roboto Slab', Georgia, serif;
  --font-body: Arial, Helvetica, sans-serif;

  --max-width: 1160px;
  --gap-xs: 0.5rem;
  --gap-sm: 1rem;
  --gap-md: 2rem;
  --gap-lg: 4rem;
  --gap-xl: 7rem;

  /* Single source of truth for the page's left/right edge margin. The header
     uses this directly; page content sections use it as a floor (via max())
     so they can never sit closer to the edge than the header does, but can
     still grow further out on very wide screens where that's wanted. */
  --edge-margin: 8rem;
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--gh-charcoal);
  background: var(--gh-white);
  line-height: 1.6;
  font-size: 18px;
}

h1, h2, h3, h4, h5 {
  font-family: var(--font-heading);
  font-weight: 500;
  color: var(--gh-navy);
  line-height: 1.2;
  margin: 0 0 var(--gap-sm);
}

h1 { font-size: clamp(2.2rem, 4vw, 3rem); }
h2 { font-size: clamp(1.6rem, 3vw, 2rem); }
h3 { font-size: clamp(1.3rem, 2.4vw, 1.5rem); }
h4 { font-size: clamp(1.1rem, 2vw, 1.25rem); font-weight: 500; }

p { margin: 0 0 1rem; }

a {
  color: var(--gh-violet);
  text-decoration: none;
}
a:hover, a:focus-visible { text-decoration: underline; }

:focus-visible {
  outline: 3px solid var(--gh-gold);
  outline-offset: 2px;
}

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

.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--edge-margin);
}

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0);
  overflow: hidden;
  white-space: nowrap;
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: bold;
  font-size: 0.95rem;
  padding: 0.75rem 1.6rem;
  border-radius: 8px;
  text-decoration: none;
  transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.btn:hover, .btn:focus-visible { text-decoration: none; }

.btn-primary {
  background: var(--gh-violet);
  color: var(--gh-white);
  border: 1px solid var(--gh-violet);
}
.btn-primary:hover { background: #543f8a; border-color: #543f8a; }

.btn-outline {
  background: transparent;
  color: var(--gh-white);
  border: 1px solid var(--gh-white);
}
.btn-outline:hover { background: var(--gh-white); color: var(--gh-navy); }

.btn-outline-dark {
  background: transparent;
  color: var(--gh-navy);
  border: 1px solid var(--gh-navy);
}
.btn-outline-dark:hover { background: var(--gh-navy); color: var(--gh-white); }

/* ---------- Header / Nav ---------- */
/* Fixed rather than sticky: sticky depends on every ancestor up to the
   scrolling viewport having no clipping/scroll context, which is brittle
   and hard to guarantee. Fixed anchors directly to the viewport regardless
   of ancestors. js/main.js compensates by padding <main> down by the
   header's actual measured height so content doesn't start underneath it. */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  /* A 50% tint of ice blue toward white (#DDE5ED -> #EEF2F6). Full ice blue
     was the obvious choice but it is exactly what .bg-ice sections use, and
     this header is fixed, so an ice band scrolling underneath would merge with
     it and the header would appear to vanish. The tint keeps the brand hue
     while staying distinct from every band it passes over.

     The border does the real work: it guarantees a visible edge over white,
     over ice, over a navy CTA band and over the photo heroes alike. #C9D6E4 is
     the same line weight already used for card borders on ice. */
  background: #EEF2F6;
  border-bottom: 1px solid #C9D6E4;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--gh-navy);
  color: var(--gh-white);
  padding: 0.75rem 1.25rem;
  z-index: 200;
}
.skip-link:focus {
  left: 1rem;
  top: 0.5rem;
}

.nav-wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1.4rem var(--edge-margin);
}

.nav-logo img { height: 40px; width: auto; }

.nav-links {
  display: flex;
  /* baseline, not center: the items are different heights, so centering put
     their text on different lines. "Practices" sat 2.76px above "Partners"
     because the active page's border-bottom and padding make its box 4px
     taller, and centering a taller box lifts its text by half that. The two
     dropdown items were also off by 0.76px, since a .has-dropdown-row flex
     container is 24.3px tall against a plain <li>'s 28.8px line box.
     Aligning on the baseline makes the text line up regardless of box height,
     which is the thing that actually needs to match. Reserving the underline's
     space on every link does NOT fix this; it was measured and it doesn't.
     The mobile rule below re-sets align-items, so this is desktop only. */
  align-items: baseline;
  gap: 1.75rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The CTA is a filled pill rather than bare text, so keep it centred in the
   row instead of hanging off the shared text baseline. */
.nav-links > li > .nav-cta { align-self: center; }

.nav-links a {
  color: var(--gh-charcoal);
  font-size: 0.95rem;
  font-weight: bold;
}
.nav-links a:hover, .nav-links a:focus-visible,
.nav-links a[aria-current="page"] {
  color: var(--gh-violet);
}
.nav-links a[aria-current="page"] {
  border-bottom: 2px solid var(--gh-violet);
  padding-bottom: 2px;
  text-decoration: none;
}

.nav-cta {
  background: var(--gh-navy);
  color: var(--gh-white) !important;
  padding: 0.55rem 1.2rem;
  border-radius: 8px;
}
.nav-cta:hover { background: var(--gh-violet); text-decoration: none !important; }

.nav-toggle {
  display: none;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0.5rem;
}
.nav-toggle svg { width: 26px; height: 26px; }

/* ---------- Practices dropdown (desktop: hover/focus opens; also click-toggleable) ---------- */
.has-dropdown {
  position: relative;
}
.has-dropdown-row {
  display: flex;
  align-items: center;
}
.dropdown-toggle {
  background: none;
  border: none;
  padding: 0.35rem;
  margin-left: 0.15rem;
  cursor: pointer;
  color: inherit;
  display: flex;
  align-items: center;
}
.dropdown-toggle svg {
  width: 11px;
  height: 11px;
  transition: transform 0.15s ease;
}
.has-dropdown.is-open .dropdown-toggle svg {
  transform: rotate(180deg);
}
.dropdown-menu {
  list-style: none;
  margin: 0;
  padding: 0.5rem 0;
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 0.6rem;
  min-width: 240px;
  background: var(--gh-white);
  border: 1px solid var(--gh-ice-blue);
  border-radius: 4px;
  box-shadow: 0 10px 28px rgba(4, 30, 66, 0.14);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.15s ease, transform 0.15s ease, visibility 0.15s;
  z-index: 200;
}
.dropdown-menu li { width: 100%; }
.dropdown-menu a {
  display: block;
  padding: 0.65rem 1.25rem;
  font-size: 0.9rem;
  font-weight: normal;
  color: var(--gh-charcoal);
  white-space: nowrap;
}
.dropdown-menu a:hover, .dropdown-menu a:focus-visible {
  background: var(--gh-ice-blue);
  color: var(--gh-violet);
  text-decoration: none;
}
@media (min-width: 901px) {
  .has-dropdown:hover .dropdown-menu,
  .has-dropdown:focus-within .dropdown-menu,
  .has-dropdown.is-open .dropdown-menu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }
  .has-dropdown:hover .dropdown-toggle svg,
  .has-dropdown:focus-within .dropdown-toggle svg {
    transform: rotate(180deg);
  }
}

/* The gap between the mobile breakpoint and a comfortable desktop. The full
   horizontal nav is still shown down to 901px, but --edge-margin was 8rem all
   the way down, and 256px of margin does not leave room for it: the logo is
   198px and the nav 555px, so one line needs roughly 1033px of viewport. Below
   that the nav wrapped and ran into the logo, which is what a ~900px window
   showed.

   Stepping the margin down to 2rem keeps everything on one line to 901px,
   where the hamburger takes over: 198 + 555 + 64 + breathing room fits inside
   861. It also un-squeezes the home hero, whose text column reserves 400px
   plus this margin before the photo gets any width at all. */
@media (max-width: 1100px) {
  :root { --edge-margin: 2rem; }
  /* Margin alone is not enough. Measured at 880px: logo 211px, nav items
     451px, and five 1.75rem gaps add another 140px, so one line needs 889px
     of viewport and the nav wrapped into the logo at anything under that.
     A 1rem gap brings the requirement to 829px, which clears the 901px
     hamburger breakpoint with room to spare. */
  .nav-links { gap: 1rem; }
}

@media (max-width: 900px) {
  :root { --edge-margin: 1.5rem; }
  .nav-toggle { display: block; }
  .nav-links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--gh-white);
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    border-bottom: 1px solid var(--gh-ice-blue);
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.25s ease;
  }
  .nav-links.is-open { max-height: 720px; }
  .nav-links li { width: 100%; }
  .nav-links a {
    display: block;
    padding: 1rem 1.5rem;
    width: 100%;
    border-bottom: 1px solid var(--gh-ice-blue);
  }
  .nav-cta { border-radius: 0; }

  /* Practices becomes a tap-to-expand accordion instead of a hover dropdown */
  .has-dropdown {
    position: static;
  }
  .has-dropdown-row {
    display: flex;
    align-items: stretch;
    width: 100%;
    border-bottom: 1px solid var(--gh-ice-blue);
  }
  .has-dropdown-row > a { flex: 1; border-bottom: none; }
  .dropdown-toggle {
    flex-shrink: 0;
    width: 52px;
    justify-content: center;
    margin-left: 0;
  }
  .dropdown-menu {
    position: static;
    width: 100%;
    min-width: 0;
    margin-top: 0;
    background: var(--gh-ice-blue);
    border: none;
    border-radius: 0;
    box-shadow: none;
    opacity: 1;
    visibility: visible;
    transform: none;
    max-height: 0;
    overflow: hidden;
    padding: 0;
    transition: max-height 0.25s ease;
  }
  .has-dropdown.is-open .dropdown-menu { max-height: 220px; }
  .dropdown-menu a {
    padding: 0.85rem 1.5rem 0.85rem 2.5rem;
    border-bottom: 1px solid rgba(4, 30, 66, 0.08);
  }
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  background: linear-gradient(135deg, var(--gh-navy) 0%, var(--gh-near-black) 100%);
  color: var(--gh-white);
  overflow: hidden;
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(circle at 82% 20%, rgba(101,78,163,0.55) 0%, transparent 45%),
    radial-gradient(circle at 15% 85%, rgba(50,98,149,0.4) 0%, transparent 50%);
  pointer-events: none;
}
.hero-inner {
  position: relative;
  padding-top: var(--gap-xl);
  padding-bottom: var(--gap-lg);
  /* Left edge matches the site's standard container/nav alignment exactly (same
     formula used elsewhere), so it doesn't shift even as the block below grows wider.
     Floored at --edge-margin so it's never smaller than the header's own margin. */
  padding-left: max(var(--edge-margin), calc((100vw - var(--max-width)) / 2));
  padding-right: 1.5rem;
}
.hero h1 { color: var(--gh-white); max-width: 24ch; }
.hero .eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.95rem;
  font-weight: bold;
  color: var(--gh-gold);
  margin-bottom: 0.75rem;
}
.hero .lede {
  font-size: 1.4rem;
  max-width: 46ch;
  color: var(--gh-ice-blue);
}
.hero-cta { margin-top: 1.75rem; display: flex; gap: 1rem; flex-wrap: wrap; }

/* Photo-background hero variant (e.g. People page): a real image sits behind the
   headline instead of the plain gradient, with a dark tint overlay so white text
   stays legible over any photo. */
.hero-photo {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.hero-photo::before {
  background-image: none;
  background: linear-gradient(90deg, rgba(4,30,66,0.55) 0%, rgba(4,30,66,0.15) 100%);
}

/* ---------- Home hero (text + image split, image bleeds to viewport edge) ---------- */
/* Image height is synced to the text column's rendered height via JS (see js/main.js,
   syncHeroHeight) rather than CSS align-items:stretch. Stretch-based approaches hit a
   circular-reference edge case: an <img> with height:100% can't resolve that percentage
   while the row's own height is still being computed, so browsers fall back to the
   image's raw intrinsic pixel size to help size the row — inflating it regardless of
   text content or padding. Measuring the text height directly in JS avoids that entirely. */
.home-hero { overflow: hidden; }
.home-hero .hero-flex {
  display: flex;
  align-items: flex-start;
}
.home-hero .hero-copy {
  flex: 0 0 auto;
  min-width: 400px;   /* <-- the text column's minimum width lives here */
  max-width: 650px;   /* <-- and its maximum width lives here */
  margin-left: max(var(--edge-margin), calc((100vw - var(--max-width)) / 2));
  padding: 6rem 2rem 6rem 0;
  box-sizing: border-box;
}
.home-hero h1 {
  max-width: 14ch;
  font-size: clamp(2.8rem, 5.5vw, 4.25rem);
}
.home-hero h2.lede {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: clamp(1.3rem, 2.4vw, 1.6rem);
  color: var(--gh-charcoal);
  max-width: 48ch;
  margin-bottom: 1rem;
}

.home-hero .hero-image-wrap {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  /* height is set inline by js/main.js to match .hero-copy exactly */
}
.home-hero .hero-image {
  display: block;
  height: 100%;
  width: auto;
  max-width: none; /* width follows the image's own aspect ratio and may bleed past the edge */
}

@media (max-width: 900px) {
  .home-hero .hero-flex { flex-direction: column; }
  .home-hero .hero-copy { margin-left: 0; min-width: 0; max-width: none; width: 100%; padding: 2rem 1.5rem; }
  .home-hero .hero-image-wrap { width: 100%; height: auto !important; order: -1; }
  .home-hero .hero-image {
    width: 100%;
    height: auto;
    max-width: 100%; /* on small screens, fit the viewport instead of bleeding/overflowing */
  }
}
/* ---------- Section divider ---------- */
.divider {
  height: 1px;
  background: var(--gh-ice-blue);
  max-width: var(--max-width);
  margin: 0 auto;
}
.divider.on-dark { background: rgba(255,255,255,0.16); }

/* ---------- Sections ---------- */
section { padding: var(--gap-lg) 0; }
.section-tight { padding: var(--gap-md) 0; }
.bg-ice { background: var(--gh-ice-blue); }
.bg-navy { background: var(--gh-navy); color: var(--gh-white); }
.bg-navy h2, .bg-navy h3, .bg-navy h4 { color: var(--gh-white); }

.section-head { max-width: 75ch; margin-bottom: var(--gap-md); }
.section-head.center { margin-left: auto; margin-right: auto; text-align: center; }
.section-head.block-center { margin-left: auto; margin-right: auto; text-align: left; }

/* Icon row that sits under the hero-adjacent text block on the Analytics page (used together with .grid-3) */
.hero-follow-icons { max-width: 75ch; margin: 1.75rem auto 0; justify-items: center; }

/* ---------- Cards / Grids ---------- */
.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--gap-md);
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 5rem;
}
@media (max-width: 900px) {
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
}

.feature-card {
  background: var(--gh-white);
  border: 1px solid var(--gh-ice-blue);
  border-radius: 4px;
  padding: 1.75rem;
  color: var(--gh-violet); /* default icon color via inheritance + currentColor; .practice-card overrides this per-card */
}
.feature-card img.icon,
.feature-card svg.icon {
  width: 40px;
  height: 40px;
  margin-bottom: 1rem;
}
.feature-card h4, .feature-card p { color: var(--gh-charcoal); }
.feature-card h4 { margin-bottom: 0.5rem; }
.feature-card p { margin-bottom: 0; font-size: 0.95rem; }

/* Practice hub cards (Practices page): three offerings, each with a small accent
   color so they read as distinct products rather than three identical boxes */
.practice-card {
  border-top: 3px solid var(--gh-violet);
  display: flex;
  flex-direction: column;
  color: var(--gh-violet); /* sets icon color via currentColor; text below overrides its own color as normal */
}
.practice-card h3, .practice-card h4, .practice-card p { color: var(--gh-charcoal); }
.practice-card .icon { width: 44px; height: 44px; margin-bottom: 1rem; fill: currentColor; }
.practice-card h3, .practice-card h4 { margin-bottom: 0.5rem; }
.practice-card p { margin-bottom: 1.25rem; flex-grow: 1; }

/* A three-column card is narrow enough that a short question heading wraps with
   a single word stranded on the last line — "What do we do about / it?".
   Balancing splits the lines evenly instead. */
.practice-card h3, .practice-card h4, .feature-card h4 { text-wrap: balance; }
/* The three offerings previously took mid-blue / violet / gold in order. They
   are one family of services rather than three unrelated things, so they now
   share the violet accent set on .practice-card above. Adding a fourth card
   needs no rule here; it inherits the same accent. */

/* Homepage audience-split cards ("For independent practices" / "For GPOs & billing companies") */
.audience-card {
  padding: 2.25rem;
  border-top: 3px solid var(--gh-mid-blue);
  display: flex;
  flex-direction: column;
}
.audience-card h3 { margin-bottom: 0.75rem; }
.audience-card p { margin-bottom: 1.5rem; flex-grow: 1; }
.audience-card:nth-child(2) { border-top-color: var(--gh-violet); }

/* ---------- Placeholder photo panel ---------- */
.photo-panel {
  border-radius: 4px;
  aspect-ratio: 4 / 3;
  background: linear-gradient(135deg, var(--gh-mid-blue) 0%, var(--gh-violet) 100%);
  position: relative;
  overflow: hidden;
}
.photo-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: repeating-linear-gradient(45deg, rgba(255,255,255,0.05) 0 2px, transparent 2px 14px);
}
.photo-panel .replace-note {
  position: absolute;
  bottom: 0.75rem;
  left: 0.75rem;
  right: 0.75rem;
  font-size: 0.7rem;
  color: rgba(255,255,255,0.85);
  background: rgba(0,0,0,0.25);
  padding: 0.4rem 0.6rem;
  border-radius: 3px;
  font-family: var(--font-body);
}

/* ---------- Selected experience list (Consulting) ---------- */
.experience-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.experience-list li {
  display: flex;
  gap: 1rem;
  padding-bottom: 0.3rem;
  border-bottom: 1px solid var(--gh-ice-blue);
}
.experience-list li:last-child { border-bottom: none; padding-bottom: 0; }
.experience-list .mark {
  flex-shrink: 0;
  color: var(--gh-violet);
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 1.3rem;
  line-height: 1.4;
}

/* ---------- People bios ---------- */
.bio-card {
  display: grid;
  grid-template-columns: 160px 1fr;
  gap: 1.75rem;
  align-items: start;
  padding: var(--gap-md) 0;
  border-bottom: 1px solid var(--gh-ice-blue);
}
.bio-card:last-child { border-bottom: none; }
.bio-photo {
  width: 140px;
  height: 140px;
  border-radius: 8px;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--gh-ice-blue); /* shows briefly if the image is missing/slow to load */
}
.bio-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.bio-card h3 { margin-bottom: 0.15rem; }
.bio-card .role { color: var(--gh-violet); font-weight: bold; font-size: 0.9rem; margin-bottom: 0.75rem; }
@media (max-width: 640px) {
  .bio-card { grid-template-columns: 1fr; }
  .bio-photo { width: 100px; height: 100px; }
}

/* ---------- Modal (ROI calculator on the homepage) ---------- */
/* Uses the [hidden] attribute rather than a class so the dialog is genuinely
   hidden from assistive tech when closed, not just visually. */
.modal[hidden] { display: none; }
.modal {
  position: fixed;
  inset: 0;
  z-index: 1200;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3vh 1rem;
  background: rgba(4, 30, 66, 0.62);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.modal-panel {
  position: relative;
  background: var(--gh-white);
  border-radius: 10px;
  width: 100%;
  max-width: 940px;
  box-shadow: 0 24px 60px rgba(4, 30, 66, 0.35);
  margin: auto 0;
}
.modal-close {
  position: absolute;
  top: 10px;
  right: 12px;
  z-index: 2;
  width: 38px;
  height: 38px;
  border: 0;
  border-radius: 50%;
  background: var(--gh-ice-blue);
  color: var(--gh-navy);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
.modal-close:hover { background: var(--gh-violet); color: var(--gh-white); }
/* Stops the page behind the dialog scrolling on desktop and iOS. */
body.modal-open { overflow: hidden; }

/* ---------- ROI teaser band ---------- */
.roi-teaser { text-align: center; }
.roi-teaser .lede { margin: 0 auto 1.5rem; max-width: 46ch; }

/* ---------- Stat grid (proof points) ---------- */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2rem;
  text-align: center;
}
.stat-grid.cols-3 { grid-template-columns: repeat(3, 1fr); }
.stat-number {
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: clamp(2rem, 4vw, 2.75rem);
  color: var(--gh-violet);
  line-height: 1.1;
  margin-bottom: 0.4rem;
}
.stat-label {
  font-size: 0.9rem;
  color: var(--gh-charcoal);
  line-height: 1.4;
}
@media (max-width: 760px) {
  .stat-grid, .stat-grid.cols-3 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .stat-grid, .stat-grid.cols-3 { grid-template-columns: 1fr; }
}

/* ---------- Testimonials ---------- */
.testimonial-card {
  background: var(--gh-white);
  /* Outlined rather than relying on background contrast: these cards are white
     and sit on white on the homepage, so without a border their edges vanish
     and the three quotes read as one block of text. */
  border: 1px solid var(--gh-ice-blue);
  border-radius: 6px;
  padding: 2rem 1.75rem;
  display: flex;
  flex-direction: column;
  height: 100%;
  box-shadow: 0 1px 3px rgba(4, 30, 66, 0.05);
}
/* On the ice-blue band a plain 1px ice border would disappear into the
   background, so darken it just enough to stay visible there. */
.bg-ice .testimonial-card { border-color: #c9d6e4; }
.testimonial-quote {
  font-family: var(--font-heading);
  font-size: 1.05rem;
  color: var(--gh-navy);
  line-height: 1.5;
  flex-grow: 1;
  margin-bottom: 1.25rem;
}
.testimonial-attribution {
  font-size: 0.85rem;
  font-weight: bold;
  color: var(--gh-violet);
  margin-bottom: 0;
  line-height: 1.4;
}

/* ---------- Quote carousel (homepage) ---------- */
/* A scroll-snap strip, not a transform-driven slider. Snapping means the
   browser owns the animation, touch swiping and momentum work natively on
   mobile, and with JS off the markup is still a readable, scrollable row of
   quotes rather than four hidden ones. */
.quotes-track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Arrows and dots drive this, so the strip's own scrollbar is just noise.
     Three properties because no single one covers Firefox, WebKit and Edge. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.quotes-track::-webkit-scrollbar { display: none; }
/* The track is focusable so the strip can be paged with arrow keys; without a
   visible ring that focus would be invisible to a keyboard user. */
.quotes-track:focus-visible { outline: 2px solid var(--gh-violet); outline-offset: 6px; }

/* Slides sit side by side at full width, so the track is as tall as the
   longest quote and nothing shifts as it pages. */
.quotes-slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  margin: 0;
  padding: 0 1rem;
  text-align: center;
}
.quotes-slide blockquote {
  margin: 0 auto 1.25rem;
  max-width: 60ch;
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 1.35rem;
  line-height: 1.5;
  color: var(--gh-navy);
}
.quotes-slide figcaption {
  font-size: 0.85rem;
  font-weight: bold;
  color: var(--gh-violet);
  line-height: 1.4;
}

/* Built by initQuotes in js/main.js, so controls never render without the
   script that makes them work. */
.quotes-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.25rem;
  margin-top: 2rem;
}
.quotes-arrow {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0;
  border: 1px solid var(--gh-ice-blue);
  border-radius: 50%;
  background: var(--gh-white);
  color: var(--gh-navy);
  cursor: pointer;
  transition: border-color 0.2s, color 0.2s;
}
.quotes-arrow:hover { border-color: var(--gh-violet); color: var(--gh-violet); }
.quotes-arrow svg { width: 1rem; height: 1rem; }

.quotes-dots { display: flex; gap: 0.5rem; }
.quotes-dot {
  width: 0.5rem;
  height: 0.5rem;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--gh-ice-blue);
  cursor: pointer;
  transition: background 0.2s, transform 0.2s;
}
.quotes-dot[aria-selected="true"] { background: var(--gh-violet); transform: scale(1.3); }

@media (max-width: 600px) {
  .quotes-slide blockquote { font-size: 1.1rem; }
}

/* ---------- Floating ROI nudge (homepage) ---------- */
/* Off-screen by default and slid in by a class, so it animates in rather than
   appearing mid-page, and so it costs nothing until initRoiNudge decides the
   reader has scrolled far enough to see it. */
.roi-nudge {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  /* Above the page, below .modal (1200) -- it must not sit over the dialog it
     opens. */
  z-index: 90;
  display: flex;
  align-items: flex-start;
  max-width: min(27rem, calc(100vw - 2.5rem));
  background: var(--gh-navy);
  border-radius: 10px;
  box-shadow: 0 12px 32px rgba(4, 30, 66, 0.35);
  transform: translateY(calc(100% + 2rem));
  transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.roi-nudge.is-visible { transform: none; }

.roi-nudge-cta {
  flex: 1;
  padding: 1.35rem 0.5rem 1.35rem 1.5rem;
  border: none;
  background: none;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
}
.roi-nudge-label {
  display: block;
  font-family: var(--font-heading);
  font-weight: 500;
  font-size: 1.15rem;
  line-height: 1.35;
  color: var(--gh-white);
}
.roi-nudge-meta {
  display: block;
  margin-top: 0.45rem;
  font-size: 0.85rem;
  color: var(--gh-gold);
}
.roi-nudge-cta:hover .roi-nudge-label { text-decoration: underline; }

/* The whole panel is one button, but at a glance it reads as a notification
   rather than something to click. The arrow is what says otherwise. */
.roi-nudge-arrow {
  display: inline-block;
  transition: transform 0.2s;
}
.roi-nudge-cta:hover .roi-nudge-arrow { transform: translateX(4px); }

.roi-nudge-close {
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  margin: 0.4rem 0.4rem 0 0;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--gh-ice-blue);
  font-size: 1.35rem;
  line-height: 1;
  cursor: pointer;
}
.roi-nudge-close:hover { background: rgba(255, 255, 255, 0.12); color: var(--gh-white); }

/* ---------- News list ---------- */
.news-list { list-style: none; margin: 0; padding: 0; }
.news-list li {
  padding: 1.1rem 0;
  border-bottom: 1px solid var(--gh-ice-blue);
  font-size: 0.98rem;
}
.news-list li:last-child { border-bottom: none; }
.news-list .news-date { color: var(--gh-charcoal); opacity: 0.7; font-size: 0.85rem; }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--gh-near-black);
  color: var(--gh-ice-blue);
  padding: var(--gap-lg) 0 var(--gap-md);
}
.footer-sitemap {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
  padding-bottom: var(--gap-md);
  margin-bottom: var(--gap-md);
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}
.footer-col h4 {
  color: var(--gh-white);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 0.9rem;
}
.footer-col ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.footer-col a { color: var(--gh-ice-blue); font-size: 0.9rem; }
.footer-col a:hover { color: var(--gh-gold); }
@media (max-width: 640px) {
  .footer-sitemap { grid-template-columns: 1fr; gap: 1.5rem; }
}

.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
}
.footer-inner a { color: var(--gh-ice-blue); }
.footer-inner a:hover { color: var(--gh-gold); }
.footer-copy { font-size: 0.85rem; opacity: 0.85; margin: 0; }
.footer-links { display: flex; gap: 1.5rem; align-items: center; list-style: none; margin: 0; padding: 0; }

/* ---------- Case study ---------- */
/* .eyebrow is only styled inside .hero, where it sits gold on a dark photo.
   This is the light-background equivalent. */
.case-eyebrow {
  font-size: 0.8rem;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--gh-violet);
  margin: 0 0 0.5rem;
}

.case-client {
  font-family: var(--font-heading);
  font-size: 1.05rem;
  color: var(--gh-mid-blue);
  margin: 0;
}

.case-steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Generous column gap: with no boxes around them, whitespace is the only
     thing separating one step from the next, so 2rem read as crowded. */
  gap: 4rem;
  margin-bottom: var(--gap-lg);
}

/* A top rule rather than a bordered box, so this reads as a different kind of
   content from the feature cards in the next section, which are boxed. */
.case-step { border-top: 3px solid var(--gh-violet); padding-top: 1.25rem; }

.case-step h4 {
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: bold;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--gh-charcoal);
  margin: 0 0 0.6rem;
}

.case-step p { margin: 0; }

/* Three columns stop being readable well before the mobile breakpoint: the
   container is 1160px with 128px of side padding, so at a 900px viewport each
   column is only ~183px, turning a short paragraph into a 16-line ribbon.
   Below that the steps become rows instead, label beside text, which keeps the
   line length sane at every width in between. */
@media (max-width: 1080px) {
  .case-steps { grid-template-columns: 1fr; gap: 2.75rem; }
  .case-step {
    display: grid;
    grid-template-columns: 10rem 1fr;
    gap: 2rem;
    align-items: start;
  }
}

/* Too narrow for a side-by-side label; put it back above the text. */
@media (max-width: 600px) {
  .case-step { grid-template-columns: 1fr; gap: 0.6rem; }
}

/* ---------- Partner logo rail ---------- */
.logo-rail-band { padding-top: var(--gap-md); padding-bottom: var(--gap-md); }

.logo-rail-label {
  margin: 0 0 1.75rem;
  text-align: center;
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gh-mid-blue);
}

.logo-rail { overflow: hidden; }

.logo-rail-track {
  display: flex;
  width: max-content;
}

.logo-rail-group {
  display: flex;
  align-items: center;
  gap: 5rem;
  margin: 0;
  padding: 0 2.5rem;
  list-style: none;
}

.logo-rail-item { display: flex; align-items: center; justify-content: center; }

/* Logos are sized by height so marks of different widths sit on one baseline. */
.logo-rail-item img { display: block; height: 60px; width: auto; }

.logo-rail-text {
  font-family: 'Roboto Slab', Georgia, serif;
  font-weight: 500;
  font-size: 1.05rem;
  color: var(--gh-navy);
  white-space: nowrap;
}

/* is-scrolling / is-static are set by initLogoRail in js/main.js based on
   whether the logos actually overflow the band. Neither is applied until it
   has measured, so the rail sits still rather than animating a short list. */
.logo-rail.is-scrolling .logo-rail-track {
  animation: logo-rail-scroll 45s linear infinite;
}
.logo-rail.is-scrolling:hover .logo-rail-track { animation-play-state: paused; }

.logo-rail.is-static .logo-rail-track { width: 100%; justify-content: center; }
.logo-rail.is-static .logo-rail-group[aria-hidden="true"] { display: none; }

@keyframes logo-rail-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* A wide mark at full height can outgrow a phone, so ease the height and the
   spacing rather than letting the band scroll sideways. */
@media (max-width: 600px) {
  .logo-rail-item img { height: 46px; }
  .logo-rail-group { gap: 3rem; padding: 0 1.5rem; }
}

/* ---------- Utility ---------- */
.mt-0 { margin-top: 0; }
.text-center { text-align: center; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; }
  /* The rule above only covers transitions, so stop the rail explicitly. */
  .logo-rail .logo-rail-track { animation: none !important; }
  /* Paging the carousel should jump, not glide. initQuotes also skips
     auto-advance entirely under this preference. */
  .quotes-track { scroll-behavior: auto !important; }
  /* Without its transition the nudge would otherwise stay parked off-screen,
     since that is what the untransitioned transform says. */
  .roi-nudge { transform: none; }
  .roi-nudge:not(.is-visible) { display: none; }
}

/* =========================================================================
   ROI CALCULATOR (Analytics alt page)
   Scoped under .roi-calculator so it can be injected directly into the page
   without colliding with the rest of the site's styles. Originally a fully
   standalone file (roi-calculator.html, still kept as-is for anyone who
   wants to link to it directly) — only the `body` and bare
   `input[type="range"]` selectors needed scoping; everything else was
   already namespaced under calculator-specific class names with no overlap.
   ========================================================================= */

  :root {
    --gh-navy:      #041E42;
    --gh-violet:    #654EA3;
    --gh-mid-blue:  #326295;
    --gh-ice-blue:  #DDE5ED;
    --gh-gold:      #FFC845;
    --gh-charcoal:  #333F48;
    --gh-near-black:#101820;
    --gh-white:     #FFFFFF;
  }

  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  .roi-calculator {
    font-family: Arial, Helvetica, sans-serif;
    background: var(--gh-white);
    color: var(--gh-charcoal);
  }

  .page {
    max-width: 980px;
    margin: 0 auto;
    padding: 32px 24px 64px;
  }

  /* ── Header ── */
  .header { text-align: center; margin-bottom: 44px; }

  .header-logo-fallback {
    display: inline-block;
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 22px;
    color: var(--gh-navy);
    letter-spacing: 3px;
    margin-bottom: 28px;
  }

  .header h1 {
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 38px;
    color: var(--gh-navy);
    line-height: 1.2;
    margin-bottom: 14px;
  }

  .header p {
    font-size: 16px;
    color: var(--gh-charcoal);
    max-width: 580px;
    margin: 0 auto;
    line-height: 1.65;
  }

  /* ── Card ── */
  .card {
    background: var(--gh-white);
    border-radius: 14px;
    box-shadow: 0 6px 32px rgba(4, 30, 66, 0.13);
    overflow: hidden;
  }

  .card-body { display: grid; grid-template-columns: 1fr 1fr; }

  /* ── Inputs panel ── */
  .inputs {
    padding: 40px 38px;
    border-right: 2px solid var(--gh-ice-blue);
  }

  .inputs h2 {
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 21px;
    color: var(--gh-navy);
    margin-bottom: 28px;
  }

  .field { margin-bottom: 24px; }

  .f-label {
    display: block;
    font-size: 13px;
    font-weight: bold;
    color: var(--gh-navy);
    margin-bottom: 9px;
  }

  /* Specialty */
  .specialty-select {
    width: 100%;
    padding: 10px 38px 10px 13px;
    border: 2px solid var(--gh-ice-blue);
    border-radius: 8px;
    font-family: Arial, Helvetica, sans-serif;
    font-size: 14px;
    color: var(--gh-charcoal);
    background-color: var(--gh-white);
    outline: none;
    cursor: pointer;
    appearance: none;
    -webkit-appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23654EA3' stroke-width='2' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
    transition: border-color 0.15s;
  }

  .specialty-select:focus { border-color: var(--gh-violet); }

  /* Standard slider row */
  .slider-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 9px;
  }

  .slider-val {
    font-size: 16px;
    font-weight: bold;
    color: var(--gh-violet);
  }

  .slider-val.flash { animation: flash 0.35s ease; }

  @keyframes flash {
    0%   { opacity: 1; }
    30%  { opacity: 0.3; color: var(--gh-gold); }
    100% { opacity: 1; color: var(--gh-violet); }
  }

  .roi-calculator input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 5px;
    border-radius: 3px;
    background: var(--gh-ice-blue);
    outline: none;
    cursor: pointer;
  }

  .roi-calculator input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--gh-violet);
    cursor: pointer;
    box-shadow: 0 2px 7px rgba(101, 78, 163, 0.38);
    transition: transform 0.12s;
  }

  .roi-calculator input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.15); }

  .roi-calculator input[type="range"]::-moz-range-thumb {
    width: 20px;
    height: 20px;
    border: none;
    border-radius: 50%;
    background: var(--gh-violet);
    cursor: pointer;
  }

  .range-ends {
    display: flex;
    justify-content: space-between;
    font-size: 11px;
    color: #bbb;
    margin-top: 4px;
  }

  .field-hint {
    font-size: 11.5px;
    color: #999;
    margin-top: 6px;
    line-height: 1.4;
  }

  /* Billing health cards */
  .billing-cards {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 7px;
  }

  .bcard {
    padding: 12px 7px 10px;
    border: 2px solid var(--gh-ice-blue);
    border-radius: 9px;
    cursor: pointer;
    text-align: center;
    transition: border-color 0.15s, background 0.15s;
    user-select: none;
    position: relative;
  }

  .bcard:hover { border-color: #aab8c8; }

  .bcard.active {
    border-color: var(--gh-navy);
    background: rgba(4, 30, 66, 0.04);
  }

  .bcard.active::after {
    content: '✓';
    position: absolute;
    top: 5px;
    right: 7px;
    font-size: 10px;
    color: var(--gh-violet);
    font-weight: bold;
  }

  .bcard-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    margin: 0 auto 6px;
  }

  .bcard[data-val="good"]    .bcard-dot { background: #22c55e; }
  .bcard[data-val="average"] .bcard-dot { background: var(--gh-gold); }
  .bcard[data-val="poor"]    .bcard-dot { background: #ef4444; }

  .bcard-title {
    font-size: 11.5px;
    font-weight: bold;
    color: var(--gh-navy);
    margin-bottom: 3px;
    line-height: 1.2;
  }

  .bcard-desc {
    font-size: 10px;
    color: #999;
    line-height: 1.3;
  }

  /* ── Assumptions section ── */
  .assumptions {
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--gh-ice-blue);
  }

  .assumptions-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 14px;
  }

  .assumptions-title {
    font-size: 12px;
    font-weight: bold;
    color: var(--gh-navy);
    text-transform: uppercase;
    letter-spacing: 0.8px;
  }

  .assumptions-hint {
    font-size: 10.5px;
    color: #bbb;
    font-style: italic;
  }

  .assum-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 11px;
  }

  .assum-row:last-child { margin-bottom: 0; }

  .assum-label {
    font-size: 12.5px;
    color: var(--gh-charcoal);
    width: 148px;
    flex-shrink: 0;
    line-height: 1.3;
  }

  .assum-control {
    flex: 1;
    display: flex;
    align-items: center;
    gap: 9px;
  }

  .assum-control input[type="range"] {
    flex: 1;
    height: 4px;
  }

  .assum-control input[type="range"]::-webkit-slider-thumb {
    width: 17px;
    height: 17px;
  }

  .assum-val {
    font-size: 13px;
    font-weight: bold;
    color: var(--gh-violet);
    width: 54px;
    text-align: right;
    flex-shrink: 0;
  }

  /* ── Results panel ── */
  .results {
    padding: 40px 38px;
    background: var(--gh-navy);
    color: var(--gh-white);
  }

  .results h2 {
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 21px;
    color: var(--gh-white);
    margin-bottom: 24px;
  }

  /* ROI hero */
  .roi-hero {
    background: var(--gh-violet);
    border-radius: 10px;
    padding: 20px;
    text-align: center;
    margin-bottom: 24px;
  }

  .roi-eyebrow {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 2px;
    color: rgba(255,255,255,0.68);
    margin-bottom: 5px;
  }

  .roi-number {
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 54px;
    color: var(--gh-gold);
    line-height: 1;
    margin-bottom: 3px;
  }

  .roi-caption { font-size: 13px; color: rgba(255,255,255,0.78); }

  /* Breakdown */
  .breakdown { margin-bottom: 18px; }

  .b-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 11px 0;
    border-bottom: 1px solid rgba(255,255,255,0.09);
    gap: 14px;
  }

  .b-row:last-child { border-bottom: none; }

  .b-label { flex: 1; }

  .b-title {
    font-size: 13.5px;
    font-weight: bold;
    color: var(--gh-white);
    margin-bottom: 2px;
  }

  .b-desc {
    font-size: 11.5px;
    color: rgba(255,255,255,0.55);
    line-height: 1.4;
  }

  .b-amount {
    font-size: 15px;
    font-weight: bold;
    color: var(--gh-gold);
    white-space: nowrap;
    text-align: right;
  }

  /* Total bar */
  .total-bar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: rgba(255,255,255,0.08);
    border-radius: 8px;
    padding: 14px 16px;
    margin-bottom: 12px;
  }

  .total-bar .t-label {
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 15px;
    color: var(--gh-white);
  }

  .total-bar .t-value {
    font-family: 'Roboto Slab', Georgia, serif;
    font-weight: 500;
    font-size: 24px;
    color: var(--gh-gold);
  }

  /* Cost line */
  .cost-line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 9px 0;
    margin-bottom: 18px;
    border-top: 1px solid rgba(255,255,255,0.12);
  }

  .cost-line .c-label { font-size: 12.5px; color: rgba(255,255,255,0.6); }
  .cost-line .c-value { font-size: 13.5px; color: rgba(255,255,255,0.82); }

  /* CTA */
  .cta {
    display: block;
    width: 100%;
    padding: 14px;
    background: var(--gh-gold);
    color: var(--gh-navy);
    font-family: Arial, Helvetica, sans-serif;
    font-size: 15px;
    font-weight: bold;
    text-align: center;
    text-decoration: none;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    letter-spacing: 0.4px;
    transition: opacity 0.15s, transform 0.12s;
  }

  .cta:hover { opacity: 0.9; transform: translateY(-1px); }

  /* Methodology */
  .method {
    margin-top: 16px;
    padding: 11px 13px;
    background: rgba(255,255,255,0.05);
    border-radius: 6px;
  }

  .method p {
    font-size: 10.5px;
    color: rgba(255,255,255,0.4);
    line-height: 1.55;
  }

  /* Card footer */
  .card-footer {
    padding: 13px 38px;
    background: #f0f4f8;
    border-top: 1px solid var(--gh-ice-blue);
    font-size: 11px;
    color: #aaa;
    text-align: center;
  }

  /* ── Responsive ── */
  @media (max-width: 720px) {
    .card-body { grid-template-columns: 1fr; }
    .inputs { border-right: none; border-bottom: 2px solid var(--gh-ice-blue); }
    .header h1 { font-size: 28px; }
    .roi-number { font-size: 46px; }
    .inputs, .results { padding: 30px 22px; }
  }
  