/* ════════════════════════════════════════════════════════════════════════
   Browser surfaces — the parts we did not draw.

   Text selection, the caret, the scrollbar, the focus ring, the underline
   offset and the numerals in money columns all ship with browser defaults
   that belong to no design system. They were themed on three of the public
   pages (the v2/v3 landing set) and left at the default on the other ten,
   which is the kind of gap that reads as "assembled" rather than "built".

   This is a system concern, not a page concern, so it lives in one file that
   loads last on every public page. Tokens are read with literal fallbacks
   because the public pages run two token systems: v2/v3 on the landing set
   and style.css on the blog set.
   ════════════════════════════════════════════════════════════════════════ */

/* Selection: the fill, so white sits on it at 5.2:1 rather than the lighter
   --accent, which measured 4.5:1 with white on top. */
::selection {
  background: var(--accent-fill, #3a62e0);
  color: #fff;
}

/* The caret was the OS default black/white on every field. */
/* ── the public typeface ───────────────────────────────────────────────────
   Public Sans, chosen 2026-08-22 off the five-face button mock, for one
   reason: the numerals. On a page whose whole argument is that the numbers
   are right, a 6 that could read as an 8 is a defect, not a preference. It
   is the US Web Design System face, which is not a constraint on using it,
   only where it came from: an open grotesque built to be read by everyone at
   small sizes. IBM Plex Mono stays as --mono.

   It is declared here because this file loads last on all twelve public
   pages, including blog, privacy and terms, which also pull in the app's
   style.css and would otherwise keep its --font. style.css itself is out of
   bounds, so this is the one place that can set the face for every public
   page without reaching into the app. */
:root {
  --font: 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}


html {
  caret-color: var(--accent-ink, #2f50c4);
  scrollbar-color: var(--border2, #c8cad8) transparent;
  scrollbar-width: thin;
}

/* WebKit and Blink still need the older pseudo-elements. The transparent
   border plus background-clip gives the thumb breathing room inside the
   track without drawing a track. */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border2, #c8cad8);
  background-clip: content-box;
  border: 3px solid transparent;
  border-radius: 99px;
}
::-webkit-scrollbar-thumb:hover {
  background: var(--text2, #4a4f6a);
  background-clip: content-box;
}
::-webkit-scrollbar-corner { background: transparent; }

/* One focus ring for every interactive control, in the ink blue so it clears
   contrast on both themes. :where() keeps specificity at zero so any page
   that needs a different offset can still say so. */
:where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent-ink, #2f50c4);
  outline-offset: 2px;
}

/* The default underline sits on the baseline and cuts through descenders. */
a { text-underline-offset: 0.18em; }
a:where(:hover, :focus-visible) { text-decoration-thickness: 1px; }

/* Money and measurements have to line up column to column. */
:where(td, th, output, .num, .v, .amt, [data-num]) { font-variant-numeric: tabular-nums; }

/* Inline icons inside links and buttons. An <svg> with a viewBox but no
   width/height falls back to the replaced-element default of 300x150, so a
   size has to exist somewhere. :where() keeps this at zero specificity: every
   component that already sizes its own icons still wins. */
:where(a, button) > svg {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
  vertical-align: -0.13em;
}
/* Links carrying an arrow need the gap that the .btn components already have. */
:where(a, button):has(> svg) { gap: 0.42em; }

/* Inline links in running prose had no hover response on several pages. The
   underline thickens rather than the colour changing, so the link keeps its
   meaning. Low specificity: any component that styles its own links wins. */
:where(p, li, dd, blockquote) a { transition: text-decoration-thickness .12s ease; }
:where(p, li, dd, blockquote) a:hover { text-decoration-thickness: 2px; }

/* ── one corner, everywhere ─────────────────────────────
   The site was shipping six different corner radii at once: 2px on the login
   submit, 6px on the blog nav, 7px on small buttons, 8px on normal ones, 10px
   on the calculator's shape tabs and 16px on the blog filter pills. Six systems
   is not a system, and the 8px rounded rectangle is the single most generic
   control shape there is.

   The chosen visual world already asked for square. This finishes it: every
   interactive control is a right angle, so a button reads as something drawn
   on a drawing rather than as app-store chrome.

   .nav-cta and .nav-login are declared in style.css, which is the app's sheet
   and off limits for public-site work, so they are corrected here. This file
   loads last on all 22 pages, which is exactly why cross-cutting chrome
   belongs in it. */
.site-nav .nav-cta,
.site-nav .nav-login,
.site-nav .theme-btn,
.theme-btn,
.ln-pw-toggle { border-radius: 0; }
