/*
Theme Name: Kora Blog
Theme URI: https://koramoney.com
Author: Kora Financial
Author URI: https://koramoney.com
Description: Editorial blog theme for Kora Financial. Dark purple masthead with the data-trace net, server-side category filtering and search, 1.6:1 featured-image covers with a textured fallback, and a numbered long-form article layout. Ported from the editorial-v2 marketing site (src/app/blog).
Version: 2.7.0
Requires at least: 6.0
Tested up to: 6.9
Requires PHP: 7.4
License: Proprietary
Text Domain: kora-blog
*/

/* ==========================================================================
   TOKENS
   The marketing site carries a blue ramp with a `.theme-purple` override for
   the toggle. The blog ships purple only, so the purple values are inlined
   here — no indirection to unpick.
   ========================================================================== */
:root {
  --sans:
    'Geist', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
    sans-serif;
  --mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --serif: 'Source Serif 4', Georgia, 'Times New Roman', serif;

  /* neutrals — hue-neutral by design, they do NOT retint */
  --paper: #fafbfd;
  --surface: #ffffff;
  --surface-2: #f6f6f9;
  --cream-1: #fbfcfe;
  --ink: #0f1727;
  --ink-2: #33405a;
  --muted: #62708b;
  --faint: #97a3b9;
  --line: #e1e7f0;
  --g-100: #f2f4f8;
  --g-200: #e6eaf1;
  --g-300: #d4dbe5;

  /* accent ramp */
  --p-50: #f3eefe;
  --p-100: #e8e0fe;
  --p-200: #d3c7fd;
  --p-300: #b8a6fc;
  --p-400: #9a80fb;
  --p-500: #7752f9;
  --p-600: #6035e4;
  --p-700: #4c27b6;
  --p-900: #221153;
  --p-rgb: 119, 82, 249;
  --p300-rgb: 184, 166, 252;
  --cyan-rgb: 167, 139, 250;
  --grad-cool: linear-gradient(135deg, #7752f9, #5b30d0, #9a80fb);

  /* mesh (the "Iris" light recipe) */
  --mesh-a: 242, 92%, 62%;
  --mesh-b: 208, 90%, 62%;
  --mesh-c: 272, 70%, 66%; /* soft orchid */
  --mesh-d: 234, 95%, 70%;
  --mesh-bg: #f7f8fc;
  --mesh-g1: #fafbfe;
  --mesh-g2: #f2f4fa;

  /* grounds and hue aliases the nav's mega panels use, carried over from the
     marketing site so its NAV MEGA MENUS block ports verbatim */
  --cream-2: #f2eefc;
  --tint-1: #f7f8fa;
  --tint-2: #eef0f4; /* deeper off-white ground (footer gradient) */
  /* the glass plates' hue pair. The feature cards' corner marks light their
     upper edges with --plate-h2, which the card's `.plate-<hue>` class rebinds;
     --plate-h1 is the violet anchor and never moves. */
  --plate-h1: 242, 92%, 62%;
  --plate-h2: 208, 90%, 62%;
  /* the marketing site's small-type scale: 1 on desktop, stepping at
     1023 / 900 / 680 in the RESPONSIVE block */
  --viz-fs: 1;
  --hue-deep: var(--p-600);
  --hue-line: var(--p-100);
  --hue-soft: var(--p-50);

  /* the release-tag chip (Early access / Coming soon). Amber darkened for AA
     on white — the --amber above is the on-dark value. */
  --acc-3: #b06e05;
  --acc-3-soft: #fef4e3;

  /* dark zone */
  --zone-grad: linear-gradient(168deg, #33207a 0%, #221356 50%, #170d3b 100%);
  --zone-accent: #b8a6fc;
  --zone-ink-rgb: 235, 231, 250;

  /* semantic */
  --pos: #0fae6e;
  --pos-soft: #e6f8f0;
  --amber: #f5a524;
  --neg: #f0436b;

  --shadow-soft: 0 1px 2px rgba(15, 23, 39, 0.05);
  --shadow-float: 0 10px 28px -14px rgba(13, 30, 63, 0.18);
  --hi: inset 0 1.2px 0 rgba(255, 255, 255, 0.9);
  --ease: cubic-bezier(0.4, 0, 0.15, 1);
  --maxw: 1240px;
  /* the page GUTTER — `.wrap`'s horizontal padding, and the one source of truth
     for it. The nav bar, every section and the small-screen drawer all sit on
     this number, so the drawer's rows line up with the brand mark above them
     and the copy behind them. */
  --gutter: 48px;
  --nav-h: 74px;
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body.kora {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

img,
svg {
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/* no widows on titles; fill the measure rather than equalising line lengths.
   `balance` shortens every line to make them even, which reads as an
   under-filled column on long WordPress titles. */
h1,
h2,
h3 {
  margin: 0;
  text-wrap: pretty;
  font-weight: 400;
}

p {
  margin: 0;
  text-wrap: pretty;
}

ol,
ul {
  margin: 0;
  padding: 0;
}

.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 var(--gutter);
}

.tnum {
  font-variant-numeric: tabular-nums;
}

.t-acc {
  color: var(--p-600);
}

.ground-2 {
  background: var(--surface-2);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

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

.bl-skip:focus {
  position: fixed;
  top: 12px;
  left: 12px;
  z-index: 200;
  width: auto;
  height: auto;
  clip: auto;
  margin: 0;
  padding: 10px 16px;
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow-float);
  color: var(--p-700);
  font-weight: 500;
}

/* ---- buttons + links ---- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 24px;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  /* the site's rule, and the one the theme was missing: near the 900px
     handover the nav grid's right track tightens, and without this the label
     broke onto two lines while the marketing site's button held one */
  white-space: nowrap;
  transition:
    transform 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}

.btn-primary {
  background: var(--grad-cool);
  color: #fff;
  box-shadow:
    0 2px 10px rgba(96, 53, 228, 0.32),
    var(--hi);
}

.btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 7px 22px rgba(96, 53, 228, 0.42);
}

.btn .arr,
.btn .btn-arrow {
  transition: transform 0.25s;
}

.btn:hover .arr,
.btn:hover .btn-arrow {
  transform: translateX(3px);
}

/* ==========================================================================
   NAV
   At rest fully transparent with NO backdrop-filter. The filter used to be
   declared unconditionally, which over a light hero is invisible but over the
   dark masthead frosts the top 74px into a visible strip. The frosted white
   belongs to the scrolled state only.
   ========================================================================== */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 60;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    border-color 0.3s,
    background 0.3s,
    backdrop-filter 0.3s;
}

.nav.is-scrolled {
  background: rgba(250, 251, 253, 0.82);
  border-bottom-color: var(--line);
  backdrop-filter: saturate(150%) blur(14px);
  -webkit-backdrop-filter: saturate(150%) blur(14px);
}

/* 1fr auto 1fr, not space-between: the brand (~73px) and the CTA group
   (~236px) are not the same width, so flex space-between parked the links
   left of the page's centerline. Equal side tracks pin them to true center.

   THE COLUMN-GAP IS A CLEARANCE FLOOR, not rhythm. True centering holds down
   to ~975px, where the wide CTA side runs out of slack; in the last ~75px
   before the 900px burger handover the links ease LEFT, away from the CTA,
   and never fuse with it. */
.nav-in {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  column-gap: 40px;
  align-items: center;
  height: var(--nav-h);
}

.nav-in .brand {
  justify-self: start;
}

.nav-in .nav-cta {
  justify-self: end;
}

.brand {
  display: block;
  line-height: 0;
  color: var(--ink);
}

/* Sized by HEIGHT like the marketing site (--logo-h: 20 / 18 / 16), not by a
   width picked by hand: the wordmark's viewBox is 146x40, so a 104px width
   rendered it 28.5px tall against the site's 20px. The footer's KoraConnect
   lockup takes the same rule. */
.brand svg {
  height: 20px;
  width: auto;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 36px;
}

.nav-cta {
  display: flex;
  align-items: center;
  gap: 24px;
}

.nav-login {
  font-size: 16px;
  color: var(--ink-2);
  transition: color 0.3s;
  /* nowrap so the CTA column's minimum stays honest: without it the first
     thing to give under the nav-in clearance gap was this label breaking to
     two lines, not the left track. */
  white-space: nowrap;
}

.nav-login:hover {
  color: var(--p-700);
}

/* ---- inverted state, for the dark masthead ---- */
.nav.on-dark:not(.is-scrolled) .nav-login {
  color: rgba(255, 255, 255, 0.82);
}

.nav.on-dark:not(.is-scrolled) .nav-login:hover {
  color: #fff;
}

.nav.on-dark:not(.is-scrolled) .menu-btn {
  color: #fff;
}

/* `color` alone does nothing: the logo SVG hard-codes fill="#7752F9" on every
   path, so on a dark ground it rendered brand purple on purple and read as a
   smudge. Override the fill in the on-dark state only. */
.nav.on-dark:not(.is-scrolled) .brand svg path {
  fill: #fff;
}

/* ==========================================================================
   NAV MEGA MENUS
   A verbatim port of the NAV MEGA MENUS block in the marketing site's
   src/app/_shell/site.css, with the `#site` scope stripped and `.scrolled`
   renamed to this theme's `.is-scrolled`. Markup is matched element
   for element in template-parts/nav-mega.php, so the two stay diffable — do not
   "tidy" one side alone.
   ========================================================================== */
/* ===== NAV MEGA MENUS ===== */
.nav-trig {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 400;
  color: var(--ink-2);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: color 0.2s;
}
.nav-trig:hover,
.nav-trig[aria-expanded='true'] {
  color: var(--p-700);
}
.nav-trig svg {
  opacity: 0.5;
  transition:
    transform 0.25s var(--ease),
    opacity 0.2s;
}
.nav-trig[aria-expanded='true'] svg {
  transform: rotate(180deg);
  opacity: 0.9;
}
.nav.on-dark:not(.is-scrolled) .nav-trig {
  color: rgba(255, 255, 255, 0.82);
}
.nav.on-dark:not(.is-scrolled) .nav-trig:hover,
.nav.on-dark:not(.is-scrolled) .nav-trig[aria-expanded='true'] {
  color: #fff;
}

/* panel shell — centered under the bar, opens with a soft lift */
.mega {
  position: absolute;
  top: 66px;
  left: 50%;
  width: max-content;
  max-width: min(940px, calc(100vw - 40px));
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translate(-50%, 8px);
  transition:
    opacity 0.22s var(--ease),
    transform 0.22s var(--ease),
    visibility 0.22s;
  z-index: 70;
}
.mega.open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: translate(-50%, 0);
}
.mega-panel {
  position: relative;
  background: rgba(255, 255, 255, 0.99);
  backdrop-filter: saturate(160%) blur(22px);
  -webkit-backdrop-filter: saturate(160%) blur(22px);
  border: 1px solid var(--line);
  border-radius: 12px;
  box-shadow:
    0 34px 66px -34px rgba(15, 18, 28, 0.5),
    var(--hi);
  padding: 24px;
  overflow: hidden;
}
.mega-hd {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--faint);
  margin: 2px 0 12px;
}

/* Products — both revenue products get a feature card, stacked in the left
   column, beside the stacked list of the remaining modules. */
.mega-products {
  max-width: min(760px, calc(100vw - 40px));
}
.mega-grid {
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: 16px;
}
.mfeat-stack {
  display: grid;
  gap: 12px;
  align-content: start;
}
.mfeat {
  position: relative;
  display: block;
  border: 1px solid var(--line);
  border-radius: 12px;
  /* compacter than a single tall flagship card — two of them stack in the
     column, so the padding has to earn its space twice */
  padding: 18px 18px 14px;
  /* Themed "Iris" mesh (see docs/card-mesh-gradients.md) — uses the --mesh-*
     tokens so the card retints with the Blue/Purple accent. */
  background-color: var(--mesh-bg);
  background-image:
    radial-gradient(
      125% 125% at 50% 38%,
      rgba(0, 0, 0, 0) 55%,
      rgba(21, 23, 28, 0.1) 100%
    ),
    radial-gradient(
      117.6% 117.6% at 8% 12%,
      hsla(var(--mesh-a), 0.147) 0%,
      hsla(var(--mesh-a), 0) 62%
    ),
    radial-gradient(
      102.9% 102.9% at 104% 30%,
      hsla(var(--mesh-b), 0.108) 0%,
      hsla(var(--mesh-b), 0) 62%
    ),
    radial-gradient(
      114.66% 114.66% at 60% 96%,
      hsla(var(--mesh-c), 0.108) 0%,
      hsla(var(--mesh-c), 0) 62%
    ),
    radial-gradient(
      73.5% 73.5% at 30% 54%,
      hsla(var(--mesh-d), 0.098) 0%,
      hsla(var(--mesh-d), 0) 62%
    ),
    linear-gradient(160deg, var(--mesh-g1) 0%, var(--mesh-g2) 100%);
  background-blend-mode: multiply, normal, normal, normal, screen, normal;
  overflow: hidden;
  transition:
    transform 0.25s var(--ease),
    box-shadow 0.25s,
    border-color 0.25s;
}
/* the second core product — same card, plain tinted surface instead of the
   mesh, so income verification leads without either carrying a tag */
.mfeat-plain {
  background-image: none;
  background-color: var(--tint-1);
}
.mfeat:hover {
  transform: translateY(-2px);
  border-color: var(--p-200);
  box-shadow: var(--shadow-float);
}
/* no icon tile on these cards — the product's schematic runs oversized and
   faded across the bottom-right corner instead, so the copy gets the full
   width and the card loses the icon's row entirely */
.mfeat .mf-mark {
  position: absolute;
  /* the offsets run the drawing flush to the card's right and bottom edges.
     The plates are composed inside x 0-102 / y 0-98 of their viewBox to match,
     so the corner gets no padding but no detail is severed either. Filled
     shapes carry far more weight than line art, so the opacity stays low —
     just high enough that the plates' glass tiers still separate.

     The card also carries a `.plate-<hue>` companion, which is what the
     plates' gradients light their upper edges with; `--p-600` is only the
     fallback if a gradient ever fails to resolve. */
  right: -20px;
  bottom: -24px;
  width: 164px;
  height: 164px;
  color: var(--p-600);
  opacity: 0.15;
  pointer-events: none;
}
.mfeat .mf-mark svg {
  width: 100%;
  height: 100%;
}
/* the two companions the feature cards use — blue for cash flow analysis (it
   reads a bank account), teal for income verification (it returns a verified
   result). The h3/base/ramp/line values ride along so the classes stay a
   verbatim copy of site.css's; only --plate-h2 is read here. */
.plate-blue {
  --plate-h2: 212, 92%, 58%;
  --plate-h3: 194, 88%, 58%;
  --plate-base: #e3ebfd;
  --plate-ramp-a: #edf3ff;
  --plate-ramp-b: #dae5fb;
  --plate-line: #cfdcf7;
}
.plate-teal {
  --plate-h2: 184, 78%, 46%;
  --plate-h3: 202, 84%, 58%;
  --plate-base: #ddeff3;
  --plate-ramp-a: #eaf6f9;
  --plate-ramp-b: #d3e9ef;
  --plate-line: #c6e2e9;
}
.mfeat h4 {
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  margin: 0;
}
.mfeat p {
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
  /* keeps clear of the corner mark */
  max-width: 24em;
  margin: 5px 0 12px;
}
.mfeat .mf-cta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  font-weight: 500;
  color: var(--p-700);
}
.mfeat .mf-cta .arr {
  transition: transform 0.25s;
}
.mfeat:hover .mf-cta .arr {
  transform: translateX(3px);
}
.mcol {
  display: flex;
  flex-direction: column;
}
/* the module list runs shorter than the two stacked cards beside it, so its
   rows sit a little airier to take up some of the difference */
.mega-grid .mcol {
  gap: 6px;
}
.mega-grid .mcol .mcard {
  padding: 14px 12px;
}
.mcard {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  align-items: start;
  padding: 12px;
  border: 1px solid transparent;
  border-radius: 12px;
  transition:
    background 0.2s,
    border-color 0.2s;
}
.mcard:hover {
  background: var(--cream-2);
  border-color: var(--line);
}
/* unwired placeholder cards — no navigation, but keep the clickable feel */
.mcard-static {
  cursor: pointer;
}
.mcard .ibox {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: var(--hue-soft);
  border: 1px solid var(--hue-line);
  color: var(--hue-deep);
}
.mcard .ibox svg {
  width: 18px;
  height: 18px;
}
/* the title and its release tag share one line while they both fit. WRAPPING is
   the repair: with `nowrap` the two shrank against each other, and because the
   title is an anonymous flex item and the tag a shrinkable one, BOTH broke —
   "Identity / Verification" over an "EARLY / ACCESS" pill. Anything that widens
   the tag past the row (a browser minimum-font-size floor, a longer or
   translated tag) now drops it to its own line intact instead. */
.mcard .mc-t {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 4px 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}
.mcard .mc-d {
  display: block;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
  margin-top: 2px;
}
/* Solutions & Resources mega panels */
.mega-solutions {
  max-width: min(940px, calc(100vw - 40px));
}
.mega-resources {
  max-width: min(1040px, calc(100vw - 40px));
}
/* Solutions — Industries and Use cases sit side by side across the panel's
   white. The lending-stack services offer used to be a recessed strip underneath
   them both; it is now the last Use cases row, so the panel is just the two
   lists. */
.sol-layout {
  display: flex;
  flex-direction: column;
}
.sol-top {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
}
.sol-col {
  min-width: 0;
}

/* Industries — single-column card list within its half. */
.sol-ind {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
}
/* Use cases — single-column icon + label + description list. No dividers and
   no side padding, so the column reads as plain text beside the Industries
   cards rather than competing with them. */
.sol-uc {
  display: grid;
  grid-template-columns: 1fr;
  gap: 2px;
}
.sol-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  align-items: start;
  padding: 12px 0;
}
.sol-row .uc-ico {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--p-600);
}
.sol-row .uc-ico svg {
  width: 18px;
  height: 18px;
}
.sol-row .uc-t {
  display: block;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
  transition: color 0.2s;
}
.sol-row .uc-d {
  display: block;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
  margin-top: 2px;
}
a.sol-row:hover .uc-t {
  color: var(--p-700);
}
.sol-row-static {
  cursor: pointer;
}
/* Build your own lending stack — the one row that opens the demo modal instead of
   navigating, so it renders as a button and needs the row's left alignment
   and full width back. */
button.sol-row-btn {
  width: 100%;
  text-align: left;
  cursor: pointer;
}
button.sol-row-btn:hover .uc-t {
  color: var(--p-700);
}

/* Resources — highlighted links on white, beside a recessed grey White
   papers zone that bleeds to the panel's top/right/bottom edges (same recessed
   treatment as the Solutions rail).
   The left list carries no heading of its own — the links ARE the menu, and a
   "More" label over them was naming the panel rather than grouping anything.
   Two card columns instead of six stacked rows, so the list stops running
   three cards taller than the White papers zone beside it. */
.res-layout {
  display: grid;
  grid-template-columns: 1.55fr 1fr;
  gap: 28px;
  align-items: stretch;
}
.res-more {
  min-width: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2px 12px;
  align-content: start;
}
.res-wp {
  min-width: 0;
  margin: -24px -24px -24px 0;
  padding: 24px;
  background: var(--tint-1);
}
.wp-panel {
  margin-top: 2px;
}
.wp-item {
  background: transparent;
}
.wp-item:hover {
  background: #fff;
  border-color: transparent;
}

/* the Flagship tag on the two products in the drawer — same shape and slot as
   the status tags, the accent instead of the status ink */
.dp-tag.is-flag {
  color: var(--p-700);
  background: var(--p-50);
  border-color: var(--p-200);
}
/* the release-tag chip on a module or white-paper card */
.dp-tag {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--acc-3);
  background: var(--acc-3-soft);
  border: 1px solid rgba(176, 110, 5, 0.22);
  border-radius: 999px;
  padding: 2px 8px;
  vertical-align: 1px;
  /* a two-word status never breaks across two lines inside its own pill, and it
     never gets shrunk below its text by a flex parent — the row wraps instead
     (see `.mc-t`) */
  flex: none;
  white-space: nowrap;
}

/* ---- the small-screen drawer (chrome.tsx `NavDrawer`) ----
   Takes `.mega`'s visibility/opacity/transform pattern verbatim, including
   `visibility: hidden` while closed — that is what keeps a closed drawer's
   links out of the tab order without unmounting them.
   Positioned against `.nav` (fixed, full width) the same way the megas are, so
   it hangs off the bar's bottom edge rather than the content column. */
.nav-drawer {
  /* Above the breakpoint the drawer does not exist as far as layout is
     concerned. That is deliberately CSS and not just theme.js's matchMedia
     reset: if the drawer is open when the viewport grows past 900px the script
     closes the STATE, but this is what guarantees the panel can never hang
     under a nav that has its links back. */
  display: none;
  position: absolute;
  top: var(--nav-h);
  left: 0;
  right: 0;
  /* it is the only nav at this width, so it has to be able to scroll itself —
     the full sitemap with one group open is taller than a phone */
  max-height: calc(100vh - var(--nav-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-float);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition:
    opacity 0.22s var(--ease),
    transform 0.22s var(--ease),
    visibility 0.22s;
  z-index: 70;
}
.nav-drawer.open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
/* the drawer is the page's only navigation at this width, so it keeps the
   page's own gutter — its rows start on the same line as the brand mark in the
   bar above and the copy behind it */
.nd-in {
  display: flex;
  flex-direction: column;
  padding: 8px var(--gutter) 20px;
}

/* group headers and the flat Log in row are peers in the same list, so they
   share a height, a weight and a hairline. 16px is the site's --fs-card-t at
   the widths where the drawer exists (it only renders below 900px). */
.nd-group,
.nd-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  padding: 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: none;
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 500;
  text-align: left;
  color: var(--ink);
  cursor: pointer;
  transition: color 0.2s var(--ease);
}
.nd-group:hover,
.nd-top:hover {
  color: var(--p-700);
}
/* the drawer's own CTA. NOT an `.nd-top` peer: the rows above it are
   navigation and this is the action, so it keeps the button's own surface and
   sits clear of the last hairline. Full width, because every row in this panel
   is full width and a pill floated in the left gutter reads as a stray
   control. */
.nd-cta {
  margin-top: 20px;
}
.nd-cta .btn {
  width: 100%;
  justify-content: center;
}
.nd-group svg {
  flex: none;
  opacity: 0.5;
  transition: transform 0.22s var(--ease);
}
.nd-group.is-open svg {
  transform: rotate(180deg);
}

.nd-panel {
  display: flex;
  flex-direction: column;
  padding: 4px 0 12px;
}
/* `display` here is an author rule and the UA's `[hidden] { display: none }` is
   not, so without this every group rendered expanded and the accordion did
   nothing. Any element given a display AND toggled with `hidden` needs it. */
.nd-panel[hidden] {
  display: none;
}
/* the group's own sub-headings, matching `.mega-hd` in the desktop menus */
.nd-sub {
  padding: 14px 0 6px;
  font-family: var(--mono);
  font-size: max(8px, calc(11px * var(--viz-fs)));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}
/* No left stroke. It was standing in for the icon the drawer did not draw —
   a rule down the side of a list the reader is already scanning as a list,
   which just narrowed the rows. The icon is the row's leading mark now. */
.nd-row {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 6px 0;
  border: 0;
  background: none;
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 400;
  text-align: left;
  color: var(--ink-2);
  cursor: pointer;
  transition: color 0.2s var(--ease);
}
/* the bare 22px mark the solutions rows use, not the mega card's 34px tinted
   box — a box per row would bulk out a list this long on a phone */
.nd-row .nd-ico {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--p-600);
  transition: color 0.2s var(--ease);
}
.nd-row .nd-ico svg {
  width: 18px;
  height: 18px;
}
/* the label keeps its own wrapping so a long name and its tag stay together
   and never reflow under the icon */
.nd-row .nd-lbl {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
}
.nd-row:hover {
  color: var(--p-700);
}
/* placeholder rows have no page yet — same treatment as `.foot-na` */
.nd-row-static {
  color: var(--faint);
  cursor: default;
}
.nd-row-static .nd-ico {
  color: var(--faint);
}
.nd-row-static:hover {
  color: var(--faint);
}

/* ---- the burger ----
   The site's icon: a 22x22 SVG with three strokes, swapped for an X by
   theme.js while the drawer is open. */
.menu-btn {
  display: none;
  padding: 6px;
  color: var(--ink);
  background: none;
  border: none;
  cursor: pointer;
  line-height: 0;
}

.menu-btn svg {
  display: block;
}

/* ==========================================================================
   §1 MASTHEAD
   No artifact, no CTA pair, no partner marquee — an index is not a detail page.
   The presence comes from the GROUND: the site's documented dark purple recipe
   plus the rounded-orthogonal data-trace net in light hairlines.

   This is the page's one dark beat in the body; the grid runs light and the page
   closes dark on the contact band — dark → light → dark.
   ========================================================================== */
.bl-mast {
  position: relative;
  overflow: clip;
  padding: clamp(124px, 16vh, 168px) 0 clamp(56px, 7vh, 80px);
  background:
    /* Blooms are kept OFF the nav band — a bright one under the logo made
       white-on-light-purple read as a smudge. The top ~90px stays the darkest
       part of the ground so the inverted nav has something to sit on. */
    radial-gradient(
      58% 72% at 20% 44%,
      rgba(var(--p300-rgb), 0.28),
      transparent 62%
    ),
    radial-gradient(
      46% 62% at 92% 74%,
      rgba(var(--cyan-rgb), 0.18),
      transparent 60%
    ),
    radial-gradient(
      52% 64% at 68% 8%,
      rgba(var(--p300-rgb), 0.12),
      transparent 64%
    ),
    linear-gradient(158deg, var(--p-700) 0%, var(--p-900) 100%);
}

.bl-mast > .wrap {
  position: relative;
  z-index: 1;
}

/* no cap on the block: .ed-h1 and .ed-sub carry their own measures, and a cap
   here is what forced the title to break early */
.bl-mast-tx {
  max-width: none;
}

.ed-eyebrow {
  display: block;
  margin-bottom: 20px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
}

.ed-h1 {
  font-size: clamp(36px, 4.1vw, 60px);
  line-height: 1.03;
  letter-spacing: -0.026em;
  color: var(--ink);
  max-width: 12em;
}

.ed-sub {
  margin: 24px 0 0;
  font-size: clamp(18px, 1.4vw, 20px);
  line-height: 1.55;
  color: var(--muted);
  max-width: 30em;
}

.ed-sub .hl {
  color: var(--ink);
  font-weight: 500;
}

/* on-dark type: the accent phrase switches to --zone-accent (solid --p-600
   disappears on this ground) and .hl highlights by going pure white */
.bl-mast .ed-eyebrow {
  color: rgba(var(--zone-ink-rgb), 0.6);
}

.bl-mast .ed-h1 {
  color: #fff;
}

.bl-mast .ed-h1 .t-acc {
  color: var(--zone-accent);
}

.bl-mast .ed-sub {
  color: rgba(var(--zone-ink-rgb), 0.72);
}

.bl-mast .ed-sub .hl {
  color: #fff;
}

/* ---- the data-trace net, masked so it stays margin texture and dissolves
   before the copy — never an untreated full-section pattern ---- */
.bl-net {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  -webkit-mask: radial-gradient(
    50% 68% at 26% 52%,
    transparent 0 52%,
    #000 100%
  );
  mask: radial-gradient(50% 68% at 26% 52%, transparent 0 52%, #000 100%);
}

.bl-net svg {
  width: 100%;
  height: 100%;
}

.bl-net .bn-line {
  fill: none;
  stroke: rgba(255, 255, 255, 0.17);
  stroke-width: 1.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.bl-net .bn-dash {
  stroke: rgba(255, 255, 255, 0.13);
  stroke-dasharray: 4 6;
}

.bl-net .bn-node {
  fill: rgba(var(--p300-rgb), 0.85);
}

.bl-net .bn-pulse {
  fill: none;
  stroke: var(--zone-accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 0.03 0.97;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 6px rgba(var(--p300-rgb), 0.75));
  opacity: 0;
  animation: bl-net-pulse 36s linear infinite;
}

@keyframes bl-net-pulse {
  0% {
    stroke-dashoffset: 1;
    opacity: 0;
  }
  4%,
  22% {
    opacity: 0.9;
  }
  26%,
  100% {
    stroke-dashoffset: 0;
    opacity: 0;
  }
}

/* ==========================================================================
   §2 FILTER BAR — sticky under the nav. Search first at the left, chips follow.
   ========================================================================== */
.bl-bar {
  position: sticky;
  top: var(--nav-h);
  z-index: 40;
  background: rgba(250, 251, 253, 0.92);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

.bl-bar-in {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 28px);
  padding: 14px 0;
  min-width: 0;
}

.bl-search {
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  width: clamp(200px, 22vw, 264px);
  height: 38px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: var(--shadow-soft);
  transition:
    border-color 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}

.bl-search:focus-within {
  border-color: var(--p-400);
  box-shadow: 0 0 0 3px rgba(var(--p300-rgb), 0.28);
}

.bl-search-ic {
  flex: none;
  display: grid;
  place-items: center;
  color: var(--faint);
}

.bl-search-ic svg {
  width: 16px;
  height: 16px;
}

.bl-search input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: 0;
  background: none;
  font-family: var(--sans);
  font-size: 16px;
  color: var(--ink);
}

.bl-search input::placeholder {
  color: var(--faint);
}

.bl-search input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

.bl-search-x {
  flex: none;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  color: var(--muted);
  background: var(--g-100);
}

.bl-search-x:hover {
  color: var(--ink);
  background: var(--g-200);
}

.bl-search-x svg {
  width: 11px;
  height: 11px;
}

/* The chip row takes an unbounded number of WordPress categories: "All" is
   pinned, the categories scroll in a rail beside it, and the fade + arrow show
   only on a side that has more chips (data-ov, set by assets/js/theme.js).
   A single unconditional right-edge mask read as a clipped last chip. */
.bl-chips {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1;
  min-width: 0;
}

.bl-chip-all {
  flex: none;
}

.bl-rail-wrap {
  position: relative;
  flex: 1;
  min-width: 0;
}

/* the chips are the row's overflow surface: they scroll rather than wrap, so the
   bar keeps one line at every width */
.bl-rail {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  padding: 2px 0;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}

.bl-rail::-webkit-scrollbar {
  display: none;
}

/* With JS off data-ov is never set, so neither of these matches: no fade, no
   buttons, and the rail is still scrollable by swipe, trackpad and keyboard. */
.bl-rail-wrap[data-ov='end'] .bl-rail {
  -webkit-mask: linear-gradient(90deg, #000 0 84%, transparent 100%);
  mask: linear-gradient(90deg, #000 0 84%, transparent 100%);
}

.bl-rail-wrap[data-ov='start'] .bl-rail {
  -webkit-mask: linear-gradient(90deg, transparent 0, #000 16%);
  mask: linear-gradient(90deg, transparent 0, #000 16%);
}

.bl-rail-wrap[data-ov='both'] .bl-rail {
  -webkit-mask: linear-gradient(
    90deg,
    transparent 0,
    #000 14% 86%,
    transparent 100%
  );
  mask: linear-gradient(90deg, transparent 0, #000 14% 86%, transparent 100%);
}

.bl-rail-btn {
  position: absolute;
  top: 50%;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--surface);
  box-shadow: var(--shadow-soft);
  color: var(--ink-2);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-50%) scale(0.86);
  transition:
    opacity 0.18s var(--ease),
    transform 0.18s var(--ease),
    color 0.18s var(--ease),
    border-color 0.18s var(--ease);
}

.bl-rail-btn:hover {
  border-color: var(--p-200);
  color: var(--p-700);
}

.bl-rail-btn svg {
  width: 13px;
  height: 13px;
}

.bl-rail-btn.is-prev {
  left: -6px;
  transform: translateY(-50%) scale(0.86) rotate(180deg);
}

.bl-rail-btn.is-next {
  right: -6px;
}

.bl-rail-wrap[data-ov='start'] .is-prev,
.bl-rail-wrap[data-ov='both'] .is-prev {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(-50%) scale(1) rotate(180deg);
}

.bl-rail-wrap[data-ov='end'] .is-next,
.bl-rail-wrap[data-ov='both'] .is-next {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(-50%) scale(1);
}

/* touch surfaces swipe the rail; the arrows would only cover a chip */
@media (hover: none) {
  .bl-rail-btn {
    display: none;
  }
}

.bl-chip {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 32px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--surface);
  font-size: 14px;
  color: var(--ink-2);
  white-space: nowrap;
  transition:
    border-color 0.2s var(--ease),
    color 0.2s var(--ease),
    background 0.2s var(--ease);
}

.bl-chip:hover {
  border-color: var(--p-200);
  color: var(--p-700);
}

.bl-chip.is-on {
  border-color: transparent;
  background: var(--p-600);
  color: #fff;
}

.bl-chip-n {
  font-size: 12px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

.bl-chip:hover .bl-chip-n {
  color: var(--p-400);
}

.bl-chip.is-on .bl-chip-n {
  color: rgba(255, 255, 255, 0.62);
}

/* ==========================================================================
   §3 GRID
   ========================================================================== */
.bl-gridwrap {
  padding: clamp(48px, 6vh, 76px) 0 clamp(96px, 12vh, 152px);
}

/* the count is always present so the row never shifts; Clear only appears when
   there is something to clear */
.bl-res {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: clamp(24px, 3vh, 34px);
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
}

.bl-count {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}

.bl-clear {
  font-size: 14px;
  font-weight: 500;
  color: var(--p-700);
  transition: color 0.2s var(--ease);
}

.bl-clear:hover {
  color: var(--p-500);
}

.bl-more-all {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.bl-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 2.6vw, 36px) clamp(20px, 2.2vw, 30px);
  align-items: start;
}

.bl-cell {
  min-width: 0;
  animation: bl-in 0.5s var(--ease) both;
  animation-delay: calc(var(--i, 0) * 40ms);
}

@keyframes bl-in {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.bl-card {
  display: block;
  min-width: 0;
}

.bl-card .bp {
  transition:
    transform 0.25s var(--ease),
    box-shadow 0.25s var(--ease);
}

.bl-card:hover .bp {
  transform: translateY(-3px);
  box-shadow: var(--shadow-float);
}

.bl-card-tx {
  padding-top: 18px;
}

.bl-card-tx h3 {
  margin: 10px 0 0;
  font-size: clamp(18px, 1.5vw, 20px);
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.016em;
  color: var(--ink);
  transition: color 0.2s var(--ease);
}

.bl-card:hover .bl-card-tx h3 {
  color: var(--p-700);
}

/* the card's one accent moment */
.bl-topic {
  display: block;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--p-600);
}

.bl-meta {
  margin-top: 12px;
  font-size: 14px;
  color: var(--muted);
}

.bl-empty {
  padding: clamp(48px, 7vh, 80px) 0;
  text-align: center;
}

.bl-empty p {
  font-size: 18px;
  color: var(--muted);
}

.bl-empty .bl-clear {
  display: inline-block;
  margin-top: 16px;
}

/* pagination — ‹ 1 2 … 12 ›, rendered by kora_the_pager(). Every cell is the
   same 38px square, arrows included, so the row reads as one control; the
   arrows stay in place and grey out at the ends rather than disappearing. */
.bl-pager {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  margin-top: clamp(40px, 5vh, 64px);
}

.bl-pager .bl-pg {
  display: inline-grid;
  place-items: center;
  min-width: 38px;
  height: 38px;
  padding: 0 12px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--surface);
  font-size: 14px;
  color: var(--ink-2);
  transition:
    color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}

.bl-pager a.bl-pg:hover {
  border-color: var(--p-200);
  color: var(--p-700);
}

.bl-pager .bl-pg.is-current {
  border-color: transparent;
  background: var(--p-600);
  color: #fff;
}

.bl-pager .bl-pg-arrow {
  padding: 0;
  width: 38px;
}

.bl-pager .bl-pg-arrow svg {
  display: block;
}

/* at either end the arrow has nowhere to go: kept for the row's shape, faded,
   and not a link */
.bl-pager .bl-pg-arrow.is-disabled {
  color: var(--faint);
  border-color: var(--line);
  cursor: default;
}

/* the collapsed run — plain glyph, no box */
.bl-pager .bl-pg-dots {
  display: inline-grid;
  place-items: center;
  min-width: 20px;
  height: 38px;
  font-size: 14px;
  color: var(--faint);
}

/* ==========================================================================
   COVER PLATES
   The cover is the post's featured image, produced with the /blog-cover skill
   and uploaded in the editor. This is the frame around it.

   A FIXED height, not a min-height — the plates in a row must share a bottom
   edge as well as a top one.

   The image is 1.6:1 but the plate is 1.56:1 in the grid and 1.95:1 on the
   article page, so it is object-fit cropped rather than letterboxed, and the
   skill keeps everything meaningful inside a safe zone that survives both.
   ========================================================================== */
.bp {
  display: grid;
  place-items: center;
  height: 232px;
  padding: 20px;
  overflow: hidden;
  border: 1px solid rgba(15, 23, 39, 0.07);
  border-radius: 12px;
}

.bp-lg {
  height: auto;
  min-height: clamp(292px, 27vw, 348px);
}

/* ---- with a featured image: the image IS the plate, edge to edge ---- */
.bp-img {
  padding: 0;
  background: var(--g-100);
}

.bp-img-el {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* .bp-lg has no fixed height, so the article-page plate needs the ratio stated
   or the image would drive the box and break the 1.95:1 crop. */
.bp-lg.bp-img {
  aspect-ratio: 680 / 348;
}

/* ---- with no featured image ------------------------------------------------
   A hairline texture on the post's ground. Deliberately abstract: a schematic
   of invented figures next to someone else's headline would read as evidence
   for a claim it knows nothing about. ---- */
.bp-blank::after {
  content: '';
  width: 100%;
  height: 100%;
  background-image: repeating-linear-gradient(
    122deg,
    transparent 0 38px,
    currentColor 38px 39px
  );
  color: rgba(15, 23, 39, 0.06);
  mask-image: radial-gradient(120% 92% at 50% 50%, #000 30%, transparent 78%);
  -webkit-mask-image: radial-gradient(
    120% 92% at 50% 50%,
    #000 30%,
    transparent 78%
  );
}

.bp-blank.g-violet::after,
.bp-blank.g-deep::after,
.bp-blank.g-zone::after {
  color: rgba(255, 255, 255, 0.12);
}

/* ---- LIGHT TIER · Sky. Unambiguously COOL — cyan and blue only, no violet
   node — so it cannot be confused with the mid tier. ---- */
.bp.g-sky {
  border-color: rgba(var(--cyan-rgb), 0.4);
  background:
    radial-gradient(
      66% 74% at 86% 10%,
      rgba(var(--cyan-rgb), 0.42),
      transparent 62%
    ),
    radial-gradient(
      58% 66% at 8% 26%,
      hsla(var(--mesh-b), 0.28),
      transparent 60%
    ),
    radial-gradient(
      62% 72% at 34% 100%,
      rgba(var(--cyan-rgb), 0.3),
      transparent 64%
    ),
    #eef4fb;
}

/* ---- MID TIER · a saturated violet field: the step between the pale plate and
   the dark ones, so the three read as three distinct luminance steps. ---- */
.bp.g-violet {
  background:
    radial-gradient(
      68% 76% at 12% 6%,
      rgba(255, 255, 255, 0.2),
      transparent 62%
    ),
    radial-gradient(
      60% 68% at 94% 98%,
      rgba(var(--cyan-rgb), 0.3),
      transparent 60%
    ),
    linear-gradient(150deg, var(--p-500) 0%, var(--p-700) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.16);
}

/* ---- DARK TIER · two of them so the darks don't read as one repeated swatch ---- */
.bp.g-deep {
  background:
    radial-gradient(
      70% 78% at 16% 6%,
      rgba(var(--p300-rgb), 0.3),
      transparent 64%
    ),
    radial-gradient(
      62% 70% at 92% 96%,
      rgba(var(--cyan-rgb), 0.16),
      transparent 62%
    ),
    linear-gradient(152deg, var(--p-700) 0%, var(--p-900) 100%);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.bp.g-zone {
  background:
    radial-gradient(
      66% 74% at 84% 8%,
      rgba(var(--p300-rgb), 0.22),
      transparent 64%
    ),
    radial-gradient(
      56% 62% at 8% 100%,
      rgba(var(--cyan-rgb), 0.14),
      transparent 60%
    ),
    var(--zone-grad);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

/* the dark tiers carry no hairline border — the ground is the edge */
.bp.g-deep,
.bp.g-zone,
.bp.g-violet {
  border-color: transparent;
}

/* ==========================================================================
   ARTICLE
   ========================================================================== */

/* reading progress — CSS scroll-timeline, no listener, nothing to hydrate.
   Without support it stays at scaleX(0), i.e. invisible. */
.bl-prog {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  z-index: 70;
  background: var(--grad-cool);
  transform: scaleX(0);
  transform-origin: 0 50%;
  pointer-events: none;
}

@supports (animation-timeline: scroll()) {
  .bl-prog {
    animation: bl-prog linear forwards;
    animation-timeline: scroll(root block);
  }
}

@keyframes bl-prog {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}

.bl-art {
  padding: clamp(112px, 14vh, 152px) 0 clamp(72px, 9vh, 108px);
  background: var(--paper);
}

/* One reading column, 680px. At 18px that is ~68 characters; 720 pushed it past
   the comfortable measure for a long article. */
.bl-art-hd,
.bl-article,
.bl-deck,
.bl-toc {
  max-width: 680px;
  margin-left: auto;
  margin-right: auto;
}

.bl-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: clamp(28px, 3.5vh, 40px);
  font-size: 14px;
  font-weight: 500;
  color: var(--muted);
  transition: color 0.2s var(--ease);
}

.bl-back:hover {
  color: var(--p-700);
}

/* a drawn chevron rather than "←", which sat off the baseline */
.bl-back::before {
  content: '';
  width: 6px;
  height: 6px;
  border-left: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.2s var(--ease);
}

.bl-back:hover::before {
  transform: rotate(45deg) translate(2px, -2px);
}

.bl-art-hd .ed-eyebrow {
  color: var(--p-600);
}

.bl-art-hd .ed-h1 {
  max-width: none;
  font-size: clamp(30px, 3.6vw, 48px);
  line-height: 1.12;
}

.bl-art-hd .bl-meta {
  margin-top: clamp(20px, 2.5vh, 28px);
}

.bl-art-cover {
  max-width: 680px;
  margin: clamp(36px, 4.5vh, 56px) auto clamp(40px, 5vh, 60px);
}

/* the standfirst — a real element, split off the body in PHP rather than styled
   as :first-child, so it can sit ABOVE the contents list */
.bl-deck {
  margin-bottom: clamp(32px, 4vh, 44px);
  font-size: 20px;
  line-height: 1.6;
  color: var(--ink-2);
}

.bl-deck em {
  font-style: normal;
  color: inherit;
}

/* ---- CONTENTS — the first of two chunking devices. Gives the reader the shape
   of the article up front and a way back into it. The numerals are the same
   counter the h2s use, so list and body read as one numbered spine. ---- */
.bl-toc {
  margin-bottom: clamp(40px, 5vh, 56px);
  padding: clamp(22px, 2.8vh, 28px) 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.bl-toc-h {
  display: block;
  margin-bottom: 16px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
}

.bl-toc-list {
  counter-reset: toc;
  display: grid;
  gap: 10px;
  list-style: none;
}

.bl-toc-list li {
  counter-increment: toc;
  display: flex;
  gap: 14px;
  margin: 0;
}

.bl-toc-list li::before {
  content: counter(toc, decimal-leading-zero);
  flex: none;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
  letter-spacing: 0.08em;
  color: var(--p-400);
  font-variant-numeric: tabular-nums;
}

.bl-toc-list a {
  font-size: 16px;
  line-height: 1.5;
  color: var(--ink-2);
  transition: color 0.2s var(--ease);
}

.bl-toc-list a:hover {
  color: var(--p-700);
}

/* ---- the body ---- */
.bl-article {
  counter-reset: sec;
  font-size: 18px;
  line-height: 1.7;
  color: var(--ink-2);
}

/* The second chunking device: each h2 becomes a numbered, ruled section break
   rather than just larger text. Before this the body was an undifferentiated run
   of 24px heads and 18px paragraphs, which is what made it hard to finish —
   there were no landmarks. The rule is a structural divider spanning the column,
   not a callout marker. */
.bl-article h2 {
  counter-increment: sec;
  margin: clamp(52px, 6.5vh, 72px) 0 0;
  padding-top: clamp(26px, 3.2vh, 34px);
  border-top: 1px solid var(--line);
  font-size: 24px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.02em;
  color: var(--ink);
  /* clear the fixed nav when jumped to from the contents list */
  scroll-margin-top: calc(var(--nav-h) + 30px);
}

.bl-article h2::before {
  content: counter(sec, decimal-leading-zero);
  display: block;
  margin-bottom: 12px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  color: var(--p-600);
}

.bl-article h3 {
  margin: clamp(32px, 4vh, 40px) 0 0;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--ink);
}

/* a paragraph straight after a heading is part of the same unit */
.bl-article h2 + p,
.bl-article h3 + p {
  margin-top: 14px;
}

.bl-article p,
.bl-article ul,
.bl-article ol {
  margin-top: 24px;
}

.bl-article li {
  margin-top: 8px;
  margin-left: 22px;
  list-style: disc;
}

.bl-article ol li {
  list-style: decimal;
}

.bl-article li::marker {
  color: var(--faint);
}

.bl-article strong,
.bl-article b {
  font-weight: 500;
  color: var(--ink);
}

.bl-article em {
  color: var(--muted);
}

.bl-article a {
  color: var(--p-700);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--p-200);
  transition:
    color 0.2s var(--ease),
    text-decoration-color 0.2s var(--ease);
}

.bl-article a:hover {
  color: var(--p-500);
  text-decoration-color: currentColor;
}

.bl-article img {
  display: block;
  margin: clamp(32px, 4vh, 44px) auto;
  border-radius: 12px;
}

/* ---- pull quote ---------------------------------------------------------
   NO STROKE ON ONE EDGE. A coloured bar down the left is the default blockquote
   move and it is the wrong one: the accent lands as a 2px sliver at the far edge,
   too peripheral to register as emphasis, and the block still reads as body copy
   that has been indented. A callout is a SURFACE — its own accent-tinted ground,
   a full border on all four sides, and type in a different voice.

   The serif is the site's ONE documented exception to "Geist everywhere". It
   breaks a hierarchy tie: 24px sans collided with the h2 (24/500) and 20px sans
   collided with the standfirst, so changing the FAMILY is what separates it.
   Source Serif 4 is a TEXT serif — a display serif's tight tracking read cramped
   here. Let the face's metrics do the spacing; do not add letter-spacing.
   ---- */
.bl-article blockquote {
  margin: clamp(40px, 5vh, 56px) 0 clamp(16px, 2vh, 24px);
  padding: clamp(28px, 3.4vh, 36px) clamp(28px, 3.4vw, 40px);
  border: 1px solid var(--p-200);
  border-radius: 16px;
  background: var(--p-50);
  box-shadow: var(--hi);
  font-family: var(--serif);
  font-size: 20px;
  line-height: 1.6;
  letter-spacing: normal;
  /* --p-600 not --p-700: the darker step reads as near-black with a purple cast
     at this size. ~5.9:1 on --p-50, past AA. */
  color: var(--p-600);
}

/* the colour has to be set on the inner <p> too — a rule matching the paragraph
   directly beats any inherited value however specific the ancestor selector is */
.bl-article blockquote p {
  margin: 0;
  color: inherit;
}

.bl-article blockquote p + p {
  margin-top: 14px;
}

/* ---- the stat row.
   Pasted posts carry three headline figures as an inline-styled grid on a
   near-black slab, in Georgia and mint green. functions.php throws that markup
   away and re-emits the figures in these classes, so the row is styled here
   like every other component instead of by whoever wrote the paste.

   Quieter than the blockquote on purpose: the purple plate is the pull-quote's
   voice, and two loud plates in one column compete. This is a hairline-framed
   band on the pale ground, with the figures carrying the only colour. Left
   aligned, not centred — the article is a single ragged-right column and centred
   text inside it reads as a foreign object.

   auto-fit rather than a media query: the column is ~680px and three 160px
   tracks fit with room, so the row reflows to two and then one on its own.
   ---- */
.bl-article .bl-figs {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: clamp(20px, 2.4vw, 32px);
  margin: clamp(40px, 5vh, 56px) 0 clamp(16px, 2vh, 24px);
  padding: clamp(24px, 3vh, 32px) clamp(24px, 3vw, 36px);
  border: 1px solid var(--line);
  border-radius: 16px;
  background: var(--cream-1);
}

.bl-article .bl-fig {
  display: block;
}

/* Figures are their own type tier — not a heading size, and not body. Tabular
   numerals so `$9.2B` and `3–5%` sit on the same rhythm across the row. */
.bl-article .bl-fig-n {
  display: block;
  font-size: 34px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: var(--p-600);
}

.bl-article .bl-fig-t {
  display: block;
  margin-top: 10px;
  font-size: 14px;
  line-height: 1.45;
  color: var(--muted);
}

/* ==========================================================================
   §4 CLOSE — the dark contact band
   ========================================================================== */
.sig-band {
  position: relative;
  overflow: clip;
  padding: clamp(96px, 12vh, 152px) 0;
  background:
    radial-gradient(
      60% 70% at 12% 8%,
      rgba(var(--p300-rgb), 0.22),
      transparent 62%
    ),
    radial-gradient(
      52% 62% at 92% 96%,
      rgba(var(--cyan-rgb), 0.14),
      transparent 60%
    ),
    linear-gradient(158deg, var(--p-700) 0%, var(--p-900) 100%);
}

.sig-band::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: linear-gradient(90deg, #9a80fb, #a78bfa, #e8e0fe, #7752f9);
  opacity: 0.55;
}

.sig-flow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  -webkit-mask: linear-gradient(
    180deg,
    transparent,
    #000 22%,
    #000 78%,
    transparent
  );
  mask: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}

.sig-flow .sf-line {
  fill: none;
  stroke: rgba(255, 255, 255, 0.16);
  stroke-width: 1.2;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

.sig-flow .sf-dash {
  stroke: rgba(255, 255, 255, 0.12);
  stroke-dasharray: 4 5;
}

.sig-flow .sf-pulse {
  fill: none;
  stroke: var(--zone-accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-dasharray: 0.03 0.97;
  vector-effect: non-scaling-stroke;
  opacity: 0;
  animation: bl-net-pulse 36s linear infinite;
}

.sig {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}

.sig-logo {
  display: block;
  margin-bottom: 28px;
  line-height: 0;
}

.sig-logo svg {
  width: 96px;
  height: auto;
}

.sig-logo svg path {
  fill: var(--zone-accent);
}

.sig-copy h2 {
  font-size: clamp(30px, 4.4vw, 60px);
  font-weight: 400;
  line-height: 1.08;
  letter-spacing: -0.026em;
  color: #fff;
}

.sig-copy h2 .t-acc {
  color: var(--zone-accent);
}

.sig-lead {
  margin-top: 24px;
  font-size: 18px;
  line-height: 1.6;
  color: rgba(var(--zone-ink-rgb), 0.7);
  max-width: 34em;
}

.sig-sub {
  margin-top: 28px;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: rgba(var(--zone-ink-rgb), 0.46);
}

.sig-form {
  padding: clamp(24px, 3vw, 32px);
  border-radius: 16px;
  background: var(--surface);
  box-shadow: 0 40px 80px -50px rgba(10, 4, 32, 0.7);
}

.sig-form-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.sig-field {
  display: block;
  grid-column: 1 / -1;
}

.sig-field.half {
  grid-column: auto;
}

.sig-field-l {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 500;
  color: var(--ink);
}

.sig-input {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--paper);
  font-family: var(--sans);
  font-size: 16px;
  color: var(--ink);
}

.sig-input::placeholder {
  color: var(--faint);
}

.sig-input:focus {
  outline: 0;
  border-color: var(--p-400);
  box-shadow: 0 0 0 3px rgba(var(--p300-rgb), 0.28);
}

.sig-textarea {
  resize: vertical;
  min-height: 84px;
}

.sig-form-err {
  margin-top: 12px;
  font-size: 14px;
  color: var(--neg);
}

.sig-submit {
  width: 100%;
  justify-content: center;
  margin-top: 20px;
}

.sig-submit[disabled] {
  opacity: 0.6;
  cursor: default;
}

.sig-form-done {
  text-align: center;
  padding: 20px 0;
}

.sig-form-done h3 {
  font-size: 20px;
  font-weight: 500;
  color: var(--ink);
}

.sig-form-done p {
  margin-top: 8px;
  color: var(--muted);
}

/* ==========================================================================
   FOOTER — banded sitemap, brand + legal (no giant wordmark)
   A verbatim port of site.css's FOOTER block, `#site` scope stripped.
   ========================================================================== */
.footer {
  position: relative;
  overflow: hidden;
  padding: 84px 0 48px;
  background: var(--paper);
  border-top: 1px solid var(--line);
}
.footer .wrap {
  position: relative;
  z-index: 6;
}
/* neutral only — no accent blooms on the footer ground */
.foot-grad {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg, var(--tint-2) 0%, var(--paper) 42%);
}
.footer .brand {
  color: var(--ink);
}
/* sitemap grid — one even column per nav group, no orphaned group.

   FOUR TRACKS, not five. The fifth was the Pricing column, delisted
   2026-08-20 — at `repeat(5, 1fr)` the four remaining columns left a whole
   empty track on the right and the group of four read as off-centre against
   the band below it. The ≤1023 fold stays at three, where four columns wrap to
   3 + 1 rather than leaving a hole. */
.foot-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 32px;
  padding: 0 0 44px;
}
.foot-col h4 {
  font-family: var(--mono);
  font-size: max(8px, calc(12px * var(--viz-fs)));
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  font-weight: 500;
  margin-bottom: 16px;
}
.foot-col a,
.foot-col .foot-na {
  display: block;
  font-size: 14px;
  color: var(--ink-2);
  padding: 6px 0;
  transition: color 0.2s;
}
.foot-col a:hover {
  color: var(--p-700);
}
/* unwired footer item — reads as a normal link, no navigation yet */
.foot-col .foot-na {
  cursor: default;
}
/* brand + summary band */
.foot-band {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 32px 48px;
  padding: 34px 0;
}
.foot-brand {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.foot-brand .brand {
  display: inline-block;
}
.foot-social {
  display: inline-flex;
  margin-top: 20px;
  color: var(--faint);
  transition: color 0.2s;
}
.foot-social:hover {
  color: var(--p-700);
}
.foot-social svg {
  display: block;
  width: 22px;
  height: 22px;
}
/* under the logo now, so it reads left with the rest of the brand stack — it was
   right-aligned when it sat opposite, in the band's other column. */
.foot-desc {
  max-width: 24em;
  margin: 18px 0 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--muted);
}
/* MEMBERSHIPS BOX — port of `.foot-memb` in the marketing site's site.css; that
   file is canonical and carries the full reasoning. The short version:
   · neutral ground, no border. `--tint-1` and not `--surface-2`, because
     --surface-2 is 3.6 L* off white and needs a border to be seen at all.
   · the caption is plain Geist at the 12px micro-label floor, `--muted`, which
     measures 4.67 on this ground.
   · contents flush LEFT, and the caption is kept shorter than the mark so the
     mark sets the column width and sits flush both sides. A caption longer than
     the mark makes the mark the narrower child and it gains a one-sided gap.
   · the marks wrap INSIDE the box, so a second association changes this box's
     height and nothing else on the page. */
.foot-memb {
  text-align: left;
  padding: 16px 18px;
  border-radius: 14px;
  background: var(--tint-1);
}
.foot-memb-l {
  display: block;
  margin-bottom: 12px;
  font-size: max(8px, calc(12px * var(--viz-fs)));
  font-weight: 400;
  line-height: 1.5;
  color: var(--muted);
}
.foot-memb-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 20px;
}
/* the marks keep their own colours — a third party's registered mark is not
   ours to recolour. 150px is a legibility floor for this lockup: its two lines
   of name are unreadable much below it. */
.foot-badge {
  flex: none;
  width: 150px;
  height: auto;
}
/* copyright. The legal-link row and the Westbon NMLS / South Carolina /
   Michigan disclosures were deleted on the marketing site — consumer-lending
   fine print from the Boro-era site, not this B2B platform. */
.foot-base {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 32px;
  padding-top: 26px;
  border-top: 1px solid var(--line);
}
.foot-copy {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
}
/* ONE declaration for the legal row's type tier, shared by the copyright text
   and the notice links, so the two halves of the row cannot drift apart. */
.foot-copy .mono,
.foot-legal a {
  font-family: var(--mono);
  font-size: max(8px, calc(12px * var(--viz-fs)));
  letter-spacing: 0.06em;
  color: var(--muted);
}
/* THE NOTICE LINKS — port of `.foot-legal` in the marketing site's site.css,
   which is canonical. They take the free half `.foot-base`'s space-between
   already reserves, so the row stays one line and gains no height.

   Grey, not purple: they inherit the copyright's `--muted` from the tier above
   rather than restating it, so the row reads as one voice. That leaves the
   UNDERLINE carrying the affordance by itself, which is why it is not optional
   — nothing else separates these from the two spans beside them that are not
   links. 1px at a 3px offset, thickening on hover, the site's own recipe.
   Hover also goes `--p-700`, as every other link in this footer does. */
.foot-legal {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
}
.foot-legal a {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.2s;
}
.foot-legal a:hover {
  color: var(--p-700);
  text-decoration-thickness: 2px;
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 1023px) {
  :root {
    --viz-fs: 0.94;
  }

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

  .foot-grid {
    grid-template-columns: repeat(3, 1fr);
    gap: 32px 28px;
  }
}

@media (max-width: 980px) {
  .sig {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ===== the nav's own breakpoint =====
   Measured on the marketing site, not picked: brand 73 + links 418 + CTA group
   236 = 727px of content, and the gutters are 48px a side. That overflows
   823px, and the space between the three groups falls under the links row's
   own 36px gap at ~895px. So the row hands over to the burger here, and the
   drawer becomes the page's only navigation. `.mega` goes too: its triggers
   live in the row being hidden. */
@media (max-width: 900px) {
  :root {
    --viz-fs: 0.88;
  }

  .brand svg {
    height: 18px;
  }

  .btn {
    padding: 10px 18px;
    font-size: 14px;
  }

  .nav-links,
  .nav-login,
  .mega {
    display: none;
  }

  /* the CTA goes with them, into the drawer as `.nd-cta`. In the bar it sat
     immediately beside the brand and pushed the burger into the middle of the
     row. */
  .nav-cta .btn {
    display: none;
  }

  /* TWO TRACKS. `display: none` takes `.nav-links` out of PLACEMENT but not
     out of the track list, so with three tracks declared the CTA group
     auto-placed into the middle `auto` one and the trailing `1fr` sat empty
     behind it. Two tracks put the burger back on the right edge, where
     `.nav-cta`'s `justify-self: end` always meant to hold it. */
  .nav-in {
    grid-template-columns: 1fr auto;
  }

  .menu-btn,
  .nav-drawer {
    display: block;
  }
}

/* Once the copy spans the full width there is no left/right split for the net's
   radial hole to sit in, and the tubes start crossing the subtitle. Below this
   the mask keeps only the top and bottom bands. */
@media (max-width: 860px) {
  .bl-net {
    opacity: 0.55;
    -webkit-mask: linear-gradient(
      180deg,
      #000 0 15%,
      transparent 30%,
      transparent 72%,
      #000 94%
    );
    mask: linear-gradient(
      180deg,
      #000 0 15%,
      transparent 30%,
      transparent 72%,
      #000 94%
    );
  }
}

@media (max-width: 900px) {
  .bp-lg {
    min-height: 240px;
  }
}

@media (max-width: 680px) {
  :root {
    --viz-fs: 0.84;
    --gutter: 24px;
  }

  .brand svg {
    height: 16px;
  }

  .nd-row {
    font-size: 14px;
  }

  .foot-grid {
    grid-template-columns: 1fr 1fr;
    gap: 28px 32px;
  }

  .foot-band,
  .foot-base {
    flex-direction: column;
    align-items: flex-start;
  }


  .bl-bar-in {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 12px 0;
  }

  .bl-search {
    width: 100%;
  }

  /* the chips need the gutter's full bleed to scroll cleanly. "All" keeps its
     place at the left gutter and the rail bleeds off the right edge. */
  .bl-chips {
    margin-right: -24px;
  }

  .bl-rail {
    padding: 2px 24px 2px 0;
  }

  .bl-grid {
    grid-template-columns: minmax(0, 1fr);
    gap: 32px;
  }

  .bp,
  .bp-lg {
    height: 196px;
    min-height: 196px;
    padding: 18px;
  }

  .bl-art-hd .ed-h1 {
    font-size: 30px;
  }

  /* 24px in a 342px column ran the callout to nine lines and it swallowed the
     screen; the padding is what needs easing, the size is already 20px */
  .bl-article blockquote {
    padding: 24px;
  }

  .sig-form-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .sig-field.half {
    grid-column: 1 / -1;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .bl-cell {
    animation: none;
  }

  .bl-card:hover .bp {
    transform: none;
  }

  .bl-net .bn-pulse,
  .sig-flow .sf-pulse {
    animation: none;
    opacity: 0;
  }
}
