@charset "utf-8";
/* ==========================================================================
   4calculators.com — core stylesheet
   Aesthetic: precision instrument / engineering handbook.
   Dense, legible, tabular, no ornament that does not carry information.
   No external fonts, no frameworks, no runtime CSS. All paths relative.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */
:root {
  /* Type */
  --ff-ui: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
           "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --ff-mono: ui-monospace, "SF Mono", "SFMono-Regular", "Cascadia Mono",
             "JetBrains Mono", "Roboto Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --fs-3xs: 0.6875rem;  /* 11px  — micro labels, table units */
  --fs-2xs: 0.75rem;    /* 12px  — captions, help text */
  --fs-xs:  0.8125rem;  /* 13px  — dense UI, table body */
  --fs-sm:  0.875rem;   /* 14px  — secondary prose */
  --fs-md:  1rem;       /* 16px  — body */
  --fs-lg:  1.125rem;   /* 18px  — lede */
  --fs-xl:  1.375rem;   /* 22px  — h3 */
  --fs-2xl: 1.75rem;    /* 28px  — h2 */
  --fs-3xl: 2.25rem;    /* 36px  — h1 */
  --fs-4xl: 2.875rem;   /* 46px  — hero figure */

  --lh-tight: 1.18;
  --lh-snug: 1.35;
  --lh-body: 1.68;

  /* Spacing — 4px base, geometric-ish */
  --s-1: 0.25rem;  --s-2: 0.5rem;   --s-3: 0.75rem;  --s-4: 1rem;
  --s-5: 1.5rem;   --s-6: 2rem;     --s-7: 3rem;     --s-8: 4rem;   --s-9: 6rem;

  /* Radii — small and deliberate; this is instrumentation, not candy */
  --r-sm: 3px; --r-md: 5px; --r-lg: 8px; --r-xl: 12px;

  /* Light theme (default) */
  --c-bg:            #f4f6f9;
  --c-bg-grid:       #dfe5ee;
  --c-surface:       #ffffff;
  --c-surface-2:     #f1f4f8;
  --c-surface-3:     #e7ecf3;
  /* --c-border is decorative only. --c-border-strong bounds interactive controls
     and must clear WCAG 1.4.11 (3:1) against the surfaces it sits on:
     #8a97a6 measures 3.02:1 on #ffffff and 2.87:1 on #f1f4f8, so controls also
     carry a --c-surface-2 fill to identify themselves independent of the edge. */
  --c-border:        #d6dde7;
  --c-border-strong: #8a97a6;
  --c-rule:          #c3ccd9;   /* medium decorative rule: section heads, table heads */
  --c-text:          #131b25;
  --c-text-2:        #46566a;
  /* #5c6a7b: 5.52:1 on #ffffff, 5.10:1 on #f4f6f9, 5.01:1 on #f1f4f8,
     4.65:1 on #e7ecf3, 4.80:1 on #e7f0fa — passes 4.5:1 on every surface it is used on. */
  --c-text-3:        #5c6a7b;
  --c-text-inv:      #ffffff;

  --c-accent:        #14539a;
  --c-accent-hover:  #0f3f77;
  --c-accent-soft:   #e7f0fa;
  --c-accent-line:   #a9c6e6;

  --c-signal:        #a4560a;   /* standards / amber */
  --c-signal-soft:   #fdf3e4;
  --c-signal-line:   #e8cba0;

  --c-pos:           #0b6b52;
  --c-pos-soft:      #e5f4ef;
  --c-pos-line:      #a3d5c5;

  --c-neg:           #a91f26;
  --c-neg-soft:      #fdecec;
  --c-neg-line:      #eeb4b4;

  --c-focus:         #1e7ae0;
  --c-chart-4:       #7a5ea8;

  --sh-1: 0 1px 1px rgba(19, 27, 37, .04), 0 1px 2px rgba(19, 27, 37, .05);
  --sh-2: 0 1px 2px rgba(19, 27, 37, .05), 0 3px 8px rgba(19, 27, 37, .06);
  --sh-3: 0 2px 4px rgba(19, 27, 37, .06), 0 8px 24px rgba(19, 27, 37, .09);

  --wrap: 1340px;
  /* 62ch ~= 535px ~= 75 characters of running prose. `ch` is the advance of "0"
     (8.63px in this stack) but average prose glyphs measure 7.16px, so 74ch was
     rendering 89 characters per line — past the WCAG 1.4.8 80-character ceiling. */
  --measure: 62ch;
  --header-h: 56px;
}

/* The header and drawer carry the dark palette in BOTH themes. The brand mark is
   a white-on-transparent lockup, so it needs a dark plate under it; a permanently
   dark bar over a light page reads as a deliberate masthead rather than a defect,
   and the light theme still owns the whole content column below it. */
[data-theme="dark"], .site-header, .drawer {
  --c-bg:            #0d1219;
  --c-bg-grid:       #18212c;
  --c-surface:       #141c25;
  --c-surface-2:     #1a232e;
  --c-surface-3:     #222d3a;
  --c-border:        #26313f;
  --c-border-strong: #5b6b7d;
  --c-rule:          #35424f;
  --c-text:          #e6ecf3;
  --c-text-2:        #a4b2c2;
  /* #8695a7: 4.96:1 on --c-accent-soft, 4.57:1 on --c-surface-3, 6.15:1 on --c-bg. */
  --c-text-3:        #8695a7;
  --c-text-inv:      #0d1219;

  --c-accent:        #6aa9e9;
  --c-accent-hover:  #8fc0f2;
  --c-accent-soft:   #16273a;
  --c-accent-line:   #2d4c6e;

  --c-signal:        #e0a35c;
  --c-signal-soft:   #2a2116;
  --c-signal-line:   #4d3b22;

  --c-pos:           #5fc9a5;
  --c-pos-soft:      #12261f;
  --c-pos-line:      #245043;

  --c-neg:           #f08a8a;
  --c-neg-soft:      #2a1618;
  --c-neg-line:      #55282b;

  --c-focus:         #6aa9e9;
  --c-chart-4:       #a98cd8;

  /* Dark elevation comes from a light top edge, not a black shadow: a black
     shadow is invisible against #0d1219 and carries no information. */
  --sh-1: 0 1px 0 rgba(255, 255, 255, .04), 0 1px 2px rgba(0, 0, 0, .5);
  --sh-2: 0 0 0 1px rgba(255, 255, 255, .05), 0 4px 12px rgba(0, 0, 0, .55);
  --sh-3: 0 0 0 1px rgba(255, 255, 255, .07), 0 12px 32px rgba(0, 0, 0, .6);
}

/* --------------------------------------------------------------------------
   2. Reset / base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--s-4));
  font-size: 100%;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  font-family: var(--ff-ui);
  font-size: var(--fs-md);
  line-height: var(--lh-body);
  color: var(--c-text);
  background-color: var(--c-bg);
  background-image:
    linear-gradient(var(--c-bg-grid) 1px, transparent 1px),
    linear-gradient(90deg, var(--c-bg-grid) 1px, transparent 1px);
  background-size: 88px 88px, 88px 88px;
  background-position: -1px -1px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  overflow-x: hidden;
  text-underline-offset: 0.16em;
}

img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
:where(a) { color: var(--c-accent); text-decoration-thickness: 1px; }
:where(a):hover { color: var(--c-accent-hover); }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--c-focus);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

h1, h2, h3, h4, h5, h6 { line-height: var(--lh-tight); font-weight: 600; letter-spacing: -0.011em; text-wrap: balance; }
p, li { text-wrap: pretty; }

code, kbd, samp, var, .mono { font-family: var(--ff-mono); font-size: 0.925em; font-variant-ligatures: none; }
var { font-style: normal; font-weight: 600; color: var(--c-accent); }
:where(p, li, td, dd) > code {
  background: var(--c-surface-2); border: 1px solid var(--c-border);
  border-radius: var(--r-sm); padding: 0.08em 0.34em; white-space: nowrap;
}
kbd {
  background: var(--c-surface-2); border: 1px solid var(--c-border-strong);
  border-bottom-width: 2px; border-radius: var(--r-sm);
  padding: 0.08em 0.36em; font-size: 0.85em;
}

.tnum { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: var(--s-3); top: -100px; z-index: 200;
  background: var(--c-accent); color: var(--c-text-inv); padding: var(--s-2) var(--s-4);
  border-radius: var(--r-md); font-size: var(--fs-sm); font-weight: 600; text-decoration: none;
}
.skip-link:focus { top: var(--s-3); color: var(--c-text-inv); }

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */
.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--s-4); }
@media (min-width: 720px) { .wrap { padding-inline: var(--s-5); } }

.stack > * + * { margin-top: var(--s-4); }
.stack-lg > * + * { margin-top: var(--s-6); }

/* Two-column: main + right rail */
.layout {
  display: grid; gap: var(--s-6); align-items: start;
  grid-template-columns: minmax(0, 1fr);
  padding-block: var(--s-5) var(--s-8);
}
@media (min-width: 1080px) {
  .layout { grid-template-columns: minmax(0, 1fr) 292px; gap: var(--s-7); }
}
.rail { display: none; }
@media (min-width: 1080px) {
  .rail { display: block; position: sticky; top: calc(var(--header-h) + var(--s-4)); }
  .rail > * + * { margin-top: var(--s-5); }
}

/* --------------------------------------------------------------------------
   4. Header / nav
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in srgb, var(--c-surface) 88%, transparent);
  backdrop-filter: saturate(150%) blur(10px);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid var(--c-border);
}
@supports not (backdrop-filter: blur(4px)) { .site-header { background: var(--c-surface); } }

.site-header__bar {
  height: var(--header-h);
  display: flex; align-items: center; gap: var(--s-4);
}

.brand {
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-weight: 700; font-size: 1.0625rem; letter-spacing: -0.02em;
  color: var(--c-text); text-decoration: none; white-space: nowrap; flex: none;
}
.brand:hover { color: var(--c-text); }
.brand:hover .brand__logo { opacity: .82; }
/* Intrinsic 826x114. Height is the control dimension so the bar never reflows;
   width follows. Below 720px the search field needs the room, so it steps down. */
.brand__logo { display: block; height: 28px; width: auto; flex: none; }
@media (max-width: 719px) { .brand__logo { height: 23px; } }

/* Popular and A–Z only; everything else is in the browse panel. Moving search out
   of the header freed the row, so these can appear from 520px instead of needing
   960px. Below that the wordmark plus two controls already fill the bar, and both
   links lead the browse panel instead. */
.nav-primary { display: none; }
@media (min-width: 520px) {
  .nav-primary { display: flex; align-items: center; gap: 2px; margin-inline-start: var(--s-3); }
}
.nav-primary a {
  display: inline-block; padding: var(--s-2) var(--s-3);
  font-size: var(--fs-sm); font-weight: 500; color: var(--c-text-2);
  text-decoration: none; border-radius: var(--r-md);
}
.nav-primary a:hover { background: var(--c-surface-2); color: var(--c-text); }
.nav-primary a[aria-current="page"] { color: var(--c-accent); background: var(--c-accent-soft); }

.header-tools { margin-inline-start: auto; display: flex; align-items: center; gap: var(--s-2); }

.icon-btn {
  display: inline-grid; place-items: center; flex: none; width: 34px; height: 34px;
  background: transparent; border: 1px solid transparent; border-radius: var(--r-md);
  color: var(--c-text-2);
}
.icon-btn:hover { background: var(--c-surface-2); color: var(--c-text); border-color: var(--c-border); }
.icon-btn svg { width: 17px; height: 17px; }

/* Search */
.search { position: relative; flex: 1 1 auto; max-width: 420px; }
@media (max-width: 719px) { .search { max-width: none; } }
.search__input {
  width: 100%; height: 34px; padding: 0 var(--s-3) 0 30px;
  background: var(--c-surface-2); border: 1px solid var(--c-border);
  border-radius: var(--r-md); font-size: var(--fs-sm); color: var(--c-text);
}
.search__input::placeholder { color: var(--c-text-3); }
.search__input:focus { background: var(--c-surface); border-color: var(--c-accent-line); }
.search__icon {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: var(--c-text-3); pointer-events: none;
}
.search__results {
  position: absolute; z-index: 120; inset-inline: 0; top: calc(100% + 6px);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-lg); box-shadow: var(--sh-3);
  max-height: min(70vh, 460px); overflow-y: auto; padding: var(--s-1);
}
.search__results[hidden] { display: none; }
.search__hit {
  display: block; padding: var(--s-2) var(--s-3); border-radius: var(--r-md);
  text-decoration: none; color: var(--c-text);
}
.search__hit:hover, .search__hit[aria-selected="true"] { background: var(--c-accent-soft); color: var(--c-text); }
.search__hit strong { display: block; font-size: var(--fs-sm); font-weight: 600; }
.search__hit strong mark { background: transparent; color: var(--c-accent); font-weight: 700; }
.search__hit span { display: block; font-size: var(--fs-2xs); color: var(--c-text-3); }
.search__empty { padding: var(--s-4); font-size: var(--fs-sm); color: var(--c-text-3); text-align: center; }

/* Site-wide search bar, directly under the header on every page.
   Search used to live inside .site-header__bar, where it was a flex sibling of
   the wordmark and two icon buttons: at 390px it measured 44px wide, which is not
   a search field, and it consumed the row that should carry navigation. Out here
   it gets the full content width and a proper touch height, and the header row is
   free for Popular and A–Z. Deliberately NOT sticky — pinning ~64px more chrome
   under an already-sticky header would cost a phone a fifth of its viewport. */
.searchbar {
  background: var(--c-surface-2);
  border-bottom: 1px solid var(--c-border);
  padding-block: var(--s-3);
}
.search--bar { max-width: none; flex: none; }
.search--bar .search__input {
  height: 46px; font-size: var(--fs-md); padding: 0 var(--s-4) 0 42px;
  background: var(--c-surface); border-radius: var(--r-lg);
}
.search--bar .search__icon { left: 14px; width: 17px; height: 17px; }
/* The fixed-position dropdown below is a fix for the old cramped header field;
   a full-width bar can anchor its own results normally. */
@media (max-width: 719px) {
  .search--bar .search__results {
    position: absolute; inset-inline: 0;
    inset-block-start: calc(100% + 6px);
    max-height: min(70vh, 460px);
  }
}

/* Popular calculators — one short list per subject */
.popular-group + .popular-group { margin-top: var(--s-6); }
.popular-group h3 {
  font-size: var(--fs-md); margin-bottom: var(--s-2);
  padding-bottom: var(--s-2); border-bottom: 2px solid var(--c-rule);
}
.popular-group h3 a { color: var(--c-text); text-decoration: none; }
.popular-group h3 a:hover { color: var(--c-accent); }
.popular-group__more { margin-top: var(--s-2); font-size: var(--fs-xs); }
.popular-group__more a { color: var(--c-accent); text-decoration: none; }
.popular-group__more a:hover { text-decoration: underline; }

/* Browse panel — the whole subject list, at every width.
   This used to be a mobile-only drawer holding a flat run of 47 links, and the
   header carried six family labels that each resolved to a single domain. Now
   one control opens every one of the 41 domains, grouped, from any page and any
   viewport, so the drawer toggle is no longer hidden on desktop. */
.btn-browse {
  display: inline-flex; align-items: center; gap: var(--s-2); flex: none;
  height: 34px; padding-inline: var(--s-3);
  background: transparent; border: 1px solid var(--c-border); border-radius: var(--r-md);
  font-size: var(--fs-sm); font-weight: 500; color: var(--c-text-2); cursor: pointer;
}
.btn-browse:hover { background: var(--c-surface-2); color: var(--c-text); border-color: var(--c-border-strong); }
.btn-browse[aria-expanded="true"] { background: var(--c-accent-soft); color: var(--c-accent); border-color: var(--c-accent-line); }
.btn-browse svg { width: 18px; height: 18px; }
/* Below 720px the label costs more than it explains — the icon and the panel
   itself carry the meaning, and the row needs the room for the search field. */
@media (max-width: 719px) {
  .btn-browse { width: 40px; height: 40px; padding-inline: 0; justify-content: center; }
  .btn-browse__label { display: none; }
}

.drawer {
  position: fixed; inset: var(--header-h) 0 0 0; z-index: 99;
  background: var(--c-surface); border-top: 1px solid var(--c-border);
  padding-block: var(--s-5) var(--s-8); overflow-y: auto;
  overscroll-behavior: contain;
}
.drawer[hidden] { display: none; }
.drawer__grid {
  display: grid; gap: var(--s-5) var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  align-items: start;
}
.drawer__title {
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--c-text-3);
  padding-bottom: var(--s-2); margin-bottom: var(--s-2);
  border-bottom: 1px solid var(--c-border);
}
.drawer__group ul { list-style: none; padding: 0; margin: 0; }
.drawer a {
  display: block; padding: var(--s-2) 0; font-size: var(--fs-sm);
  font-weight: 500; color: var(--c-text-2); text-decoration: none; line-height: 1.35;
}
.drawer a:hover { color: var(--c-accent); }
.drawer__group--site a { color: var(--c-text-3); font-size: var(--fs-xs); }

/* --------------------------------------------------------------------------
   5. Breadcrumbs & page head
   -------------------------------------------------------------------------- */
.crumbs { font-size: var(--fs-2xs); color: var(--c-text-3); padding-block: var(--s-4) 0; }
.crumbs ol { list-style: none; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-1); }
.crumbs li { display: inline-flex; align-items: center; gap: var(--s-1); }
.crumbs li + li::before { content: "/"; color: var(--c-border-strong); margin-inline-end: var(--s-1); }
.crumbs a { display: inline-block; padding-block: 4px; color: var(--c-text-2); text-decoration: none; }
.crumbs a:hover { color: var(--c-accent); text-decoration: underline; }
.crumbs [aria-current="page"] { color: var(--c-text); font-weight: 500; }

.page-head { padding-block: var(--s-4) 0; }
.page-head h1 {
  font-size: clamp(1.75rem, 1.35rem + 1.8vw, var(--fs-3xl));
  margin-bottom: var(--s-3);
}
.page-head__lede { font-size: var(--fs-lg); line-height: 1.55; color: var(--c-text-2); max-width: var(--measure); }
.page-head__lede p + p { margin-top: var(--s-3); }

.eyebrow {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2);
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--c-text-3); margin-bottom: var(--s-3);
}
.eyebrow a { display: inline-block; padding-block: 4px; color: var(--c-accent); text-decoration: none; }
.eyebrow a:hover { text-decoration: underline; }

.badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  padding: 3px 7px; border-radius: var(--r-sm);
  background: var(--c-signal-soft); color: var(--c-signal);
  border: 1px solid var(--c-signal-line);
}
.badge--accent { background: var(--c-accent-soft); color: var(--c-accent); border-color: var(--c-accent-line); }
.badge--pos { background: var(--c-pos-soft); color: var(--c-pos); border-color: var(--c-pos-line); }

.meta-line {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4);
  font-size: var(--fs-2xs); color: var(--c-text-3);
  padding-block: var(--s-4); margin-top: var(--s-4);
  border-block: 1px solid var(--c-border);
}
.meta-line b { font-weight: 600; color: var(--c-text-2); }

/* --------------------------------------------------------------------------
   6. Panels / cards
   -------------------------------------------------------------------------- */
.panel {
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-lg); box-shadow: var(--sh-1);
}
.panel__head {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--c-border);
  background: var(--c-surface-2);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.panel__head h2, .panel__head h3 {
  font-size: var(--fs-xs); font-weight: 700; letter-spacing: .07em;
  text-transform: uppercase; color: var(--c-text-2);
}
.panel__body { padding: var(--s-4); }
.panel__foot {
  padding: var(--s-3) var(--s-4); border-top: 1px solid var(--c-border);
  background: var(--c-surface-2); border-radius: 0 0 var(--r-lg) var(--r-lg);
  font-size: var(--fs-2xs); color: var(--c-text-3);
}

/* --------------------------------------------------------------------------
   7. The calculator
   -------------------------------------------------------------------------- */
.calc {
  background: var(--c-surface);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-xl);
  box-shadow: var(--sh-2);
  /* `overflow: hidden` here is what actually defeated the sticky results panel,
     on desktop as well as mobile: it makes .calc the nearest scroll container, so
     a sticky descendant sticks relative to a box that never scrolls and therefore
     never appears to stick at all. `overflow: clip` clips the child backgrounds
     to the rounded corners without establishing a scroll container. The `hidden`
     line stays first as the fallback for engines that do not know `clip`. */
  overflow: hidden;
  overflow: clip;
  scroll-margin-top: calc(var(--header-h) + var(--s-4));
}
.calc__grid { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 860px) {
  .calc__grid { grid-template-columns: minmax(0, 1.05fr) minmax(300px, 0.95fr); }
}

.calc__inputs { padding: var(--s-5); }
@media (min-width: 860px) { .calc__inputs { border-inline-end: 1px solid var(--c-border); } }

.calc__section-title {
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--c-text-3);
  padding-bottom: var(--s-2); margin-bottom: var(--s-4);
  border-bottom: 1px solid var(--c-border);
}

.fields { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--s-4) var(--s-3); }
.field { grid-column: span 6; min-width: 0; }
@media (min-width: 520px) {
  .field--half { grid-column: span 3; }
  .field--third { grid-column: span 2; }
}

.field__label {
  display: flex; align-items: baseline; gap: var(--s-2);
  font-size: var(--fs-sm); font-weight: 600; color: var(--c-text);
  margin-bottom: var(--s-2);
}
.field__req { color: var(--c-neg); font-weight: 400; }
.field__hint-btn {
  margin-inline-start: auto; flex: none; width: 16px; height: 16px;
  display: inline-grid; place-items: center; border-radius: 50%;
  border: 1px solid var(--c-border-strong); background: transparent;
  color: var(--c-text-3); font-size: 10px; font-weight: 700; line-height: 1;
}
.field__hint-btn:hover { border-color: var(--c-accent); color: var(--c-accent); background: var(--c-accent-soft); }

.control { display: flex; align-items: stretch; position: relative; }
.control__box {
  display: flex; align-items: stretch; flex: 1 1 auto; min-width: 0;
  background: var(--c-surface); border: 1px solid var(--c-border-strong);
  border-radius: var(--r-md); transition: border-color .12s, box-shadow .12s;
}
.control__box:focus-within {
  border-color: var(--c-focus);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-focus) 18%, transparent);
}
.control__affix {
  display: grid; place-items: center; padding-inline: var(--s-3);
  font-size: var(--fs-sm); font-weight: 600; color: var(--c-text-3);
  background: var(--c-surface-2); flex: none; white-space: nowrap;
}
.control__affix--prefix { border-inline-end: 1px solid var(--c-border); border-radius: var(--r-md) 0 0 var(--r-md); }
.control__affix--suffix { border-inline-start: 1px solid var(--c-border); border-radius: 0 var(--r-md) var(--r-md) 0; }

.control input[type="number"], .control input[type="text"] {
  flex: 1 1 auto; min-width: 0; width: 100%;
  padding: 9px var(--s-3); border: 0; background: transparent;
  font-family: var(--ff-mono); font-size: var(--fs-md); font-weight: 500;
  font-variant-numeric: tabular-nums; color: var(--c-text);
  border-radius: var(--r-md);
}
.control input:focus { outline: none; }
.control input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.control input[type="number"]::-webkit-outer-spin-button,
.control input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.control select {
  flex: 1 1 auto; min-width: 0; width: 100%;
  padding: 9px 30px 9px var(--s-3); border: 0; background: transparent;
  font-size: var(--fs-sm); font-weight: 500; color: var(--c-text);
  appearance: none; -webkit-appearance: none; border-radius: var(--r-md);
}
.control--select::after {
  content: ""; position: absolute; right: 11px; top: 50%; width: 8px; height: 8px;
  margin-top: -5px; pointer-events: none;
  border-right: 2px solid var(--c-text-3); border-bottom: 2px solid var(--c-text-3);
  transform: rotate(45deg);
}
.control__unit {
  flex: none; position: relative;
  border-inline-start: 1px solid var(--c-border);
  background: var(--c-surface-2); border-radius: 0 var(--r-md) var(--r-md) 0;
}
.control__unit select {
  padding: 9px 26px 9px var(--s-3); font-size: var(--fs-xs); font-weight: 600;
  color: var(--c-text-2); cursor: pointer;
}
.control__unit::after {
  content: ""; position: absolute; right: 9px; top: 50%; width: 6px; height: 6px;
  margin-top: -4px; pointer-events: none;
  border-right: 2px solid var(--c-text-3); border-bottom: 2px solid var(--c-text-3);
  transform: rotate(45deg);
}

/* Slider companion */
.field__slider { width: 100%; margin-top: var(--s-2); accent-color: var(--c-accent); }

.field__help {
  font-size: var(--fs-2xs); line-height: 1.5; color: var(--c-text-3); margin-top: var(--s-2);
}
.field__help[hidden] { display: none; }
.field__error {
  display: flex; align-items: flex-start; gap: 5px;
  font-size: var(--fs-2xs); font-weight: 500; color: var(--c-neg); margin-top: var(--s-2);
}
.field__error[hidden] { display: none; }
.field.is-invalid .control__box { border-color: var(--c-neg); background: var(--c-neg-soft); }

/* Radio / checkbox */
.choices { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.choice {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 7px var(--s-3); border: 1px solid var(--c-border-strong);
  border-radius: var(--r-md); background: var(--c-surface);
  font-size: var(--fs-sm); font-weight: 500; cursor: pointer;
}
.choice:hover { border-color: var(--c-accent-line); background: var(--c-accent-soft); }
.choice input { accent-color: var(--c-accent); margin: 0; }
.choice:has(input:checked) { border-color: var(--c-accent); background: var(--c-accent-soft); color: var(--c-accent); }

.switch { display: flex; align-items: flex-start; gap: var(--s-3); cursor: pointer; }
.switch input { margin-top: 3px; accent-color: var(--c-accent); width: 16px; height: 16px; flex: none; }
.switch__text { font-size: var(--fs-sm); font-weight: 500; }
.switch__text small { display: block; font-size: var(--fs-2xs); font-weight: 400; color: var(--c-text-3); }

/* Advanced group */
.fieldgroup { grid-column: span 6; border: 0; padding: 0; margin: 0; min-width: 0; }
.fieldgroup > legend {
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--c-text-3); padding: 0 0 var(--s-2); width: 100%;
  border-bottom: 1px solid var(--c-border); margin-bottom: var(--s-3);
}
details.fieldgroup > summary {
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--c-text-2); cursor: pointer; padding: var(--s-2) 0;
  border-bottom: 1px solid var(--c-border); margin-bottom: var(--s-3);
  list-style: none; display: flex; align-items: center; gap: var(--s-2);
}
details.fieldgroup > summary::-webkit-details-marker { display: none; }
details.fieldgroup > summary::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform .15s;
}
details.fieldgroup[open] > summary::before { transform: rotate(45deg); }

.calc__actions { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-5); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  padding: 9px var(--s-4); border-radius: var(--r-md); border: 1px solid transparent;
  font-size: var(--fs-sm); font-weight: 600; text-decoration: none; white-space: nowrap;
  transition: background-color .12s, border-color .12s, color .12s;
}
.btn svg { width: 15px; height: 15px; flex: none; }
.btn--primary { background: var(--c-accent); color: var(--c-text-inv); }
.btn--primary:hover { background: var(--c-accent-hover); color: var(--c-text-inv); }
.btn--ghost { background: var(--c-surface); border-color: var(--c-border-strong); color: var(--c-text-2); }
.btn--ghost:hover { background: var(--c-surface-2); color: var(--c-text); border-color: var(--c-text-3); }
.btn--sm { padding: 6px var(--s-3); font-size: var(--fs-xs); }
.btn--link { background: none; border: 0; color: var(--c-accent); padding: 0; font-weight: 600; }
.btn--link:hover { text-decoration: underline; }

/* ---- Results ----
   .calc__results is a layout wrapper only. The two panels inside it — the
   headline answer and the supporting detail — are separate boxes so a phone can
   pin the answer alone (see the narrow-viewport block in section 16). */
.calc__results {
  background: var(--c-surface-3);
  display: flex; flex-direction: column;
}
.calc__answer, .calc__detail {
  background: var(--c-surface-3);
  display: flex; flex-direction: column; gap: var(--s-4);
  padding: var(--s-5);
}
/* Stacked in one column they must read as a single panel, not two. */
.calc__answer { padding-block-end: 0; }
.calc__detail { padding-block-start: var(--s-4); }
.calc__detail:empty { display: none; }
@media (min-width: 860px) {
  .calc__results { position: sticky; top: calc(var(--header-h) + var(--s-3)); align-self: start; }
}

.result-hero {
  padding: var(--s-4); border-radius: var(--r-lg);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-inline-start: 3px solid var(--c-accent);
}
.result-hero__label {
  font-size: var(--fs-2xs); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--c-text-3); margin-bottom: var(--s-1);
}
.result-hero__value {
  font-family: var(--ff-mono);
  font-size: clamp(1.875rem, 1.3rem + 2.4vw, var(--fs-4xl));
  font-weight: 700; line-height: 1.05; letter-spacing: -0.028em;
  font-variant-numeric: tabular-nums; color: var(--c-text);
  overflow-wrap: break-word;
}
.result-hero__value .unit { font-size: 0.46em; font-weight: 600; color: var(--c-text-3); letter-spacing: 0; }
.result-hero__value .unit--pre { margin-inline-end: 0.08em; }
.result-hero__value .unit--post { margin-inline-start: 0.14em; }
.result-hero__note { font-size: var(--fs-2xs); color: var(--c-text-3); margin-top: var(--s-2); line-height: 1.5; }
.result-hero.is-good { border-inline-start-color: var(--c-pos); }
.result-hero.is-good .result-hero__value { color: var(--c-pos); }
.result-hero.is-warn { border-inline-start-color: var(--c-signal); }
.result-hero.is-warn .result-hero__value { color: var(--c-signal); }
.result-hero.is-bad { border-inline-start-color: var(--c-neg); }
.result-hero.is-bad .result-hero__value { color: var(--c-neg); }

.result-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(132px, 1fr)); gap: var(--s-2); }
/* An odd final tile spans the row rather than leaving a dangling half-width cell. */
.result-grid > .result:last-child:nth-child(odd) { grid-column: 1 / -1; }
.result {
  padding: var(--s-3); border-radius: var(--r-md);
  background: var(--c-surface); border: 1px solid var(--c-border);
  min-width: 0;
}
.result__label {
  font-size: var(--fs-3xs); font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--c-text-3);
  margin-bottom: 3px; line-height: 1.35;
}
.result__value {
  font-family: var(--ff-mono); font-size: var(--fs-lg); font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
  color: var(--c-text); overflow-wrap: break-word; line-height: 1.25;
}
.result__value .unit { font-size: 0.62em; font-weight: 600; color: var(--c-text-3); }
.result__note { font-size: var(--fs-3xs); color: var(--c-text-3); margin-top: 3px; line-height: 1.4; }
.result.is-good .result__value { color: var(--c-pos); }
.result.is-warn .result__value { color: var(--c-signal); }
.result.is-bad  .result__value { color: var(--c-neg); }

/* Alerts inside results */
.alert {
  display: flex; gap: var(--s-3); padding: var(--s-3);
  border-radius: var(--r-md); font-size: var(--fs-xs); line-height: 1.55;
  border: 1px solid var(--c-signal-line); background: var(--c-signal-soft); color: var(--c-signal);
}
.alert svg { width: 15px; height: 15px; flex: none; margin-top: 2px; }
.alert--error { border-color: var(--c-neg-line); background: var(--c-neg-soft); color: var(--c-neg); }
.alert--info { border-color: var(--c-accent-line); background: var(--c-accent-soft); color: var(--c-accent); }
.alert--ok { border-color: var(--c-pos-line); background: var(--c-pos-soft); color: var(--c-pos); }
.alert b { font-weight: 700; }

/* Show-the-work */
.steps { border-top: 1px solid var(--c-border); padding-top: var(--s-3); }
.steps > summary {
  font-size: var(--fs-xs); font-weight: 600; color: var(--c-accent);
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: var(--s-2);
}
.steps > summary::-webkit-details-marker { display: none; }
.steps > summary::before {
  content: ""; width: 6px; height: 6px; flex: none;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(-45deg); transition: transform .15s;
}
.steps[open] > summary::before { transform: rotate(45deg); }
.steps__list { list-style: none; padding: 0; margin-top: var(--s-3); display: grid; gap: 1px; }
.steps__item {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s-2) var(--s-3);
  align-items: baseline; padding: var(--s-2) var(--s-3);
  background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--r-sm);
}
.steps__label { font-size: var(--fs-2xs); font-weight: 600; color: var(--c-text-2); }
.steps__expr {
  grid-column: 1 / -1; font-family: var(--ff-mono); font-size: var(--fs-3xs);
  color: var(--c-text-3); overflow-x: auto;
}
.steps__value {
  font-family: var(--ff-mono); font-size: var(--fs-sm); font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--c-accent); white-space: nowrap;
}

/* Chart + generated table */
.calc__viz { border-top: 1px solid var(--c-border); padding: var(--s-5); }
.calc__viz[hidden] { display: none; }
.viz-title { font-size: var(--fs-sm); font-weight: 600; margin-bottom: var(--s-3); }
.chart { width: 100%; overflow-x: auto; }
/* No min-width: the SVG carries a viewBox, so it scales to the container. A
   320px floor was forcing every phone to scroll the chart sideways. */
.chart svg { width: 100%; height: auto; min-width: 0; }
.chart__grid line { stroke: var(--c-border); stroke-width: 1; }
.chart__axis line, .chart__axis path { stroke: var(--c-border-strong); stroke-width: 1; fill: none; }
.chart__axis text { fill: var(--c-text-3); font-size: 10px; font-family: var(--ff-mono); }
.chart__label { fill: var(--c-text-2); font-size: 11px; font-weight: 600; }
.chart__s0 { stroke: var(--c-accent); fill: var(--c-accent); }
.chart__s1 { stroke: var(--c-signal); fill: var(--c-signal); }
.chart__s2 { stroke: var(--c-pos); fill: var(--c-pos); }
.chart__s3 { stroke: var(--c-chart-4); fill: var(--c-chart-4); }
.chart__s4 { stroke: var(--c-neg); fill: var(--c-neg); }
.chart__line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.chart__area { stroke: none; opacity: .14; }
.chart__legend { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); margin-top: var(--s-3); }
.chart__legend span { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-2xs); color: var(--c-text-2); }
.chart__swatch { width: 11px; height: 11px; border-radius: 2px; flex: none; }

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.calc__viz .table-scroll { max-height: min(70vh, 620px); overflow: auto; }
.table-scroll + .table-scroll { margin-top: var(--s-4); }

.dtable { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); min-width: 480px; }
.dtable caption {
  caption-side: top; text-align: start; font-size: var(--fs-2xs);
  color: var(--c-text-3); padding-bottom: var(--s-2);
}
.dtable th, .dtable td { padding: 7px var(--s-3); border-bottom: 1px solid var(--c-border); text-align: start; }
.dtable thead th {
  position: sticky; top: 0; z-index: 2; background: var(--c-surface-3);
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--c-text-2); border-bottom: 2px solid var(--c-rule); white-space: nowrap;
}
.dtable tbody tr:nth-child(even) { background: var(--c-surface-2); }
.dtable tbody tr:hover { background: var(--c-accent-soft); }
.dtable td.num, .dtable th.num {
  text-align: end; font-family: var(--ff-mono); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.dtable tfoot td { font-weight: 700; background: var(--c-surface-3); border-top: 2px solid var(--c-rule); }
.table-note { font-size: var(--fs-2xs); color: var(--c-text-3); margin-top: var(--s-2); }

/* --------------------------------------------------------------------------
   8. Formula block
   -------------------------------------------------------------------------- */
.formula {
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-lg); overflow: hidden;
}
.formula__math {
  padding: var(--s-5) var(--s-4); text-align: center; overflow-x: auto;
  background:
    linear-gradient(var(--c-surface-2) 1px, transparent 1px) 0 0 / 100% 22px,
    var(--c-surface);
  border-bottom: 1px solid var(--c-border);
}
.formula__math math { font-size: 1.28rem; color: var(--c-text); }
.formula__math .fallback {
  font-family: var(--ff-mono); font-size: var(--fs-md); font-weight: 600; color: var(--c-text);
}
.formula__math + .formula__math { border-top: 0; }
.formula__vars { list-style: none; padding: var(--s-4); margin: 0; display: grid; gap: var(--s-2); }
@media (min-width: 640px) { .formula__vars { grid-template-columns: 1fr 1fr; gap: var(--s-2) var(--s-5); } }
.formula__vars li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-3); align-items: baseline; font-size: var(--fs-xs); }
.formula__vars dfn, .formula__vars .sym {
  font-family: var(--ff-mono); font-style: normal; font-weight: 700;
  color: var(--c-accent); min-width: 2.4em;
}
.formula__vars .desc { color: var(--c-text-2); }
.formula__vars .u { color: var(--c-text-3); font-size: var(--fs-3xs); }
.formula__note {
  padding: var(--s-3) var(--s-4); border-top: 1px solid var(--c-border);
  background: var(--c-surface-2); font-size: var(--fs-2xs); color: var(--c-text-3);
}

/* --------------------------------------------------------------------------
   9. Article prose
   -------------------------------------------------------------------------- */
/* Running prose keeps a readable measure; block figures use the full column so a
   1440px screen is not left with a third of the main track empty. */
.prose { max-width: none; }
.prose > :where(p, ul, ol, dl, blockquote, h2, h3, h4, h5, figcaption) { max-width: var(--measure); }
.prose > * + * { margin-top: var(--s-4); }
.prose h2 {
  font-size: clamp(1.4rem, 1.15rem + 1vw, var(--fs-2xl));
  margin-top: var(--s-8); padding-top: var(--s-2);
  scroll-margin-top: calc(var(--header-h) + var(--s-4));
}
.prose h2:first-child { margin-top: 0; }
.prose h3 {
  font-size: var(--fs-xl); margin-top: var(--s-6);
  scroll-margin-top: calc(var(--header-h) + var(--s-4));
}
.prose h4 {
  font-size: 1.0625rem; font-weight: 700; letter-spacing: -0.008em;
  margin-top: var(--s-5); padding-bottom: var(--s-1);
  border-bottom: 1px solid var(--c-border);
}
.prose h5 { font-size: var(--fs-sm); font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--c-text-2); margin-top: var(--s-4); }
.prose p { line-height: var(--lh-body); }
.prose > ul, .prose > ol { padding-inline-start: 1.4em; }
.prose li + li { margin-top: var(--s-2); }
.prose li::marker { color: var(--c-text-3); }
.prose ol > li::marker { font-family: var(--ff-mono); font-weight: 600; color: var(--c-accent); }
.prose strong { font-weight: 600; color: var(--c-text); }
.prose a { font-weight: 500; }
.prose abbr[title] { text-decoration: underline dotted; cursor: help; }
.prose blockquote {
  border-inline-start: 3px solid var(--c-accent-line);
  padding: var(--s-1) 0 var(--s-1) var(--s-4);
  color: var(--c-text-2); font-style: italic;
}
.prose figure { margin: 0; }
.prose figcaption { font-size: var(--fs-2xs); color: var(--c-text-3); margin-top: var(--s-2); }
.prose dl { display: grid; gap: var(--s-3); }
.prose dt { font-weight: 600; color: var(--c-text); }
.prose dd { margin: 0; color: var(--c-text-2); padding-inline-start: 0; }

.prose table {
  width: 100%; border-collapse: collapse; font-size: var(--fs-xs);
  border: 1px solid var(--c-border); background: var(--c-surface);
}
.prose table caption {
  caption-side: bottom; text-align: start; font-size: var(--fs-2xs);
  color: var(--c-text-3); padding-top: var(--s-2);
}
.prose th, .prose td { padding: 8px var(--s-3); border: 1px solid var(--c-border); text-align: start; vertical-align: top; }
.prose thead th {
  background: var(--c-surface-3); font-size: var(--fs-3xs); font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; color: var(--c-text-2);
}
.prose tbody tr:nth-child(even) { background: var(--c-surface-2); }

/* Numbered / definition / step lists as blocks */
.doc-list { list-style: none; padding: 0; display: grid; gap: var(--s-3); counter-reset: dl; }
.doc-list li { position: relative; padding-inline-start: 2.1rem; }
.doc-list--numbered li::before {
  counter-increment: dl; content: counter(dl);
  position: absolute; left: 0; top: 1px; width: 1.5rem; height: 1.5rem;
  display: grid; place-items: center; border-radius: 50%;
  background: var(--c-accent-soft); color: var(--c-accent);
  font-family: var(--ff-mono); font-size: var(--fs-2xs); font-weight: 700;
  border: 1px solid var(--c-accent-line);
}
.doc-list--bulleted li::before {
  content: ""; position: absolute; left: 8px; top: 0.62em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--c-accent);
}
.doc-list--checks li::before {
  content: ""; position: absolute; left: 3px; top: 0.36em;
  width: 12px; height: 7px; border-inline-start: 2.5px solid var(--c-pos);
  border-block-end: 2.5px solid var(--c-pos); transform: rotate(-45deg);
}

.steplist { list-style: none; padding: 0; display: grid; gap: var(--s-4); counter-reset: sl; }
.steplist > li {
  position: relative; padding-inline-start: 2.75rem;
  padding-bottom: var(--s-4); border-bottom: 1px solid var(--c-border);
}
.steplist > li:last-child { border-bottom: 0; padding-bottom: 0; }
.steplist > li::before {
  counter-increment: sl; content: "Step " counter(sl);
  position: absolute; left: 0; top: 0; width: 2rem;
  font-family: var(--ff-mono); font-size: var(--fs-3xs); font-weight: 700;
  color: var(--c-accent); text-transform: uppercase; letter-spacing: .04em;
  writing-mode: horizontal-tb; line-height: 1.3;
}
.steplist__title { font-size: var(--fs-md); font-weight: 600; margin-bottom: var(--s-2); }

/* Callouts */
.callout {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s-3);
  padding: var(--s-4); border-radius: var(--r-lg);
  border: 1px solid var(--c-accent-line); background: var(--c-accent-soft);
  font-size: var(--fs-sm); line-height: 1.6;
}
.callout__icon { width: 18px; height: 18px; color: var(--c-accent); margin-top: 2px; }
.callout__title { font-weight: 700; color: var(--c-text); margin-bottom: var(--s-1); font-size: var(--fs-sm); }
.callout > div > * + * { margin-top: var(--s-2); }
.callout--warning { border-color: var(--c-signal-line); background: var(--c-signal-soft); }
.callout--warning .callout__icon { color: var(--c-signal); }
.callout--tip { border-color: var(--c-pos-line); background: var(--c-pos-soft); }
.callout--tip .callout__icon { color: var(--c-pos); }
.callout--standard { border-color: var(--c-border-strong); background: var(--c-surface-2); }
.callout--standard .callout__icon { color: var(--c-text-2); }

/* Worked example */
.example {
  border: 1px solid var(--c-border); border-radius: var(--r-lg);
  background: var(--c-surface); overflow: hidden;
}
.example__head {
  display: flex; align-items: center; gap: var(--s-2);
  padding: var(--s-3) var(--s-4); background: var(--c-surface-2);
  border-bottom: 1px solid var(--c-border);
}
.example__head svg { width: 15px; height: 15px; color: var(--c-accent); flex: none; }
.example__head h3, .example__head h2 {
  font-size: var(--fs-sm); font-weight: 700; margin: 0; letter-spacing: 0;
}
.example__body { padding: var(--s-4); }
.example__body > * + * { margin-top: var(--s-3); }
.example__body ol { padding-inline-start: 1.4em; }
.example__body ol > li::marker { font-family: var(--ff-mono); font-weight: 600; color: var(--c-accent); }

/* FAQ */
.faq { display: grid; gap: var(--s-2); }
.faq__item {
  border: 1px solid var(--c-border); border-radius: var(--r-lg);
  background: var(--c-surface); overflow: hidden;
}
.faq__item > summary {
  display: flex; align-items: flex-start; gap: var(--s-3);
  padding: var(--s-4); font-size: var(--fs-md); font-weight: 600;
  cursor: pointer; list-style: none;
}
.faq__item > summary::-webkit-details-marker { display: none; }
.faq__item > summary::after {
  content: ""; flex: none; width: 8px; height: 8px; margin: 6px 0 0 auto;
  border-right: 2px solid var(--c-text-3); border-bottom: 2px solid var(--c-text-3);
  transform: rotate(45deg); transition: transform .15s;
}
.faq__item[open] > summary::after { transform: rotate(-135deg); margin-top: 9px; }
.faq__item[open] > summary { border-bottom: 1px solid var(--c-border); background: var(--c-surface-2); }
.faq__item > summary:hover { color: var(--c-accent); }
.faq__body { padding: var(--s-4); font-size: var(--fs-sm); line-height: 1.65; color: var(--c-text-2); }
.faq__body > * + * { margin-top: var(--s-3); }

/* --------------------------------------------------------------------------
   10. TOC & rail widgets
   -------------------------------------------------------------------------- */
.toc { font-size: var(--fs-xs); }
.toc ol { list-style: none; padding: 0; display: grid; gap: 1px; }
.toc a {
  display: block; padding: 5px var(--s-3); color: var(--c-text-2);
  text-decoration: none; border-inline-start: 2px solid var(--c-border);
  line-height: 1.45;
}
.toc a:hover { color: var(--c-accent); background: var(--c-accent-soft); border-inline-start-color: var(--c-accent-line); }
.toc a.is-active { color: var(--c-accent); font-weight: 600; border-inline-start-color: var(--c-accent); background: var(--c-accent-soft); }
.toc .lvl-3 a { padding-inline-start: var(--s-5); font-size: var(--fs-2xs); }

.linklist { list-style: none; padding: 0; display: grid; gap: 1px; font-size: var(--fs-xs); }
.linklist a {
  display: flex; align-items: baseline; gap: var(--s-2);
  padding: 7px var(--s-3); color: var(--c-text-2); text-decoration: none; border-radius: var(--r-sm);
}
.linklist a:hover { background: var(--c-accent-soft); color: var(--c-accent); }
.linklist a::before { content: "→"; color: var(--c-text-3); flex: none; font-size: 0.9em; }
.linklist a:hover::before { color: var(--c-accent); }

/* --------------------------------------------------------------------------
   11. Directory / hub grids
   -------------------------------------------------------------------------- */
.card-grid { display: grid; gap: var(--s-3); grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }
.card-grid--wide { grid-template-columns: repeat(auto-fill, minmax(min(100%, 340px), 1fr)); }

.card {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-4); background: var(--c-surface);
  border: 1px solid var(--c-border); border-radius: var(--r-lg);
  text-decoration: none; color: inherit;
  transition: border-color .12s, box-shadow .12s, transform .12s;
}
a.card:hover {
  border-color: var(--c-accent-line); box-shadow: var(--sh-2);
  transform: translateY(-1px); color: inherit;
}
.card__icon { width: 26px; height: 26px; color: var(--c-accent); }
.card__title { font-size: var(--fs-md); font-weight: 600; line-height: 1.3; }
a.card:hover .card__title { color: var(--c-accent); }
.card__desc { font-size: var(--fs-xs); color: var(--c-text-2); line-height: 1.55; flex: 1 1 auto; }
.card__meta {
  font-size: var(--fs-3xs); font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--c-text-3); display: flex; align-items: center; gap: var(--s-2);
}
.card__count {
  font-family: var(--ff-mono); background: var(--c-surface-3); color: var(--c-text-2);
  padding: 1px 6px; border-radius: var(--r-sm); font-size: var(--fs-3xs); font-weight: 700;
}

/* Dense calculator index list */
.calc-list { list-style: none; padding: 0; display: grid; gap: 0; }
.calc-list li { border-bottom: 1px solid var(--c-border); }
.calc-list li:first-child { border-top: 1px solid var(--c-border); }
/* The tag column carries the calculator's `standard` field, which is prose, not a
   chip — "Amortised loan comparison; Regulation Z closing-cost disclosure" is 63
   characters. It was `white-space: nowrap` in an `auto` track, so on a phone the
   tag claimed 434px of a 466px row and the minmax(0,1fr) name track collapsed to
   its 0 floor: measured 21px wide by 396px tall on /personal-finance/, and 0px —
   the title invisible — on the refinance row. It also pushed the document to
   613px inside a 375px viewport on /unit-conversion/, which body{overflow-x:hidden}
   then clipped with no scrollbar, so the text was unreachable rather than merely
   ugly. Stack single-column by default and let the tag wrap; give the name a
   guaranteed 70% only once there is room for two tracks. */
.calc-list a {
  display: grid; grid-template-columns: minmax(0, 1fr); align-items: baseline;
  gap: var(--s-1) var(--s-4); padding: var(--s-3) var(--s-2);
  text-decoration: none; color: inherit;
}
.calc-list a:hover { background: var(--c-accent-soft); }
.calc-list__name { grid-column: 1; font-size: var(--fs-sm); font-weight: 600; min-width: 0; overflow-wrap: break-word; }
.calc-list a:hover .calc-list__name { color: var(--c-accent); }
.calc-list__desc { grid-column: 1; font-size: var(--fs-2xs); color: var(--c-text-3); line-height: 1.5; min-width: 0; overflow-wrap: break-word; }
.calc-list__tag {
  grid-column: 1; min-width: 0;
  font-size: var(--fs-3xs); font-family: var(--ff-mono); color: var(--c-text-3);
  text-transform: uppercase; letter-spacing: .04em;
  overflow-wrap: break-word; line-height: 1.45;
}
.calc-list__tag:empty { display: none; }
@media (min-width: 860px) {
  .calc-list a { grid-template-columns: minmax(0, 1fr) minmax(0, 30%); gap: var(--s-2) var(--s-4); }
  .calc-list__tag { grid-column: 2; grid-row: 1 / span 2; text-align: end; }
}

/* Subject groups on the A-Z letter pages */
.letter-group + .letter-group { margin-top: var(--s-7); }
.letter-group__head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2) var(--s-3);
  font-size: var(--fs-md); padding-bottom: var(--s-2); margin-bottom: var(--s-3);
  border-bottom: 2px solid var(--c-rule);
}
.letter-group__head a { text-decoration: none; color: inherit; }
.letter-group__head a:hover { color: var(--c-accent); }
.letter-group__count {
  font-family: var(--ff-mono); background: var(--c-surface-3); color: var(--c-text-2);
  padding: 1px 6px; border-radius: var(--r-sm); font-size: var(--fs-3xs); font-weight: 700;
  white-space: nowrap;
}

.section-head {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2) var(--s-4);
  padding-bottom: var(--s-3); margin-bottom: var(--s-4);
  border-bottom: 2px solid var(--c-rule);
}
.section-head h2 { font-size: var(--fs-xl); }
.section-head p { font-size: var(--fs-sm); color: var(--c-text-2); flex: 1 1 260px; }
.section-head a { margin-inline-start: auto; font-size: var(--fs-xs); font-weight: 600; white-space: nowrap; }

.pill-row { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.pill {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 5px var(--s-3); border-radius: 100px;
  border: 1px solid var(--c-border-strong); background: var(--c-surface);
  font-size: var(--fs-xs); font-weight: 500; color: var(--c-text-2); text-decoration: none;
}
.pill:hover { border-color: var(--c-accent); background: var(--c-accent-soft); color: var(--c-accent); }
/* Which subject a cross-domain pill belongs to, so "Ventilation" is not ambiguous */
.pill__ctx {
  font-size: var(--fs-3xs); color: var(--c-text-3); text-transform: uppercase;
  letter-spacing: .04em; padding-inline-start: var(--s-2);
  border-inline-start: 1px solid var(--c-border); margin-inline-start: var(--s-1);
}
.pill:hover .pill__ctx { color: inherit; }
.pill[aria-current="true"] { background: var(--c-accent); border-color: var(--c-accent); color: var(--c-text-inv); }

/* Alphabet index */
.alpha-nav { display: flex; flex-wrap: wrap; gap: 4px; }
.alpha-nav a {
  display: grid; place-items: center; width: 36px; height: 36px;
  font-family: var(--ff-mono); font-size: var(--fs-xs); font-weight: 700;
  border: 1px solid var(--c-border); border-radius: var(--r-sm);
  background: var(--c-surface); color: var(--c-text-2); text-decoration: none;
}
.alpha-nav a:hover { border-color: var(--c-accent); background: var(--c-accent-soft); color: var(--c-accent); }

/* --------------------------------------------------------------------------
   12. Hero (home)
   -------------------------------------------------------------------------- */
.hero { padding-block: var(--s-7) var(--s-6); text-align: center; }
.hero h1 {
  font-size: clamp(2rem, 1.4rem + 3vw, 3.25rem);
  letter-spacing: -0.03em; margin-bottom: var(--s-4);
}
.hero h1 .accent { color: var(--c-accent); }
.hero__sub {
  font-size: clamp(var(--fs-md), 0.95rem + .4vw, var(--fs-lg));
  color: var(--c-text-2); max-width: 66ch; margin-inline: auto; line-height: 1.6;
}
.hero__search { max-width: 620px; margin: var(--s-6) auto 0; }
.hero__search .search__input { height: 48px; font-size: var(--fs-md); padding-left: 42px; border-radius: var(--r-lg); box-shadow: var(--sh-2); }
.hero__search .search__icon { left: 15px; width: 17px; height: 17px; }
.hero__stats {
  display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s-4) var(--s-7);
  margin-top: var(--s-6);
}
.hero__stat { text-align: center; }
.hero__stat b {
  display: block; font-family: var(--ff-mono); font-size: var(--fs-2xl);
  font-weight: 700; color: var(--c-text); letter-spacing: -0.02em;
}
.hero__stat span {
  font-size: var(--fs-3xs); font-weight: 600; letter-spacing: .08em;
  text-transform: uppercase; color: var(--c-text-3);
}
/* Four tiles on one row measured 72–91px wide at 320–390px, which broke the
   uppercase labels across three lines each. Two per row instead. */
@media (max-width: 559px) {
  .hero__stats { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4) var(--s-3); }
  .hero__stat span { letter-spacing: .04em; }
}

/* --------------------------------------------------------------------------
   12b. What every page carries (home)
        The site's actual differentiator, stated where a visitor — or a Google
        reviewer — sees it without scrolling past the fold on a laptop. Every
        claim in it is measured across all 1,292 files; see the comment beside
        `promises` in generate.py before changing any wording.
   -------------------------------------------------------------------------- */
.promises {
  margin-block: var(--s-6) var(--s-7); padding: var(--s-6);
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
}
.promises h2 {
  font-size: var(--fs-lg); letter-spacing: -0.01em;
  margin-bottom: var(--s-5); text-align: center;
}
.promise-grid {
  display: grid; gap: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
}
.promise { display: flex; flex-direction: column; gap: 5px; }
/* The accent rule reads as a checklist mark without needing an icon font or an
   inline SVG per item — four more DOM nodes on the most-requested page. */
.promise b {
  font-size: var(--fs-sm); color: var(--c-text);
  padding-left: var(--s-3); border-left: 3px solid var(--c-accent);
}
.promise span {
  font-size: var(--fs-xs); line-height: 1.6; color: var(--c-text-2);
  padding-left: var(--s-3);
}
.promises__foot {
  margin: var(--s-5) auto 0; max-width: 74ch; text-align: center;
  font-size: var(--fs-sm); line-height: 1.65; color: var(--c-text-2);
}

/* Postal address block on the contact page. */
.postal {
  margin: var(--s-4) 0; padding: var(--s-4) var(--s-5);
  background: var(--c-surface-2); border-left: 3px solid var(--c-border-strong);
  border-radius: var(--r-md); line-height: 1.7;
}

/* --------------------------------------------------------------------------
   13. Ad slots and Auto ads
       Advertising is a BUILD-time switch: ADSENSE_CLIENT in build/generate.py.
       With no publisher ID the generator emits no .adslot markup at all, so
       nothing here applies and the page carries no dead space.
   -------------------------------------------------------------------------- */
/* READ THIS BEFORE "FIXING" THE RESERVED HEIGHTS BELOW.
   When a responsive unit fills, AdSense walks UP from its <ins> and writes
       height: auto !important; min-height: 0px !important
   inline onto the ancestor containers, so it can measure available width.
   Measured on a real fill, two levels up, through an intermediate wrapper.

   Consequences, both learned the hard way:
     1. `height` does NOT reserve space. It was `height: 114px` here; the leader
        rendered 280px on desktop and 375px on a phone — a 261px shift on the
        element directly under the calculator, a Core Web Vitals failure on the
        page the site most wants to rank.
     2. `min-height` does not survive either, and NEITHER DOES A WRAPPER. That
        was tried: AdSense climbed past it and neutralised the outer div too.
        An inline `!important` beats an author `!important`, so there is no CSS
        defence at all. Do not add another wrapper — it has been measured.

   What actually works is the only thing left: make the reserved number EQUAL
   the height the unit really fills at. The constraint applies during the window
   before AdSense runs, which is exactly the window CLS is measured in; once it
   fills, the content itself holds the same height and nothing moves.
   So these values are load-bearing and must be re-measured, not guessed.

   overflow is `clip`, not `hidden`: `hidden` makes this a scroll container, and
   per section 9 that silently kills `position: sticky` on any descendant — the
   same trap that broke the results panel. Ads never need to scroll. */
.adslot {
  display: block; margin-block: var(--s-6); overflow: hidden; overflow: clip;
  position: relative; text-align: center;
  background: var(--c-surface-2); border: 1px solid var(--c-border);
  border-radius: var(--r-md); padding-top: 14px;
}
/* These are border-box totals (see the global box-sizing reset), i.e. the ad's
   own height + 14px label strip + 2px border, so the reserved box equals the
   filled box exactly and nothing moves:
       leader  mobile  100 + 16 = 116     desktop  90 + 16 = 106
       inline          285 + 16 = 301
       rail            600 + 16 = 616
   Re-measure against the LIVE account before trusting them to the pixel: these
   came from a test publisher ID, which exercises AdSense's slot-sizing logic
   but not its real fill. */
.adslot--leader { min-height: 116px; }
.adslot--inline { min-height: 301px; }
.adslot--rail   { min-height: 616px; margin-block: 0; }

@media (min-width: 1080px) {
  .adslot--leader { min-height: 106px; }
}

/* Google requires ad units to be labelled only as "Advertisement" or
   "Sponsored links" — no other wording, and never anything that could read as
   an incentive to click. */
.adslot::before {
  content: "Advertisement"; position: absolute; inset-block-start: 3px; inset-inline: 0;
  font-size: 9px; letter-spacing: .1em; text-transform: uppercase; color: var(--c-text-3);
}
.adslot ins { display: block; }

/* ---- Auto ads: keep them out of the tool ---------------------------------
   Auto ads reads the DOM and inserts units wherever it finds room. That is
   exactly what we want down the 6,000px article — and exactly what must never
   happen INSIDE the calculator, where an injected banner would land between the
   input fields and the results panel and break the one thing the visitor came
   for. It would also add a second scroll container around .calc__answer, whose
   sticky behaviour is already fragile (see the overflow note in section 9).

   Two layers, because neither alone is sufficient:
     1. `google-auto-ads: ignore` — the declaration AdSense's own "Excluded
        areas" tool writes for a selected region. Harmless to every browser
        (unknown property, dropped at parse time).
     2. The stable hooks `#calculator`, `.no-autoads`, `.site-header`,
        `.searchbar` and `.site-footer`, so the selectors you pick in
        AdSense › Ads › Edit site › Excluded areas keep matching across
        rebuilds. That UI is the authoritative control; Google warns that an
        excluded area stops working if its selector changes, and these do not.

   Do NOT exclude .prose or .faq — the article body is where Auto ads earns its
   keep, and excluding it leaves only the three fixed slots on an 18,000px page. */
.no-autoads,
#calculator,
.site-header,
.searchbar,
.site-footer { google-auto-ads: ignore; }

/* Anchor ads dock to the bottom of the viewport. The calculator's mobile
   results panel sticks to the TOP, so the two never fight, but the footer needs
   room or the last line sits under the anchor unit. */
[data-auto-ads="on"] .site-footer { padding-bottom: calc(var(--s-5) + 68px); }

/* Consent UI is deliberately NOT styled here, and there is no .consent markup
   left in the build. Google requires a certified TCF v2.2 CMP for EEA/UK/CH
   traffic; the site uses Google's own "Privacy & messaging", which renders in
   its own shadow-DOM container and cannot — and must not — be restyled from
   this file. Restyling a certified CMP can invalidate its certification.
   The `.consent` rule in the print block below is kept as a defensive hide. */

/* --------------------------------------------------------------------------
   13b. Contact form
        Markup comes from contact_form_html() in build/generate.py and is
        repopulated server-side by contact/index.php. No address is published.
   -------------------------------------------------------------------------- */
.cform { margin-top: var(--s-5); }
.cform .field + .field, .cform .field-row + .field { margin-top: var(--s-4); }

.field { display: flex; flex-direction: column; gap: 6px; }
.field__label { font-size: var(--fs-sm); font-weight: 600; color: var(--c-text); }
.field__opt { font-weight: 400; color: var(--c-text-3); font-size: var(--fs-xs); }
.field__hint { font-size: var(--fs-xs); color: var(--c-text-2); line-height: 1.5; }

.field__input {
  width: 100%; padding: 9px var(--s-3);
  background: var(--c-surface); color: var(--c-text);
  border: 1px solid var(--c-border-strong); border-radius: var(--r-md);
  font: inherit; font-size: var(--fs-sm);
}
.field__input:focus-visible {
  outline: 2px solid var(--c-accent); outline-offset: 1px;
  border-color: var(--c-accent);
}
.field__input--area { resize: vertical; min-height: 180px; line-height: 1.6; }
/* Monospace and generous tracking: the answer is a code, not a word, and
   telling 'rn' from 'm' matters more here than matching the body font. */
.field__input--cap {
  max-width: 15ch; font-family: var(--ff-mono);
  letter-spacing: .18em; text-transform: uppercase; font-size: var(--fs-md);
}
.field__input[aria-invalid="true"] { border-color: #c0392b; background: #fdf3f2; }

.field-row { display: grid; gap: var(--s-4); grid-template-columns: 1fr 1fr; }
@media (max-width: 599px) { .field-row { grid-template-columns: 1fr; } }

/* The honeypot. Deliberately NOT display:none — a share of bots skip fields
   that are display:none or type=hidden, and filling one is the signal we want.
   Moved off-canvas instead, removed from the tab order in the markup, and
   aria-hidden so it is never announced. No human can reach it. */
.cform__trap {
  position: absolute !important; left: -9999px !important; top: auto !important;
  width: 1px !important; height: 1px !important; overflow: hidden !important;
}

.cform__captcha { margin-top: var(--s-5); }
.cform__cap-row { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; }
.cform__cap-img {
  display: block; width: 264px; height: 78px; max-width: 100%;
  border: 1px solid var(--c-border); border-radius: var(--r-md);
  background: #f6f8fa;   /* literal: the PNG's own background, both themes */
}
.cform__actions {
  display: flex; align-items: center; gap: var(--s-4); flex-wrap: wrap;
  margin-top: var(--s-6); padding-top: var(--s-5);
  border-top: 1px solid var(--c-border);
}
.cform__actions .field__hint { flex: 1 1 260px; }

/* Result banner injected by contact/index.php at <!--CF_STATUS-->. */
.formnote {
  margin: var(--s-5) 0; padding: var(--s-4) var(--s-4) var(--s-4) var(--s-5);
  border: 1px solid var(--c-border); border-left-width: 4px;
  border-radius: var(--r-md); background: var(--c-surface-2);
}
.formnote:focus { outline: none; }
.formnote strong { display: block; font-size: var(--fs-md); color: var(--c-text); }
.formnote p { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--c-text-2); }
.formnote ul { margin: var(--s-3) 0 0; padding-left: var(--s-5); font-size: var(--fs-sm); }
.formnote li + li { margin-top: 4px; }
.formnote--ok  { border-left-color: #1e7d4f; background: #eef8f2; }
.formnote--err { border-left-color: #c0392b; background: #fdf3f2; }

[data-theme="dark"] .formnote--ok  { background: #10241a; }
[data-theme="dark"] .formnote--err { background: #2a1614; }
[data-theme="dark"] .field__input[aria-invalid="true"] { background: #2a1614; }

/* --------------------------------------------------------------------------
   14. Footer
   -------------------------------------------------------------------------- */
.site-footer {
  margin-top: var(--s-8); border-top: 1px solid var(--c-border);
  background: var(--c-surface); padding-block: var(--s-7) var(--s-5);
}
.footer-grid {
  display: grid; gap: var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 180px), 1fr));
}
.footer-col h2 {
  font-size: var(--fs-3xs); font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--c-text-3); margin-bottom: var(--s-3);
}
.footer-col ul { list-style: none; padding: 0; display: grid; gap: var(--s-2); }
.footer-col a {
  display: inline-block; padding-block: 5px;
  font-size: var(--fs-xs); color: var(--c-text-2); text-decoration: none;
}
.footer-col a:hover { color: var(--c-accent); text-decoration: underline; }

/* 41 domain links stacked one per row made the footer 2,238px tall on a 390px
   viewport — 2.6 screens of scrolling below every page, which is also what
   buried About/Privacy/Terms deep enough that they read as missing. Two columns
   and tighter rows bring it to roughly a third of that. `display: grid` above
   would ignore `columns`, so the list switches to block flow here. */
@media (max-width: 719px) {
  .footer-col ul { display: block; columns: 2; column-gap: var(--s-4); }
  .footer-col li { break-inside: avoid; }
  .footer-col a { padding-block: 3px; line-height: 1.35; }
  .site-footer { padding-block: var(--s-6) var(--s-4); }
  .footer-grid { gap: var(--s-5); }
}
.footer-bottom {
  margin-top: var(--s-6); padding-top: var(--s-4); border-top: 1px solid var(--c-border);
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-5); align-items: center;
  font-size: var(--fs-2xs); color: var(--c-text-3);
}
.footer-bottom nav { display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-4); margin-inline-start: auto; }
.footer-bottom a { display: inline-block; padding-block: 5px; color: var(--c-text-3); text-decoration: none; }
.footer-bottom a:hover { color: var(--c-accent); text-decoration: underline; }
.disclaimer {
  margin-top: var(--s-4); padding: var(--s-3) var(--s-4);
  background: var(--c-surface-2); border: 1px solid var(--c-border); border-radius: var(--r-md);
  font-size: var(--fs-2xs); line-height: 1.6; color: var(--c-text-3);
}

/* The AI/authorship disclosure on the home page. Deliberately styled as a plain
   note rather than fine print — it is a statement the reader is entitled to see,
   not a disclaimer being got out of the way. */
.home-note {
  margin-top: var(--s-5); padding: var(--s-4);
  background: var(--c-surface-2); border: 1px solid var(--c-border);
  border-inline-start: 3px solid var(--c-accent-line); border-radius: var(--r-md);
  font-size: var(--fs-sm); line-height: 1.65; color: var(--c-text-2); max-width: none;
}
.home-note strong { color: var(--c-text); }

/* --------------------------------------------------------------------------
   15. Utilities
   -------------------------------------------------------------------------- */
.muted { color: var(--c-text-3); }
.small { font-size: var(--fs-2xs); }
.center { text-align: center; }
.nowrap { white-space: nowrap; }
.mt-0 { margin-top: 0 !important; }
.divider { border: 0; border-top: 1px solid var(--c-border); margin-block: var(--s-6); }
.rule-strong { border: 0; border-top: 2px solid var(--c-rule); margin-block: var(--s-6); }

.toast {
  position: fixed; inset-block-end: var(--s-5); inset-inline-start: 50%;
  transform: translateX(-50%) translateY(8px); z-index: 300;
  background: var(--c-text); color: var(--c-bg);
  padding: var(--s-2) var(--s-4); border-radius: 100px;
  font-size: var(--fs-xs); font-weight: 600; box-shadow: var(--sh-3);
  opacity: 0; pointer-events: none; transition: opacity .18s, transform .18s;
}
.toast.is-visible { opacity: 1; transform: translateX(-50%) translateY(0); }

.no-js-note {
  padding: var(--s-3) var(--s-4); margin-bottom: var(--s-4);
  background: var(--c-signal-soft); border: 1px solid var(--c-signal-line);
  border-radius: var(--r-md); font-size: var(--fs-xs); color: var(--c-signal);
}

/* --------------------------------------------------------------------------
   16. Responsive corrections
       Each rule here fixes a defect measured on a real device viewport, not a
       guess. Comments record what was measured so the reason survives.
   -------------------------------------------------------------------------- */

/* Below the two-column breakpoint the inputs column measured 1,450px tall, which
   put the answer 1,450px below the fold: a phone user filled the form and then
   had to scroll past all of it to find the number.

   Pinning the whole results panel was the first attempt and it silently did
   nothing. Measured on a 390x844 viewport: the panel is 799px tall — title 27,
   hero 136, secondary grid 352, warnings 147, steps 40 — against 787px of
   viewport below the 57px header. A sticky box taller than its own travel space
   never stays put; it scrolled off at every offset tested, so the answer still
   disappeared the moment the visitor reached the inputs.

   Only the 136px hero needs to be pinned. The wrapper collapses to
   display:contents so .calc__answer, .calc__inputs and .calc__detail all become
   flex items of .calc__grid — that makes .calc__grid the sticky containing
   block, which is what lets the answer ride over the inputs. Reading order
   becomes answer → inputs → detail, which is also the right mobile IA: the
   number first, the controls, then the supporting figures. */
@media (max-width: 859px) {
  .calc__grid { display: flex; flex-direction: column; }
  .calc__results { display: contents; }

  .calc__answer {
    order: -1;
    position: sticky; top: var(--header-h); z-index: 6;
    gap: var(--s-2); padding: var(--s-4);
    border-bottom: 1px solid var(--c-border-strong);
  }
  .calc__inputs { order: 0; padding: var(--s-4); }
  .calc__detail { order: 1; padding: var(--s-4); border-top: 1px solid var(--c-border); }

  .calc__detail .result-grid { grid-template-columns: repeat(auto-fit, minmax(108px, 1fr)); }
  .calc__answer .result-hero__value { font-size: 2rem; }
  /* The section title is redundant once the hero carries its own label, and the
     pinned bar is charged for every pixel it occupies. */
  .calc__answer .calc__section-title { display: none; }
}

/* At 320px (iPhone SE, folded Galaxy Fold) the header ran 19px past the
   viewport. The wordmark is intrinsically 826x114, so at its 23px mobile height
   it renders 167px wide, and 167 + the search field + two 40px controls did not
   fit in 288px of content box. Step the wordmark down and tighten the row gap;
   the search field keeps min-width:0 so it takes what is left. */
@media (max-width: 400px) {
  .site-header__bar { gap: var(--s-2); }
  .brand__logo { height: 19px; }
  .header-tools { gap: var(--s-1); }
}

@media (max-width: 719px) {
  /* iOS Safari zooms the viewport whenever a focused control is under 16px.
     The number inputs were already 16px; these three were not. */
  .search__input, .control select, .control__unit select { font-size: 16px; }
  .control__unit select { padding-inline: var(--s-2) 24px; letter-spacing: .02em; }

  /* Platform minimum touch target. */
  .icon-btn { width: 40px; height: 40px; }
  .btn { padding-block: 11px; }
  .choice { padding-block: 9px; }

  /* The header search was taking the whole row and crushing the icon buttons;
     its dropdown then inherited a 99px anchor width. Detach the dropdown from
     the field and let it span the viewport instead. */
  .search { flex: 1 1 120px; min-width: 0; }
  .search__results {
    position: fixed; inset-inline: var(--s-3); inset-block-start: calc(var(--header-h) + 6px);
    max-height: calc(100vh - var(--header-h) - var(--s-6));
  }
  .hero__search .search__results { position: absolute; inset-inline: 0; inset-block-start: calc(100% + 6px); }
}

/* Chart text is specified in SVG user units, so it shrinks with the viewBox.
   At 375px the 720-unit viewBox renders at 0.444x, which turned 10px ticks into
   4.4px. Scale the declared size up so the RENDERED size stays ~10px. */
@media (max-width: 640px) {
  .chart__axis text { font-size: 22px; }
  .chart__label { font-size: 24px; }
  .calc__viz { padding: var(--s-3); }
  .dtable { font-size: var(--fs-2xs); }
}

/* --------------------------------------------------------------------------
   17. Print — engineers print their calcs
   -------------------------------------------------------------------------- */
@media print {
  :root { --c-bg: #fff; --c-surface: #fff; --c-surface-2: #fff; --c-border: #bbb; }
  body { background: #fff; font-size: 10.5pt; color: #000; }
  .site-header, .site-footer, .rail, .adslot, .drawer, .search, .calc__actions,
  .skip-link, .toast, .nav-primary, .header-tools, .no-js-note,
  .consent, .alpha-nav { display: none !important; }
  .layout { display: block; padding: 0; }
  .calc { border: 1px solid #999; box-shadow: none; page-break-inside: avoid; }
  /* A Letter page is about 816 CSS px, so the max-width:859px rules are live
     while printing: without these the sheet would inherit the phone layout —
     .calc__results collapsed to display:contents, the answer pulled above the
     inputs by order:-1 and still marked sticky, and its "Results" heading
     hidden. Print wants plain block flow in document order (inputs, then the
     answer, then the supporting figures) with every panel visible. */
  .calc__grid { display: block; }
  .calc__results { display: block; }
  .calc__answer, .calc__detail {
    position: static; background: #fff; border: 0; padding: 0 0 8pt;
  }
  .calc__answer .calc__section-title { display: block; }
  .steps, .faq__item { border-color: #bbb; }
  .steps[open] .steps__list, .faq__item[open] .faq__body { display: block !important; }
  .prose h2, .prose h3 { page-break-after: avoid; }
  .prose table, .example, .callout, .formula { page-break-inside: avoid; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 8pt; color: #555; }
  .crumbs { font-size: 8pt; }
}
