/* =============================================================================
   Exactitude · Design System (Rebuild v2)
   Editorial minimalism — beige + ink + functional accents only.
   Reference: Stripe docs, Linear. Report detail IA: Mordor Intelligence.
   ============================================================================= */

:root {
  /* ---- Surface ---- */
  --ds-paper:        #F5F0E2;   /* primary background — the beige everything sits on */
  --ds-paper-warm:   #F0E9D5;   /* card background — 3% darker */
  --ds-paper-cool:   #FAF6EC;   /* nested surface — 3% lighter */

  /* ---- Ink ---- */
  --ds-ink:          #0A0A0B;   /* headings, primary buttons */
  --ds-body:         #2E2C28;   /* body copy */
  --ds-muted:        #6B655A;   /* secondary text, timestamps, meta */
  --ds-muted-soft:   #8A8477;   /* tertiary text, disabled */

  /* ---- Structure ---- */
  --ds-hairline:     #D8CFB8;   /* borders, dividers */
  --ds-hairline-strong: #B8AE95; /* stronger dividers on hover / active */

  /* ---- Functional accents (used ONLY when information demands it) ---- */
  --ds-link:         #1F3443;   /* deep teal — links, focus rings */
  --ds-link-hover:   #0A0A0B;   /* black on hover — no color transition, just weight */
  --ds-growth:       #2F6E4E;   /* green — positive CAGR, growth deltas */
  --ds-decline:      #8A2A1F;   /* red — negative deltas */
  --ds-warn:         #B99335;   /* muted gold — one-off highlights only */

  /* ---- Typography ---- */
  --ds-font-display: "Source Sans 3", "Source Sans Pro", -apple-system, BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
  --ds-font-body:    "Source Sans 3", "Source Sans Pro", -apple-system, BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
  --ds-font-mono:    "Geist Mono", "SF Mono", "IBM Plex Mono", ui-monospace, "Menlo", monospace;

  /* ---- Radii ---- */
  --ds-radius-sm: 2px;    /* buttons, chips */
  --ds-radius-md: 4px;    /* cards */
  --ds-radius-lg: 8px;    /* large panels */

  /* ---- Motion ---- */
  --ds-ease-out:  cubic-bezier(0.16, 1, 0.3, 1);
  --ds-ease-in:   cubic-bezier(0.7, 0, 0.84, 0);
  --ds-dur-fast:  180ms;
  --ds-dur-mid:   320ms;
  --ds-dur-slow:  650ms;

  /* ---- Layout ---- */
  --ds-container-max: 1200px;
  --ds-container-pad: clamp(16px, 3vw, 32px);
  --ds-section-y:     clamp(40px, 5.5vw, 72px);
}

/* =============================================================================
   Scoped reset — namespaced under .ex-scope so we don't blow up admin pages
   ============================================================================= */
.ex-scope,
.ex-scope * ,
.ex-scope *::before,
.ex-scope *::after {
  box-sizing: border-box;
}

.ex-scope {
  font-family: var(--ds-font-body);
  color: var(--ds-body);
  background: var(--ds-paper);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

.ex-scope a {
  color: var(--ds-link);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color var(--ds-dur-fast) var(--ds-ease-out),
              border-color var(--ds-dur-fast) var(--ds-ease-out);
}
.ex-scope a:hover {
  color: var(--ds-link-hover);
  border-bottom-color: currentColor;
}

.ex-scope button {
  font-family: inherit;
  cursor: pointer;
}

.ex-scope img,
.ex-scope svg,
.ex-scope video,
.ex-scope canvas {
  max-width: 100%;
  display: block;
}

.ex-scope ::selection {
  background: var(--ds-ink);
  color: var(--ds-paper);
}

/* =============================================================================
   Typography scale — clamp() everywhere for fluid responsiveness
   ============================================================================= */
.ex-scope h1,
.ex-scope .ex-h1 {
  font-family: var(--ds-font-display);
  font-weight: 400;
  font-size: clamp(2.25rem, 5vw, 4rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
  color: var(--ds-ink);
  margin: 0 0 0.5em;
}

.ex-scope h2,
.ex-scope .ex-h2 {
  font-family: var(--ds-font-display);
  font-weight: 500;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--ds-ink);
  margin: 0 0 0.6em;
}

.ex-scope h3,
.ex-scope .ex-h3 {
  font-family: var(--ds-font-display);
  font-weight: 500;
  font-size: clamp(1.25rem, 2vw, 1.5rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ds-ink);
  margin: 0 0 0.5em;
}

.ex-scope h4,
.ex-scope .ex-h4 {
  font-family: var(--ds-font-body);
  font-weight: 600;
  font-size: 1.125rem;
  line-height: 1.35;
  color: var(--ds-ink);
  margin: 0 0 0.5em;
}

.ex-scope p {
  margin: 0 0 1em;
  color: var(--ds-body);
}

.ex-scope .ex-eyebrow {
  display: inline-block;
  font-family: var(--ds-font-body);
  font-size: 0.72rem;
  font-weight: 650;
  letter-spacing: 0.16em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--ds-muted);
  margin: 0 0 1em;
}

.ex-scope .ex-lead {
  font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  line-height: 1.55;
  color: var(--ds-body);
  font-weight: 400;
}

.ex-scope .ex-mono {
  font-family: var(--ds-font-mono);
  font-feature-settings: "tnum" 1, "zero" 1;
  letter-spacing: -0.01em;
}

.ex-scope .ex-muted { color: var(--ds-muted); }
.ex-scope .ex-growth { color: var(--ds-growth); }
.ex-scope .ex-decline { color: var(--ds-decline); }

/* =============================================================================
   Layout primitives
   ============================================================================= */
.ex-scope .ex-container {
  width: 100%;
  max-width: var(--ds-container-max);
  margin-inline: auto;
  padding-inline: var(--ds-container-pad);
}

.ex-scope .ex-container--wide {
  max-width: 1400px;
}

.ex-scope .ex-section {
  padding-block: var(--ds-section-y);
}

.ex-scope .ex-section--tight {
  padding-block: clamp(32px, 5vw, 56px);
}

.ex-scope .ex-hairline {
  border: 0;
  border-top: 1px solid var(--ds-hairline);
  margin: 0;
}

/* =============================================================================
   Reveal on scroll — restrained fade-up
   ============================================================================= */
.ex-scope .ex-reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--ds-dur-slow) var(--ds-ease-out),
              transform var(--ds-dur-slow) var(--ds-ease-out);
}
.ex-scope .ex-reveal.is-visible {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .ex-scope .ex-reveal,
  .ex-scope .ex-reveal.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .ex-scope * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* =============================================================================
   A11y utilities
   ============================================================================= */
.ex-scope .ex-skip-link {
  position: absolute;
  top: -100px;
  left: 8px;
  padding: 8px 16px;
  background: var(--ds-ink);
  color: var(--ds-paper);
  font-weight: 600;
  z-index: 1000;
  transition: top var(--ds-dur-fast) var(--ds-ease-out);
}
.ex-scope .ex-skip-link:focus {
  top: 8px;
}

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

/* =============================================================================
   Focus visible — one style everywhere
   ============================================================================= */
.ex-scope :focus-visible {
  outline: 2px solid var(--ds-link);
  outline-offset: 3px;
  border-radius: 2px;
}
.ex-scope :focus:not(:focus-visible) {
  outline: none;
}

/* =============================================================================
   text-wrap: balance for headings — 2026-09-03
   Balances line lengths on all headings so wrapped text looks more even.
   Only applies to headings (H1, H2, H3, .ex-h1/2/3, .ex-hero__title, .ex-h2).
   Gracefully ignored by browsers that dont support it. Zero desktop impact.
   ============================================================================= */
.ex-scope h1,
.ex-scope h2,
.ex-scope h3,
.ex-scope .ex-h1,
.ex-scope .ex-h2,
.ex-scope .ex-h3,
.ex-scope .ex-hero__title,
.ex-scope .ex-hero__lead,
.ex-scope .ex-eyebrow,
.ex-scope .ex-report-card__title {
  text-wrap: balance;
}

/* pretty wrap for body copy — prevents orphaned single words on the last line
   e.g. "Nothing generic." at bottom of a paragraph */
.ex-scope p,
.ex-scope .ex-hero__lead {
  text-wrap: pretty;
}

/* =============================================================================
   Homepage text justification — 2026-09-03 (updated: mobile enabled per user request)
   Entire homepage body text is justified (both edges aligned) like a printed
   research report. Applies at ALL screen widths for homepage only.
   Uses body.ex-home as the scope hook (see index.php body tag).
   Other section pages (ex-section-page) still skip justify on mobile — see block below.
   ============================================================================= */
.ex-scope.ex-home,
.ex-scope.ex-home p,
.ex-scope.ex-home li,
.ex-scope.ex-home dd,
.ex-scope.ex-home blockquote,
.ex-scope.ex-home .ex-hero__lead,
.ex-scope.ex-home .ex-about__section-sub,
.ex-scope.ex-home .ex-about__quote-body,
.ex-scope.ex-home .ex-why__desc {
  text-align: justify;
  text-justify: inter-word;
  hyphens: manual;
  -webkit-hyphens: manual;
  word-break: normal;
  overflow-wrap: normal;
}
/* Exceptions: headings, meta, badges, buttons stay left-aligned */
.ex-scope.ex-home h1,
.ex-scope.ex-home h2,
.ex-scope.ex-home h3,
.ex-scope.ex-home h4,
.ex-scope.ex-home .ex-h1,
.ex-scope.ex-home .ex-h2,
.ex-scope.ex-home .ex-h3,
.ex-scope.ex-home .ex-hero__title,
.ex-scope.ex-home .ex-eyebrow,
.ex-scope.ex-home .ex-mono,
.ex-scope.ex-home .ex-btn,
.ex-scope.ex-home .ex-report-card__eyebrow,
.ex-scope.ex-home .ex-report-card__price,
.ex-scope.ex-home .ex-report-card__title,
.ex-scope.ex-home .ex-report-card__meta,
.ex-scope.ex-home .ex-report-card__meta-item,
.ex-scope.ex-home .ex-cat-tile,
.ex-scope.ex-home .ex-cat-tile__name,
.ex-scope.ex-home .ex-cat-tile__count,
.ex-scope.ex-home .ex-logos-strip__label,
.ex-scope.ex-home .ex-editors-pick__label p,
.ex-scope.ex-home .ex-editors-pick__cta,
.ex-scope.ex-home .ex-why__num,
.ex-scope.ex-home .ex-hero__quicklinks-label,
.ex-scope.ex-home .ex-search__input,
.ex-scope.ex-home .ex-search__btn,
.ex-scope.ex-home time,
.ex-scope.ex-home figcaption {
  text-align: left !important;
  hyphens: manual;
}

/* =============================================================================
   Section-page text justification — 2026-09-03
   Same treatment as homepage, applied to Industries/Services/Blog/Press/About/Contact.
   Only desktop (>720px) to avoid mobile word gaps.
   ============================================================================= */
@media (min-width: 721px) {
  .ex-scope.ex-section-page,
  .ex-scope.ex-section-page p,
  .ex-scope.ex-section-page li,
  .ex-scope.ex-section-page dd,
  .ex-scope.ex-section-page blockquote,
  .ex-scope.ex-section-page .ex-hero__lead,
  .ex-scope.ex-section-page .ex-about__section-sub,
  .ex-scope.ex-section-page .ex-about__quote-body,
  .ex-scope.ex-section-page .ex-why__desc {
    text-align: justify;
    text-justify: inter-word;
    hyphens: manual;
    -webkit-hyphens: manual;
    word-break: normal;
    overflow-wrap: normal;
  }
  .ex-scope.ex-section-page h1,
  .ex-scope.ex-section-page h2,
  .ex-scope.ex-section-page h3,
  .ex-scope.ex-section-page h4,
  .ex-scope.ex-section-page .ex-h1,
  .ex-scope.ex-section-page .ex-h2,
  .ex-scope.ex-section-page .ex-h3,
  .ex-scope.ex-section-page .ex-hero__title,
  .ex-scope.ex-section-page .ex-eyebrow,
  .ex-scope.ex-section-page .ex-mono,
  .ex-scope.ex-section-page .ex-btn,
  .ex-scope.ex-section-page .ex-report-card__eyebrow,
  .ex-scope.ex-section-page .ex-report-card__price,
  .ex-scope.ex-section-page .ex-report-card__title,
  .ex-scope.ex-section-page .ex-report-card__meta,
  .ex-scope.ex-section-page .ex-report-card__meta-item,
  .ex-scope.ex-section-page .ex-cat-tile,
  .ex-scope.ex-section-page .ex-cat-tile__name,
  .ex-scope.ex-section-page .ex-cat-tile__count,
  .ex-scope.ex-section-page .ex-logos-strip__label,
  .ex-scope.ex-section-page .ex-editors-pick__label p,
  .ex-scope.ex-section-page .ex-editors-pick__cta,
  .ex-scope.ex-section-page .ex-why__num,
  .ex-scope.ex-section-page .ex-hero__quicklinks-label,
  .ex-scope.ex-section-page .ex-search__input,
  .ex-scope.ex-section-page .ex-search__btn,
  .ex-scope.ex-section-page .ex-cf__label,
  .ex-scope.ex-section-page .ex-cf__input,
  .ex-scope.ex-section-page .ex-cf__submit,
  .ex-scope.ex-section-page time,
  .ex-scope.ex-section-page figcaption {
    text-align: left !important;
    hyphens: manual;
  }
}



/* Report cards: never justify — they use -webkit-line-clamp so justified
   text creates ugly gaps on the last visible line before the ellipsis */
.ex-scope .ex-report-card,
.ex-scope .ex-report-card *,
.ex-scope .ex-report-card__title,
.ex-scope .ex-report-card__desc,
.ex-scope .ex-report-card__eyebrow,
.ex-scope .ex-report-card__meta,
.ex-scope .ex-report-card__meta-item,
.ex-scope .ex-report-card__price {
  text-align: left !important;
  hyphens: manual !important;
  -webkit-hyphens: manual !important;
  word-break: normal !important;
  overflow-wrap: normal !important;
}

/* =============================================================================
   Report pages only — Source Sans Pro (McKinsey/Gartner-style corporate sans)
   2026-09-03. Applies ONLY on individual report detail pages. Homepage, blog,
   about, contact, checkout, admin — all stay editorial (Fraunces + Inter).
   ============================================================================= */
.ex-scope.ex-report-page {
  --ds-font-display: "Source Sans 3", "Source Sans Pro", -apple-system, BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
  --ds-font-body:    "Source Sans 3", "Source Sans Pro", -apple-system, BlinkMacSystemFont, system-ui, "Helvetica Neue", Arial, sans-serif;
}
/* Slightly heavier weight for headings so they still feel substantial without a serif */
.ex-scope.ex-report-page h1,
.ex-scope.ex-report-page h2,
.ex-scope.ex-report-page h3,
.ex-scope.ex-report-page h4,
.ex-scope.ex-report-page .ex-h1,
.ex-scope.ex-report-page .ex-h2,
.ex-scope.ex-report-page .ex-h3 {
  font-weight: 600;
  letter-spacing: -0.015em;
}


/* Global heading weight bump for Source Sans (2026-09-04)
   Source Sans at weight 500 is thinner than Fraunces 500. Bump to 600 with
   slight negative letter-spacing so all headings across the site feel as
   substantial as they did with the serif. Applies everywhere. */
.ex-scope h1,
.ex-scope h2,
.ex-scope h3,
.ex-scope h4,
.ex-scope .ex-h1,
.ex-scope .ex-h2,
.ex-scope .ex-h3,
.ex-scope .ex-hero__title {
  font-weight: 600;
  letter-spacing: -0.015em;
}


/* Smart justify override (2026-09-04)
   Justify only works well in wide text columns (700px+). Below that, big
   word gaps appear. This override force-un-justifies text inside narrow
   containers so we get natural word spacing there. */

/* Narrow-container detection via known parent classes.
   If text lives inside any of these, use left-align regardless of ex-home/ex-section-page justify. */
.ex-scope.ex-home .ex-tier p,
.ex-scope.ex-home .ex-tier li,
.ex-scope.ex-home .ex-card p,
.ex-scope.ex-home .ex-card li,
.ex-scope.ex-home .ex-services-method p,
.ex-scope.ex-home .ex-services-method li,
.ex-scope.ex-home .ex-services-method__text p,
.ex-scope.ex-home aside p,
.ex-scope.ex-home aside li,
.ex-scope.ex-home [class*="card"] p,
.ex-scope.ex-home [class*="card"] li,
.ex-scope.ex-home [class*="tier"] p,
.ex-scope.ex-home [class*="tile"] p,
.ex-scope.ex-home [class*="callout"] p,

.ex-scope.ex-section-page .ex-tier p,
.ex-scope.ex-section-page .ex-tier li,
.ex-scope.ex-section-page .ex-card p,
.ex-scope.ex-section-page .ex-card li,
.ex-scope.ex-section-page .ex-services-method p,
.ex-scope.ex-section-page .ex-services-method li,
.ex-scope.ex-section-page .ex-services-method__text p,
.ex-scope.ex-section-page aside p,
.ex-scope.ex-section-page aside li,
.ex-scope.ex-section-page [class*="card"] p,
.ex-scope.ex-section-page [class*="card"] li,
.ex-scope.ex-section-page [class*="tier"] p,
.ex-scope.ex-section-page [class*="tile"] p,
.ex-scope.ex-section-page [class*="callout"] p {
  text-align: left !important;
  word-spacing: normal !important;
}

/* Additionally: any block that ends up narrower than 720px at runtime
   (via CSS container queries, when supported) reverts to left-align.
   Older browsers fall back to the class-based rules above. */
@supports (container-type: inline-size) {
  .ex-scope.ex-home .ex-container,
  .ex-scope.ex-section-page .ex-container {
    container-type: inline-size;
  }
  @container (max-width: 720px) {
    .ex-scope.ex-home p,
    .ex-scope.ex-section-page p,
    .ex-scope.ex-home li,
    .ex-scope.ex-section-page li {
      text-align: left;
    }
  }
}
