﻿/* ============================================================
 * Whichapp — Typography System v1.0
 * ------------------------------------------------------------
 * Consumes tokens.css. Defines how every typographic element on
 * the site renders. Loaded AFTER style.css and wpnav.css so it
 * can outrank the legacy literals already in those files until
 * those files are refactored to consume tokens directly.
 *
 * Specificity strategy: most rules use a single class or a body-
 * prefix to outrank GP parent and plugin defaults without
 * resorting to !important. !important is reserved for cases where
 * (a) GP parent or wpnav.css uses !important and (b) the override
 * is necessary — not as a sledgehammer.
 *
 * When style.css is refactored to consume tokens, the !important
 * declarations here can be removed in the same pass.
 * ============================================================ */


/* ============================================================
 * Document baseline
 * ============================================================ */

body {
  font-family: var(--font-sans);
  font-size:   var(--fs-body);
  font-weight: var(--fw-regular);
  line-height: var(--lh-body);
  color:       var(--color-text-default);
}

/* Theme/plugin chrome wrappers — Inter cascades into anything that
 * doesn't have its own explicit family. !important required because
 * GeneratePress parent sets `font-family: 'Source Sans Pro'` on
 * `body` with the same specificity. */
body,
body .site,
body .site-content,
body .content-area,
body .site-main,
body .inside-article,
body .entry-content,
body .site-footer,
body .site-footer * {
  font-family: var(--font-sans) !important;
}

/* Site chrome containers (nav, footer wordmark block, plugin UI,
 * GenerateBlocks elements, mobile slideout). The wildcard class
 * selectors catch the entire wpnav-* / wpft__ / cmplz-* / gb-*
 * namespaces in a single rule each. */
body [class*="wpnav-"],
body [class*="wpnav-"] *,
body [class*="wpft__"],
body [class*="wpft__"] *,
body [class*="cmplz-"],
body [class*="gb-"],
body [class*="gb-"] *,
body .skip-link,
body .generate-back-to-top,
body .generate-back-to-top *,
body header,
body header *,
body footer,
body footer * {
  font-family: var(--font-sans) !important;
}

/* Belt-and-braces: kill the Source Serif Pro mobile-nav ghost that
 * GP Premium attaches to .menu-bar-items / gb-text / .menu-toggle
 * via scoped inline sheets. */
body nav,
body nav *,
body .menu-bar-items,
body .menu-bar-items *,
body .menu-toggle,
body .menu-toggle *,
body .main-navigation,
body .main-navigation *,
body .slideout-navigation,
body .slideout-navigation * {
  font-family: var(--font-sans) !important;
}


/* ============================================================
 * Display serif — Source Serif 4
 * H1, footer wordmark, author-bio name. Re-promoted from the
 * Inter sweep above. Specificity is higher (class + class) so
 * !important is only needed where the sweep used it. */

body .wpft__wordmark,
body .wpft__wordmark *,
body .wpft__wordmark-letter,
body .wpft__wordmark-rest,
body .wpnav-author-bio__name {
  font-family: var(--font-display) !important;
}


/* ============================================================
 * Site chrome — semantic typography
 * ============================================================ */

/* --- Breadcrumb (meta tier, 13px) ---
 * Was 11px at #98A2B3 — below WCAG AA (~3.5:1 contrast).
 * Now 13px with darker mute. */
body .wpnav-breadcrumb,
body .wpnav-breadcrumb__link,
body .wpnav-breadcrumb__sep {
  font-size: var(--fs-meta) !important;
  font-weight: var(--fw-regular) !important;
  color: var(--color-text-mute-soft) !important;
}
body .wpnav-breadcrumb__current {
  font-size: var(--fs-meta) !important;
  font-weight: var(--fw-regular) !important;
  color: var(--color-text-muted) !important;
}

/* --- Page title (.entry-title) — 2026 redesign treatment ---
 * The redesigned page bodies render in the Inter / dark-ink system, but
 * the theme's default page title stayed washed grey Source Sans, so the
 * title strip at the top of every inner page read as "old design" next to
 * the new content below it. Pin the single-page title to the new Inter
 * dark-ink treatment so the top of the page matches the redesign.
 * Scoped to .wp-singular so archive/listing card titles are untouched.
 * Inter is already loaded sitewide (fonts.css); --font-sans is Source
 * Sans, so the family is named literally here on purpose. */
body.wp-singular .entry-title {
  font-family: 'Inter', 'Helvetica Neue', Arial, sans-serif !important;
  font-weight: var(--fw-semibold) !important;
  font-size: 36px !important;
  line-height: 1.12 !important;
  letter-spacing: -0.022em !important;
  color: var(--color-text-strong) !important;
}
@media (max-width: 680px) {
  body.wp-singular .entry-title { font-size: 28px !important; }
}

/* --- Header navigation (read tier, 17px) ---
 * Balances against the 73px brand logo. */
body .wpnav-nav__trigger {
  font-size: var(--fs-read) !important;
  font-weight: var(--fw-medium) !important;
}

/* --- Header Contact CTA (read tier, 17px / semibold) ---
 * Weight differentiates from nav items at same size. */
body .wpnav-header-cta {
  font-size: var(--fs-read) !important;
  font-weight: var(--fw-semibold) !important;
}

/* --- Header utility icons (body tier) --- */
body .wpnav-search-toggle,
body .wpnav-hamburger,
body .generate-back-to-top,
body .gp-icon {
  font-size: var(--fs-body) !important;
}


/* ============================================================
 * Author bio block
 * ============================================================ */

/* --- Kicker ("ABOUT THE AUTHOR") --- */
body .wpnav-author-bio__kicker,
body .wpnav-author-bio__sep,
body .wpnav-author-bio__reviewed {
  font-size: var(--fs-micro) !important;
}

/* --- Name (display serif, H3 tier) --- */
body .wpnav-author-bio__name {
  font-size: var(--fs-h3) !important;
  font-family: var(--font-display) !important;
}

/* --- Role subtitle (meta tier) ---
 * Was the same size as the kicker label and the "Last reviewed"
 * footnote. Now reads as a subtitle to the name. */
body .wpnav-author-bio__title {
  font-size: var(--fs-meta) !important;
  font-weight: var(--fw-semibold) !important;
}

/* --- Description and profile link (body tier) --- */
body .wpnav-author-bio__desc,
body .wpnav-author-bio__profile-link,
body .wpnav-author-bio a {
  font-size: var(--fs-body) !important;
}


/* ============================================================
 * Footer
 * ============================================================ */

body .wpft__wordmark-rest {
  font-size: var(--fs-h3) !important;
}
body .wpft__mission-text {
  font-size: var(--fs-body) !important;
}
body .wpft a:not(.wpft__col-cta):not(.wpft__back),
body .wpft__back-arrow {
  font-size: var(--fs-body) !important;
}
body .wpft__col-cta,
body .wpft__arrow,
body .wpft__copyright {
  font-size: var(--fs-micro) !important;
}


/* ============================================================
 * Plugin UI (consent banner, etc.)
 * ============================================================ */

body .cmplz-btn {
  font-size: var(--fs-body) !important;
}


/* ============================================================
 * Article headings — loaded-font pinning
 *
 * GeneratePress's dynamic CSS sets article headings in Source Serif
 * Pro (H1/H2) and Source Sans Pro (H3) — fonts loaded only by the GP
 * Google Fonts stylesheet, which we dequeue in functions.php. Without
 * an explicit family they would fall back to Georgia / system once
 * that stylesheet is gone. Pin them to the loaded token families,
 * preserving the current look: Source Serif 4 matches the serif H2,
 * Inter matches the sans H3. (H1 .entry-title already renders Inter
 * via the `body header *` sweep above.) Sizes live in style.css.
 * ============================================================ */

.wp-singular:not(.home) .entry-content h2,
.wpe-worked-example h2 {
  font-family: var(--font-display) !important;
}
.wp-singular:not(.home) .entry-content h3,
.wpe-worked-example h3 {
  font-family: var(--font-sans) !important;
}


/* ============================================================
 * Redesign fix — review "alternatives" 3-up card grid overflow
 *
 * The redesigned review block's `.alts` grid sized its three columns
 * by content width, so longer cards (e.g. the "Deel vs Multiplier"
 * link) pushed the row past the 720px reading column and slid under
 * the sticky TOC rail, running off the right of the page. Force equal,
 * container-bound tracks (minmax(0,1fr) lets the text wrap instead of
 * overflowing). Scoped to the desktop widths where the rail is present;
 * below that the block's own CSS collapses the grid to one column.
 * Interim theme-side fix; fold into the review body CSS on next refresh.
 * ============================================================ */
@media (min-width: 981px) {
  body #wp-rev .alts {
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
  }
  /* The "<provider> comparison →" link sized to its own content, sticking
     out past the now-narrower card; cap it so the label wraps to fit. */
  body #wp-rev .alts .a-link {
    max-width: 100%;
  }
}


/* ============================================================
 * Focus ring — keyboard navigation
 * ============================================================ */

body :focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}

/* ============================================================
 * Redesign sans token pin (QA fix 2026-06-12)
 * ------------------------------------------------------------
 * The redesign canon is Inter for all sans text. Most redesigned bodies define
 * #wp-*{--sans:'Inter',...} inline, but some (e.g. the 3 late-migrated reviews)
 * copied an exemplar whose --sans was a system-sans stack, so their headings AND
 * body prose rendered in the system font instead of Inter, inconsistent with the
 * other 17 reviews. The theme owns typography, so pin the canonical --sans on the
 * four redesign wrappers; this outranks the inline #wp-* token (body #wp-x = id+
 * element specificity) and makes the redesign uniformly Inter regardless of any
 * per-page token drift. (Mono labels use var(--mono) and are unaffected.)
 * ============================================================ */
body #wp-de, body #wp-home, body #wp-rev, body #wp-cmp {
  --sans: 'Inter', 'Helvetica Neue', Arial, sans-serif;
}

/* ============================================================
 * Redesign heading font pins (QA fix 2026-06-12)
 * ------------------------------------------------------------
 * The redesigned bodies set font-family:var(--sans) (Inter) on the
 * wrapper (#wp-de facts, #wp-home, #wp-rev reviews, #wp-cmp compares)
 * and rely on headings/figures INHERITING it. GeneratePress sets
 * font-family DIRECTLY on h1/h2/h3 via its .entry-content element
 * rules, and a direct declaration always beats an inherited value, so
 * these headings rendered GP's Source Serif/Source Sans instead of
 * Inter. Re-pin them to the wrapper's var(--sans) (with an explicit
 * Inter fallback) so the intended typeface wins. !important is the
 * reserved case here: GP wins on the element selector and only an
 * !important direct rule can restore the inherited intent.
 * ============================================================ */
body #wp-de h1,  body #wp-de h2,  body #wp-de h3,
body #wp-de .h1, body #wp-de .h2, body #wp-de .h3, body #wp-de .val,
body #wp-home h1,  body #wp-home h2,  body #wp-home h3,
body #wp-home .h1, body #wp-home .h2, body #wp-home .h3,
body #wp-rev h1,  body #wp-rev h2,  body #wp-rev h3,
body #wp-rev .h1, body #wp-rev .h2, body #wp-rev .h3,
body #wp-cmp h1,  body #wp-cmp h2,  body #wp-cmp h3,
body #wp-cmp .h1, body #wp-cmp .h2, body #wp-cmp .h3 {
  font-family: var(--sans, 'Inter', 'Helvetica Neue', Arial, sans-serif) !important;
}

/* Mono labels/figures: the same GP override that hit the headings also beats
 * the redesign's own #wp-* .x{font-family:var(--mono)} rules (GP wins on
 * !important / specificity), so eyebrows, source lines, score numerals and
 * other JetBrains Mono labels rendered Source Sans. Re-assert var(--mono) with
 * !important on exactly the elements each scope already marks mono. */
body #wp-de .eyebrow, body #wp-de .crumbs, body #wp-de .flag, body #wp-de .hm-k,
body #wp-de .meta, body #wp-de .toc-label, body #wp-de .eff, body #wp-de .src-link,
body #wp-de .conf, body #wp-de .ladder thead th, body #wp-de .note .note-k,
body #wp-de .callout .cal-label,
body #wp-rev .eyebrow, body #wp-rev .crumbs, body #wp-rev .logo, body #wp-rev .hm-k,
body #wp-rev .meta, body #wp-rev .toc-label, body #wp-rev .score .s-num,
body #wp-rev .score .s-cap, body #wp-rev .verdict-lead .cal-label, body #wp-rev .btn .arr,
body #wp-rev .pc-col li::before, body #wp-rev .srow .s-val, body #wp-rev .author .avatar,
body #wp-rev .inline-cta .arr, body #wp-rev .callout .c-k, body #wp-rev .alt .a-link,
body #wp-cmp .eyebrow, body #wp-cmp .crumbs, body #wp-cmp .hm-k, body #wp-cmp .meta,
body #wp-cmp .info-btn, body #wp-cmp .disc-pop strong, body #wp-cmp .prov-logo,
body #wp-cmp .src, body #wp-cmp .rl, body #wp-cmp .callout .cal-label, body #wp-cmp .scn th,
body #wp-cmp .ph .ph-tag, body #wp-cmp figcaption, body #wp-cmp .ways h4, body #wp-cmp .rm-k,
body #wp-cmp .toc-label, body #wp-cmp .toc-meta, body #wp-cmp .h2h tbody td::before,
body #wp-home .btn .arr, body #wp-home .proof-score, body #wp-home .proof-badge,
body #wp-home .logoband-label, body #wp-home .sec-head .sec-eye, body #wp-home .pcard .pgo,
body #wp-home .feat-card .fc-eye, body #wp-home .feat-card .fc-fresh,
body #wp-home .snap-score, body #wp-home .snap-attr-label {
  font-family: var(--mono, 'JetBrains Mono', ui-monospace, monospace) !important;
}

/* ============================================================
 * Accessibility — visible keyboard focus (WCAG 2.2 SC 2.4.7 /
 * 2.4.11). Guarantees a clear focus indicator on every keyboard-
 * reachable control sitewide, regardless of component CSS. Uses
 * :focus-visible so it never shows on mouse click, only on
 * keyboard/AT navigation. The accent ring matches the
 * --focus-ring token (css/tokens.css). Mouse-only :focus is left
 * to the browser default; we do NOT remove outlines anywhere.
 * ============================================================ */
:where(a, button, input, select, textarea, summary, [tabindex], [role="button"], [role="tab"], [role="menuitem"], [role="link"]):focus-visible {
  outline: var(--focus-ring, 2px solid #C8362A) !important;
  outline-offset: 2px !important;
  border-radius: 2px;
}
