/* ==========================================================================
   TheCalculatory — Component Library (v2)
   The closed set. A calculator is a DATA FILE and cannot introduce styling;
   anything new is added here, never inlined on a page.

   Modern CSS in use: container queries, :has(), scroll-driven view()
   animations, @property-animated gradients, color-mix(), OKLCH, clamp().
   Every one is progressively enhanced — the page is complete without them.
   ========================================================================== */

/* ==========================================================================
   Header
   ========================================================================== */
.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: color-mix(in oklab, var(--surface) 78%, transparent);
  backdrop-filter: blur(16px) saturate(180%);
  -webkit-backdrop-filter: blur(16px) saturate(180%);
  border-bottom: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
}
.site-header__inner {
  height: var(--header-height);
  display: flex; align-items: center; gap: var(--gutter-lg);
}
.brand {
  display: flex; align-items: center; gap: var(--space-md);
  color: var(--on-surface); font-weight: var(--weight-semibold);
  font-size: 1.0625rem;
  letter-spacing: var(--tracking-snug); white-space: nowrap;
}
.brand:hover { text-decoration: none; }
.brand__mark {
  width: 2.125rem; height: 2.125rem;
  display: grid; place-items: center;
  background: var(--grad-brand);
  color: var(--on-primary);
  border-radius: var(--radius);
  box-shadow: var(--glow-primary);
  font-family: var(--font-mono); font-size: 0.9375rem;
  font-weight: var(--weight-bold);
  transition: transform var(--duration) var(--ease-out);
}
.brand:hover .brand__mark { transform: translateY(-1px) rotate(-4deg); }

.site-nav { display: flex; gap: var(--space-xs); }
.site-nav a {
  color: var(--on-surface-variant);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius);
  transition: background var(--duration) var(--ease),
              color var(--duration) var(--ease);
}
.site-nav a:hover {
  color: var(--primary); background: var(--primary-subtle);
  text-decoration: none;
}
@media (max-width: 61.9375rem) { .site-nav { display: none; } }

/* ---------- Search ---------- */
.search {
  flex: 1; max-width: 26rem; margin-left: auto;
  position: relative; display: flex; align-items: center;
}
.search__input {
  width: 100%;
  padding: var(--space-md) var(--space-md) var(--space-md) var(--space-xl);
  background: var(--surface-recessed);
  border: 1px solid var(--border);
  border-radius: var(--radius-full);
  box-shadow: var(--elev-recessed);
  font-size: var(--text-body-md);
  color: var(--on-surface);
  transition: border-color var(--duration) var(--ease),
              box-shadow var(--duration) var(--ease),
              background var(--duration) var(--ease);
}
.search__input::placeholder { color: var(--on-surface-muted); }
.search__input:focus {
  outline: none; background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: var(--elev-recessed), 0 0 0 4px var(--focus-ring);
}
.search__icon {
  position: absolute; left: var(--gutter);
  color: var(--on-surface-muted); pointer-events: none;
  transition: color var(--duration) var(--ease);
}
.search:has(.search__input:focus) .search__icon { color: var(--primary); }
.search__hint {
  position: absolute; right: var(--space-md);
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  color: var(--on-surface-muted);
  background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  padding: 0.125rem var(--space-sm);
  box-shadow: var(--elev-1);
}
.search:has(.search__input:focus) .search__hint { opacity: 0; }

/* Large hero search */
.search--hero { max-width: 34rem; margin-inline: auto; }
.search--hero .search__input {
  padding: var(--gutter) var(--gutter) var(--gutter) var(--space-2xl);
  font-size: var(--text-body-lg);
  background: var(--surface);
  border-color: var(--border-strong);
  box-shadow: var(--elev-3);
}
.search--hero .search__icon { left: var(--gutter-lg); }

/* ==========================================================================
   Breadcrumbs
   ========================================================================== */
.breadcrumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-sm);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
  padding-block: var(--gutter);
}
.breadcrumb a { color: var(--on-surface-muted); }
.breadcrumb a:hover { color: var(--primary); }
.breadcrumb__sep { opacity: 0.4; }

/* ==========================================================================
   Badges, pills, tags
   ========================================================================== */
.badge {
  display: inline-flex; align-items: center; gap: var(--space-xs);
  font-family: var(--font-mono);
  font-size: var(--text-mono-sm); line-height: var(--lh-mono-sm);
  font-weight: var(--weight-medium); letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-full);
  background: var(--surface); color: var(--on-surface-variant);
  border: 1px solid var(--border);
  box-shadow: var(--elev-1);
}
.badge--primary {
  background: linear-gradient(180deg, var(--brand-50), var(--brand-100));
  color: var(--brand-700); border-color: var(--brand-200);
}
.badge--success {
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--success-subtle) 100%, transparent),
    color-mix(in oklab, var(--success-subtle) 70%, var(--success-border)));
  color: var(--success); border-color: var(--success-border);
}
.badge--warning {
  background: var(--warning-subtle);
  color: var(--warning-text); border-color: var(--warning-border);
}

.pill {
  display: inline-flex; align-items: center;
  padding: var(--space-sm) var(--gutter);
  border-radius: var(--radius-full);
  background: var(--grad-key); color: var(--on-surface-variant);
  border: 1px solid var(--border);
  box-shadow: var(--elev-key);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  transition: transform var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out),
              color var(--duration-fast) var(--ease);
}
.pill:hover {
  text-decoration: none; color: var(--on-surface);
  transform: translateY(-2px); box-shadow: var(--elev-key-hover);
}
.pill:active { transform: translateY(1px); box-shadow: var(--elev-pressed); }
.pill[aria-pressed="true"], .pill--active {
  background: var(--grad-key-primary); color: var(--on-primary);
  border-color: transparent; box-shadow: var(--glow-primary);
}

.tag {
  font-size: var(--text-body-sm);
  padding: var(--space-xs) var(--space-md);
  border-radius: var(--radius-full);
  background: var(--surface-recessed); color: var(--on-surface-variant);
  border: 1px solid var(--border-subtle);
}

/* ==========================================================================
   Cards / surfaces
   ========================================================================== */
.card {
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--elev-2);
  padding: var(--gutter-xl);
}
@media (max-width: 40rem) { .card { padding: var(--gutter-lg); } }

.card--flush { padding: 0; overflow: hidden; }
.card__header {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--gutter); margin-bottom: var(--gutter-lg); flex-wrap: wrap;
}
.card__title {
  font-size: var(--text-headline-md); line-height: var(--lh-headline-md);
  font-weight: var(--weight-semibold); letter-spacing: var(--tracking-snug);
}
.well {
  background: var(--grad-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-recessed);
  padding: var(--gutter);
}

/* ==========================================================================
   Buttons — tactile keycaps with a weighted bottom edge
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-sm);
  padding: var(--space-md) var(--space-lg);
  border-radius: var(--radius);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  border: 1px solid var(--border);
  background: var(--grad-key); color: var(--on-surface);
  box-shadow: var(--elev-key);
  transition: transform var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out),
              filter var(--duration-fast) var(--ease);
}
.btn:hover {
  text-decoration: none; transform: translateY(-2px);
  box-shadow: var(--elev-key-hover);
}
.btn:active { transform: translateY(1px); box-shadow: var(--elev-pressed); }

.btn--primary {
  background: var(--grad-key-primary); color: var(--on-primary);
  border-color: transparent; box-shadow: var(--glow-primary);
}
.btn--primary:hover { box-shadow: var(--glow-primary-hover); }
.btn--primary:active { box-shadow: var(--elev-pressed); }

.btn--ghost {
  background: transparent; border-color: var(--border);
  box-shadow: none; color: var(--on-surface-variant);
}
.btn--ghost:hover {
  background: var(--surface-recessed); transform: none;
  box-shadow: var(--elev-1); color: var(--on-surface);
}
.btn--sm { padding: var(--space-sm) var(--space-md); font-size: var(--text-body-sm); }
.btn--lg { padding: var(--gutter) var(--space-xl); font-size: var(--text-body-lg); }
.btn--block { width: 100%; }

/* ==========================================================================
   Form controls
   ========================================================================== */
.field { display: block; }
.field + .field { margin-top: var(--gutter-lg); }

.field__label {
  display: flex; align-items: center; gap: var(--space-sm);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  margin-bottom: var(--space-md);
}
.field__help {
  display: inline-grid; place-items: center;
  width: 1.125rem; height: 1.125rem; border-radius: var(--radius-full);
  background: var(--surface-recessed); border: 1px solid var(--border);
  color: var(--on-surface-muted); font-size: var(--text-mono-sm);
  cursor: help;
}
.field__hint { margin-top: var(--space-sm); font-size: var(--text-body-sm); color: var(--on-surface-muted); }
.field__error { margin-top: var(--space-sm); font-size: var(--text-body-sm); color: var(--danger); }

/* Recessed input well with a unit affix inside the border */
.input-group {
  display: flex; align-items: stretch;
  background: var(--surface-recessed);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--elev-recessed);
  overflow: hidden;
  transition: border-color var(--duration) var(--ease),
              box-shadow var(--duration) var(--ease),
              background var(--duration) var(--ease);
}
.input-group:focus-within {
  background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: var(--elev-recessed), 0 0 0 4px var(--focus-ring);
}
.input-group__affix {
  display: grid; place-items: center;
  padding-inline: var(--gutter);
  background: color-mix(in oklab, var(--surface) 70%, transparent);
  color: var(--on-surface-muted);
  font-family: var(--font-mono); font-size: var(--text-mono-md);
  font-weight: var(--weight-medium);
  border-right: 1px solid var(--border-subtle);
}
.input-group__affix--suffix { border-right: none; border-left: 1px solid var(--border-subtle); }
.input-group__input {
  flex: 1; min-width: 0;
  padding: var(--space-md) var(--gutter);
  border: none; background: transparent;
  text-align: right;
  font-family: var(--font-mono);
  font-feature-settings: "tnum" 1, "zero" 1;
  font-size: 1.0625rem; font-weight: var(--weight-medium);
}
.input-group__input:focus { outline: none; }
.input-group--invalid { border-color: var(--danger); }
/* Free-text lists (Average Calculator) read more naturally left-aligned
   than the right-aligned numeric convention used everywhere else. */
.input-group__input--left { text-align: left; }

.select {
  width: 100%;
  padding: var(--space-md) var(--gutter);
  background: var(--grad-key);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--elev-1);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  cursor: pointer;
}
.select:focus {
  outline: none; border-color: var(--border-focus);
  box-shadow: 0 0 0 4px var(--focus-ring);
}

/* Segmented control — sunken tray, raised active key */
.segmented {
  display: inline-flex; padding: var(--space-xs);
  background: var(--grad-sunken);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-full);
  box-shadow: var(--elev-recessed);
  gap: var(--space-xs);
}
.segmented__option {
  padding: var(--space-sm) var(--gutter);
  border-radius: var(--radius-full);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  color: var(--on-surface-muted);
  transition: all var(--duration) var(--ease-out);
}
.segmented__option:hover { color: var(--on-surface); }
.segmented__option[aria-pressed="true"] {
  background: var(--surface); color: var(--on-surface);
  box-shadow: var(--elev-2);
}

/* Range slider with a dual-tone track and a raised grip */
.slider { width: 100%; margin-top: var(--space-md); }
.slider input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 0.5rem;
  border-radius: var(--radius-full);
  background: linear-gradient(to right,
    var(--brand-500) 0%, var(--brand-600) var(--fill, 50%),
    var(--n-200) var(--fill, 50%), var(--n-200) 100%);
  box-shadow: var(--elev-recessed);
  cursor: pointer;
}
.slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 1.375rem; height: 1.375rem; border-radius: var(--radius-full);
  background: var(--grad-key); border: 1px solid var(--border-strong);
  box-shadow: var(--elev-key);
  transition: transform var(--duration-fast) var(--ease-out);
}
.slider input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.12); }
.slider input[type="range"]::-webkit-slider-thumb:active { box-shadow: var(--elev-pressed); }
.slider input[type="range"]::-moz-range-thumb {
  width: 1.375rem; height: 1.375rem; border-radius: var(--radius-full);
  background: var(--surface); border: 1px solid var(--border-strong);
  box-shadow: var(--elev-key);
}
.slider__scale {
  display: flex; justify-content: space-between;
  margin-top: var(--space-sm);
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  color: var(--on-surface-muted);
}

/* ==========================================================================
   Calculator layout — asymmetric cockpit
   ========================================================================== */
.calc-grid {
  display: grid; gap: var(--gutter-lg);
  grid-template-columns: 1fr; align-items: start;
}
@media (min-width: 64rem) {
  .calc-grid { grid-template-columns: 7fr 5fr; gap: var(--gutter-xl); }
  /* Sticky is a tall-left / short-right pattern. It is only coherent when the
     two columns have genuinely different heights, so it is scoped away from
     equal-height grids (see .calc-grid--equal below). */
  .calc-grid:not(.calc-grid--equal) .calc-grid__results {
    position: sticky; top: calc(var(--header-height) + var(--gutter));
  }
}

/* ==========================================================================
   Result panel — the hero object on every calculator page
   ========================================================================== */
.result-panel {
  position: relative; isolation: isolate;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--elev-3);
  overflow: hidden;
}
.result-panel::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--grad-result);
}
.result-panel::after {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: 3px;
  background: var(--grad-brand);
}
.result-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gutter); padding: var(--gutter-lg) var(--gutter-xl) 0;
}
.result-panel__body { padding: var(--space-md) var(--gutter-xl) var(--gutter-xl); }

.readout {
  font-size: var(--text-calc-lg); line-height: var(--lh-calc-lg);
  font-weight: var(--weight-bold); letter-spacing: var(--tracking-tighter);
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  overflow-wrap: anywhere;
}
@supports not (background-clip: text) { .readout { color: var(--primary); } }
.readout--secondary {
  font-size: var(--text-calc-md); line-height: var(--lh-calc-md);
  font-weight: var(--weight-semibold); color: var(--on-surface);
  background: none; -webkit-text-fill-color: currentColor;
}

/* Metric tiles */
.metrics {
  display: grid; gap: var(--gutter);
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  margin-top: var(--gutter-lg);
}
.metric {
  padding: var(--gutter);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--grad-key);
  box-shadow: var(--elev-1);
}
.metric--success {
  background: linear-gradient(180deg, var(--success-subtle),
              color-mix(in oklab, var(--success-subtle) 55%, var(--surface)));
  border-color: var(--success-border);
}
.metric--primary {
  background: linear-gradient(180deg, var(--brand-50), var(--surface));
  border-color: var(--brand-200);
}
.metric__label {
  display: flex; align-items: center; gap: var(--space-sm);
  font-size: var(--text-body-sm); color: var(--on-surface-variant);
  margin-bottom: var(--space-sm);
}
.metric__dot {
  width: 0.625rem; height: 0.625rem; border-radius: var(--radius-full);
  flex: none; box-shadow: var(--highlight-top);
}
.metric__dot--deposits, .split-bar__seg--deposits, .chart-legend__swatch--deposits {
  background: var(--series-1);
}
.metric__dot--growth, .split-bar__seg--growth, .chart-legend__swatch--growth {
  background: var(--success);
}
.metric__value {
  font-size: 1.1875rem; font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight);
}
.metric__sub { font-size: var(--text-body-sm); color: var(--on-surface-muted); margin-top: 0.125rem; }

/* Proportional split bar */
.split-bar {
  display: flex; height: 0.75rem; margin-top: var(--gutter-lg);
  border-radius: var(--radius-full); overflow: hidden;
  background: var(--n-200); box-shadow: var(--elev-recessed);
}
.split-bar__seg {
  height: 100%; box-shadow: var(--highlight-soft);
  transition: width var(--duration-slow) var(--ease-out);
}
.split-bar__legend {
  display: flex; justify-content: space-between;
  margin-top: var(--space-sm);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
}

/* ==========================================================================
   Plain-English translation + step-by-step proof
   ========================================================================== */
.translation {
  display: flex; gap: var(--gutter);
  padding: var(--gutter);
  background: linear-gradient(180deg, var(--brand-50), var(--surface));
  border: 1px solid var(--brand-200);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  margin-top: var(--gutter-lg);
}
.translation__icon { color: var(--primary); flex: none; margin-top: 0.125rem; }
.translation__text {
  font-size: var(--text-body-md); line-height: var(--lh-body-lg);
  color: var(--on-surface-variant);
}
.translation__text strong { color: var(--on-surface); font-weight: var(--weight-semibold); }

.proof { margin-top: var(--gutter-lg); }
.proof > summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-md); cursor: pointer; list-style: none;
  padding: var(--gutter);
  background: var(--grad-key);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  font-size: var(--text-body-md); font-weight: var(--weight-semibold);
  transition: box-shadow var(--duration) var(--ease);
}
.proof > summary:hover { box-shadow: var(--elev-2); }
.proof > summary::-webkit-details-marker { display: none; }
.proof[open] > summary {
  border-bottom-left-radius: 0; border-bottom-right-radius: 0;
  border-bottom-color: transparent;
}
.proof__body {
  border: 1px solid var(--border); border-top: none;
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  background: var(--surface-recessed);
  box-shadow: var(--elev-recessed);
  padding: var(--space-sm) var(--gutter);
}
.step { display: flex; gap: var(--gutter); padding-block: var(--space-md); }
.step + .step { border-top: 1px solid var(--border-subtle); }
.step__n {
  flex: none; width: 1.5rem; height: 1.5rem;
  display: grid; place-items: center; border-radius: var(--radius-full);
  background: var(--grad-key-primary); color: var(--on-primary);
  box-shadow: var(--glow-primary);
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  font-weight: var(--weight-bold);
}
.step__label { font-size: var(--text-body-md); font-weight: var(--weight-medium); }
.step__math {
  font-family: var(--font-mono);
  font-feature-settings: "tnum" 1, "zero" 1;
  font-size: var(--text-mono-md); color: var(--on-surface-muted);
  margin-top: var(--space-xs); overflow-wrap: anywhere;
}

/* Formula ribbon */
.formula {
  font-family: var(--font-mono);
  font-size: var(--text-body-md);
  padding: var(--gutter);
  background: linear-gradient(180deg, var(--brand-50), var(--surface));
  border: 1px solid var(--brand-200);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
  overflow-x: auto;
}
.formula-vars { list-style: none; padding: 0; margin-top: var(--gutter); display: grid; gap: var(--space-sm); }
.formula-vars li { font-size: var(--text-body-md); color: var(--on-surface-variant); }
.formula-vars code {
  font-family: var(--font-mono); font-size: var(--text-mono-md);
  color: var(--primary); font-weight: var(--weight-semibold);
  background: var(--primary-subtle); padding: 0.125rem var(--space-sm);
  border-radius: var(--radius-xs);
}

/* ==========================================================================
   Chart
   ========================================================================== */
.chart { width: 100%; height: auto; display: block; overflow: visible; }
.chart-grid { stroke: var(--border-subtle); stroke-width: 1; }
.chart-axis {
  font-family: var(--font-mono); font-size: 9px;
  fill: var(--on-surface-muted);
}
.chart-legend {
  display: flex; flex-wrap: wrap; gap: var(--gutter-lg);
  margin-top: var(--gutter);
  font-size: var(--text-body-sm); color: var(--on-surface-variant);
}
.chart-legend__item { display: flex; align-items: center; gap: var(--space-sm); }
.chart-legend__swatch {
  width: 0.75rem; height: 0.75rem; border-radius: var(--radius-xs); flex: none;
  box-shadow: var(--highlight-soft);
}

/* ==========================================================================
   Data table
   ========================================================================== */
.table-wrap {
  overflow-x: auto; max-width: 100%;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-1);
}
.table { width: 100%; border-collapse: collapse; font-size: var(--text-body-md); }
.table th {
  text-align: right; white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--text-mono-sm); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; color: var(--on-surface-muted);
  font-weight: var(--weight-medium);
  padding: var(--gutter) var(--gutter);
  background: var(--grad-sunken);
  border-bottom: 1px solid var(--border);
}
.table th:first-child, .table td:first-child {
  text-align: left; font-weight: var(--weight-semibold);
}
.table td {
  text-align: right; white-space: nowrap;
  padding: var(--space-md) var(--gutter);
  border-bottom: 1px solid var(--border-subtle);
}
.table tbody tr { transition: background var(--duration-fast) var(--ease); }
.table tbody tr:nth-child(even) { background: var(--n-25); }
.table tbody tr:hover { background: var(--primary-subtle); }
.table tbody tr:last-child td { border-bottom: none; }
.table .pos { color: var(--success); font-weight: var(--weight-medium); }

/* ==========================================================================
   FAQ
   ========================================================================== */
.faq { display: grid; gap: var(--space-md); }
.faq__item {
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  background: var(--surface);
  box-shadow: var(--elev-1);
  overflow: hidden;
  transition: box-shadow var(--duration) var(--ease);
}
.faq__item:hover { box-shadow: var(--elev-2); }
.faq__item[open] { box-shadow: var(--elev-2); }
.faq__item > summary {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gutter); cursor: pointer; list-style: none;
  padding: var(--gutter);
  font-size: var(--text-body-md); font-weight: var(--weight-semibold);
}
.faq__item > summary::-webkit-details-marker { display: none; }
.faq__item > summary::after {
  content: "+"; font-family: var(--font-mono); font-size: 1.125rem;
  color: var(--primary); flex: none;
  display: grid; place-items: center;
  width: 1.5rem; height: 1.5rem; border-radius: var(--radius-full);
  background: var(--primary-subtle);
  transition: transform var(--duration) var(--ease-out);
}
.faq__item[open] > summary::after { content: "−"; transform: rotate(180deg); }
.faq__answer {
  padding: 0 var(--gutter) var(--gutter);
  color: var(--on-surface-variant); font-size: var(--text-body-md);
  line-height: var(--lh-body-lg);
}

/* ==========================================================================
   Callout / note
   ========================================================================== */
.note {
  display: flex; gap: var(--gutter);
  padding: var(--gutter);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
  background: var(--grad-key);
  box-shadow: var(--elev-1);
}
.note__title { font-size: var(--text-body-md); font-weight: var(--weight-semibold); margin-bottom: var(--space-sm); }
.note__body { font-size: var(--text-body-md); color: var(--on-surface-variant); line-height: var(--lh-body-lg); }
.note--info {
  background: linear-gradient(180deg, var(--brand-50), var(--surface));
  border-color: var(--brand-200);
}

/* ==========================================================================
   Disclaimer — rendered from the calculator's risk tier
   ========================================================================== */
.disclaimer {
  display: flex; gap: var(--gutter);
  padding: var(--gutter);
  border-radius: var(--radius-md);
  font-size: var(--text-body-md); line-height: var(--lh-body-lg);
  background: linear-gradient(180deg, var(--warning-subtle), var(--surface));
  border: 1px solid var(--warning-border);
  box-shadow: var(--elev-1);
  color: var(--warning-text);
}
.disclaimer__icon { flex: none; margin-top: 0.125rem; }
.disclaimer--tier2 {
  background: var(--grad-key); border-color: var(--border);
  color: var(--on-surface-variant);
}
.disclaimer--tier2 .disclaimer__icon { color: var(--on-surface-muted); }
/* Tier 3 (YMYL — finance, health, tax) is the base .disclaimer style: the
   warning palette is reserved for it, so it reads as more serious than the
   tier-2 neutral. Kept as an explicit modifier so a page never has to know
   that "no modifier" means "highest tier" — that footgun cost real time once
   already, with the sticky-panel bug. */
.disclaimer--tier3 {
  background: linear-gradient(180deg, var(--warning-subtle), var(--surface));
  border-color: var(--warning-border);
  color: var(--warning-text);
}
.disclaimer--tier3 .disclaimer__icon { color: var(--warning); }
.disclaimer--tier3 strong { color: inherit; }

/* ==========================================================================
   Sources block
   ========================================================================== */
.sources {
  padding: var(--gutter-lg);
  background: var(--grad-sunken);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-lg);
  box-shadow: var(--elev-recessed);
  font-size: var(--text-body-md);
}
.sources__list { list-style: none; padding: 0; margin-top: var(--gutter); display: grid; gap: var(--space-sm); }
.sources__list li { color: var(--on-surface-variant); }
.sources__meta {
  margin-top: var(--gutter-lg); padding-top: var(--gutter);
  border-top: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: var(--gutter-lg);
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  color: var(--on-surface-muted);
}

/* ==========================================================================
   Calculator + category cards
   ========================================================================== */
/* Flex rather than grid, so a final short row CENTRES instead of hanging
   off to the left. Items grow to fill full rows but are capped by
   max-width, which is what lets the orphans sit in the middle. Works for
   any number of cards at any breakpoint — no per-count special cases. */
.card-grid {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--gutter-lg);
}
.card-grid > * {
  flex: 1 1 17.5rem;
  max-width: 21rem;
  min-width: 0;
}
/* Only go full-width on genuinely narrow screens; a 640px tablet still
   comfortably fits two cards per row. */
@media (max-width: 36rem) {
  .card-grid > * { flex-basis: 100%; max-width: none; }
}

.calc-card {
  container-type: inline-size;
  position: relative; isolation: isolate;
  display: flex; flex-direction: column; gap: var(--space-md);
  padding: var(--gutter-lg);
  background: var(--surface);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-lg);
  box-shadow: var(--elev-2);
  color: var(--on-surface);
  overflow: hidden;
  transition: transform var(--duration) var(--ease-out),
              box-shadow var(--duration) var(--ease-out),
              border-color var(--duration) var(--ease);
}
/* Accent wash that blooms on hover, tinted by the card's category */
.calc-card::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: radial-gradient(120% 90% at 50% 0%,
              color-mix(in oklab, var(--accent, var(--primary)) 12%, transparent) 0%,
              transparent 70%);
  opacity: 0; transition: opacity var(--duration) var(--ease);
}
.calc-card:hover {
  text-decoration: none; transform: translateY(-4px);
  box-shadow: var(--elev-4);
  border-color: color-mix(in oklab, var(--accent, var(--primary)) 35%, var(--border));
}
.calc-card:hover::before { opacity: 1; }

.calc-card__mark {
  width: 2.75rem; height: 2.75rem; border-radius: var(--radius-md);
  display: grid; place-items: center;
  background: linear-gradient(180deg,
              color-mix(in oklab, var(--accent, var(--primary)) 82%, white),
              var(--accent, var(--primary)));
  color: var(--n-0);
  box-shadow:
    var(--highlight-top),
    0 2px 0 0 color-mix(in oklab, var(--accent, var(--primary)) 55%, black),
    0 6px 14px -3px color-mix(in oklab, var(--accent, var(--primary)) 45%, transparent);
  font-family: var(--font-mono); font-size: 1.0625rem;
  font-weight: var(--weight-bold);
  transition: transform var(--duration) var(--ease-out);
}
.calc-card:hover .calc-card__mark { transform: translateY(-2px) scale(1.04); }

.calc-card__title {
  font-size: 1.0625rem; font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
}
.calc-card__desc {
  font-size: var(--text-body-md); color: var(--on-surface-variant);
  line-height: var(--lh-body-md); flex: 1;
}
.calc-card__meta {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  color: var(--on-surface-muted);
  padding-top: var(--space-md); margin-top: var(--space-xs);
  border-top: 1px solid var(--border-subtle);
}
.calc-card__link {
  color: var(--accent, var(--primary)); font-weight: var(--weight-semibold);
  transition: transform var(--duration) var(--ease-out);
}
.calc-card:hover .calc-card__link { transform: translateX(3px); }
.category-card__tags { display: flex; flex-wrap: wrap; gap: var(--space-sm); }

/* Category accent bindings */
.cat-financial    { --accent: var(--cat-financial); }
.cat-math         { --accent: var(--cat-math); }
.cat-conversion   { --accent: var(--cat-conversion); }
.cat-health       { --accent: var(--cat-health); }
.cat-science      { --accent: var(--cat-science); }
.cat-statistics   { --accent: var(--cat-statistics); }
.cat-everyday     { --accent: var(--cat-everyday); }
.cat-datetime     { --accent: var(--cat-datetime); }
.cat-construction { --accent: var(--cat-construction); }
.cat-tech         { --accent: var(--cat-tech); }

/* Cards stay legible when genuinely squeezed (e.g. a narrow sidebar).
   Container queries measure the CONTENT box, so this threshold sits well
   below the real card width — otherwise it fires on normal cards. */
@container (max-width: 11rem) {
  .calc-card__desc { display: none; }
  .calc-card__mark { width: 2.25rem; height: 2.25rem; }
  .calc-card__meta { font-size: var(--text-mono-sm); }
}

/* ==========================================================================
   Ad slots — heights RESERVED so nothing shifts when an ad loads.
   Deliberately quiet in development so they don't dominate the design.
   ========================================================================== */
.ad-slot {
  display: grid; place-items: center;
  background: color-mix(in oklab, var(--n-100) 55%, transparent);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  color: color-mix(in oklab, var(--on-surface-muted) 45%, transparent);
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  overflow: hidden;
}
/* Billboard — the primary unit. One premium 970x250 slot earns more than
   two stacked leaderboards, and advertisers bid hardest on standard IAB
   sizes. Heights step up with the viewport and are always RESERVED. */
.ad-slot--billboard { height: var(--ad-mobile-banner-h); }
@media (min-width: 48rem)  { .ad-slot--billboard { height: var(--ad-leaderboard-h-lg); } }
@media (min-width: 64rem)  { .ad-slot--billboard { height: var(--ad-billboard-h); } }

.ad-slot--leaderboard { height: var(--ad-leaderboard-h); }
@media (min-width: 48rem) { .ad-slot--leaderboard { height: var(--ad-leaderboard-h-lg); } }
.ad-slot--rectangle { height: var(--ad-rectangle-h); }
.ad-slot--rail { height: var(--ad-rail-h); }
@media (max-width: 63.9375rem) { .ad-slot--rail { display: none; } }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative; isolation: isolate;
  text-align: center;
  padding-block: var(--space-3xl) var(--space-2xl);
}
/* Belt and braces against horizontal scroll. `clip` (not `hidden`) keeps
   position: sticky working on the header. */
html, body { overflow-x: clip; }
/* Mesh-gradient bloom behind the hero */
.hero::before {
  content: ""; position: absolute; z-index: -1;
  inset: calc(var(--space-3xl) * -1) 0 auto;
  height: 42rem;
  background:
    radial-gradient(55% 46% at 18% 16%, oklch(61% 0.191 258 / 0.18) 0%, transparent 64%),
    radial-gradient(52% 44% at 82% 10%, oklch(61% 0.191 278 / 0.16) 0%, transparent 64%),
    radial-gradient(62% 42% at 50% 46%, oklch(66% 0.135 220 / 0.11) 0%, transparent 70%);
  filter: blur(14px);
  pointer-events: none;
}
.hero__title {
  margin-top: var(--gutter-lg);
  font-size: var(--text-display); line-height: var(--lh-display);
  font-weight: var(--weight-bold); letter-spacing: var(--tracking-tighter);
  text-wrap: balance;
}
.hero__title em {
  font-style: normal;
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
@supports not (background-clip: text) { .hero__title em { color: var(--primary); } }
.hero__sub {
  margin: var(--gutter-lg) auto 0; max-width: 36rem;
  font-size: 1.0625rem;
  color: var(--on-surface-variant); text-wrap: pretty;
}
.hero__search { margin-top: var(--gutter-xl); }
.hero__quick {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--space-md); margin-top: var(--gutter-lg);
}

/* Trust strip under the hero */
.trust-strip {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--gutter-lg); margin-top: var(--gutter-xl);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
}
.trust-strip__item { display: flex; align-items: center; gap: var(--space-sm); }
.trust-strip__item svg { color: var(--success); flex: none; }

/* ==========================================================================
   Layout utilities — the closed set. Pages never write inline styles.
   ========================================================================== */
.calc-grid > *, .card-grid > *, .field-row > *, .two-col > *, .auto-cols > * {
  min-width: 0;
}
.field-row {
  display: grid; gap: var(--gutter-lg);
  grid-template-columns: 1fr; margin-top: var(--gutter-lg);
}
@media (min-width: 30rem) { .field-row { grid-template-columns: 1fr 1fr; } }
.field-row > .field { margin-top: 0; }

.two-col {
  display: grid; gap: var(--gutter-lg);
  grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr));
}
.auto-cols {
  display: grid; gap: var(--gutter-lg);
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

.page-head {
  display: flex; flex-wrap: wrap; gap: var(--gutter-lg);
  align-items: flex-start; justify-content: space-between;
}
.page-head__main { flex: 1; min-width: 16rem; }
.page-head__actions { display: flex; flex-wrap: wrap; gap: var(--space-md); }
.page-head__lede {
  margin-top: var(--gutter); max-width: 38rem;
  font-size: 1.0625rem; color: var(--on-surface-variant); text-wrap: pretty;
}

.chip-row { display: flex; flex-wrap: wrap; gap: var(--space-md); }
.badge-row { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-bottom: var(--gutter); }

.section-title {
  font-size: var(--text-headline-lg); line-height: var(--lh-headline-lg);
  font-weight: var(--weight-bold); letter-spacing: var(--tracking-tight);
  text-wrap: balance;
}
.subhead {
  font-size: 1.0625rem; font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  margin-top: var(--gutter-xl); margin-bottom: var(--gutter);
}
.subhead:first-child { margin-top: 0; }

.mt-gutter { margin-top: var(--gutter); }
.mt-lg { margin-top: var(--gutter-lg); }
.mt-xl { margin-top: var(--gutter-xl); }
.mb-sm { margin-bottom: var(--space-sm); }
.mb-lg { margin-bottom: var(--gutter-lg); }

/* ==========================================================================
   NOTE ON SCROLL-DRIVEN REVEALS — deliberately NOT used.

   An `animation-timeline: view()` reveal leaves content at opacity 0 until
   it scrolls into view. In any static render — Googlebot's renderer, a
   print, a screenshot, a browser without support that mis-applies the
   fill mode — that content is invisible. On a site whose entire value is
   organic search, shipping text that can render at zero opacity is not a
   risk worth taking for a fade.

   Motion on this site is confined to things the user directly touches:
   hover lifts, key presses, the animated split bar. Content is never
   animated in.
   ========================================================================== */

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer {
  margin-top: var(--space-4xl);
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding-block: var(--space-2xl);
}
.footer-cols {
  display: grid; gap: var(--gutter-xl);
  grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
}
.footer-col__title {
  font-size: var(--text-body-md); font-weight: var(--weight-semibold);
  margin-bottom: var(--gutter);
}
.footer-col__list { list-style: none; padding: 0; display: grid; gap: var(--space-sm); }
.footer-col__list a { color: var(--on-surface-variant); font-size: var(--text-body-md); }
.footer-legal {
  margin-top: var(--space-2xl); padding-top: var(--gutter-lg);
  border-top: 1px solid var(--border);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
  line-height: var(--lh-body-lg); max-width: 60rem;
}
.footer-meta {
  margin-top: var(--gutter-lg); display: flex; flex-wrap: wrap;
  gap: var(--gutter-lg); font-size: var(--text-body-sm);
  color: var(--on-surface-muted);
}

/* ==========================================================================
   MOBILE
   Touch targets, a scrollable category strip, and a keypad that stays
   comfortable one-handed. Nothing here is an afterthought: most calculator
   traffic arrives on a phone.
   ========================================================================== */

/* Scrollable category strip — replaces the desktop nav on small screens.
   No JS, no hamburger, no hidden menu: every category stays one tap away. */
.mobile-nav {
  display: none;
  position: sticky; top: var(--header-height); z-index: calc(var(--z-header) - 1);
  background: color-mix(in oklab, var(--surface) 86%, transparent);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border-subtle);
}
.mobile-nav__scroll {
  display: flex; gap: var(--space-sm);
  padding: var(--space-md) var(--gutter);
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.mobile-nav__scroll::-webkit-scrollbar { display: none; }
.mobile-nav__scroll a {
  flex: none; scroll-snap-align: start;
  padding: var(--space-sm) var(--gutter);
  border-radius: var(--radius-full);
  background: var(--grad-key);
  border: 1px solid var(--border);
  box-shadow: var(--elev-1);
  color: var(--on-surface-variant);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  white-space: nowrap;
}
.mobile-nav__scroll a:hover { text-decoration: none; color: var(--on-surface); }
@media (max-width: 61.9375rem) { .mobile-nav { display: block; } }

/* The header search collapses to an icon-width field on very small screens
   so the brand never gets squeezed off. */
@media (max-width: 30rem) {
  .site-header__inner { gap: var(--space-md); }
  .brand { font-size: var(--text-body-md); }
  .search__hint { display: none; }
}

/* Tighter vertical rhythm on phones — the desktop spacing reads as dead
   space on a small screen. */
@media (max-width: 47.9375rem) {
  .hero { padding-block: var(--space-2xl) var(--gutter-lg); }
  .section { margin-top: var(--space-2xl); }
  .site-footer { margin-top: var(--space-2xl); padding-block: var(--space-xl); }
  .card { padding: var(--gutter); }
  .result-panel__head { padding: var(--gutter) var(--gutter) 0; }
  .result-panel__body { padding: var(--space-sm) var(--gutter) var(--gutter); }
  .trust-strip { gap: var(--space-md); font-size: var(--text-body-sm); }
}

/* Sticky result panel is a desktop idea; on mobile it would trap the view. */
@media (max-width: 63.9375rem) {
  .calc-grid__results { position: static; }
}

/* Honour the iOS safe area so nothing sits under the home indicator. */
@supports (padding: max(0px)) {
  .site-footer { padding-bottom: max(var(--space-xl), env(safe-area-inset-bottom)); }
  .container { padding-inline: max(var(--gutter-lg), env(safe-area-inset-left)); }
}
@media (max-width: 30rem) {
  @supports (padding: max(0px)) {
    .container { padding-inline: max(var(--gutter), env(safe-area-inset-left)); }
  }
}

/* On a phone the calculator is what people came for — get it near the top.
   Nothing is hidden from crawlers; only spacing and the duplicated badge
   (the trust strip below says the same thing) are trimmed. */
@media (max-width: 47.9375rem) {
  .hero { padding-block: var(--gutter-lg) var(--space-md); }
  .hero > .badge { display: none; }
  .hero__sub { font-size: var(--text-body-md); max-width: 30rem; margin-top: var(--gutter); }
  .trust-strip {
    margin-top: var(--gutter); gap: var(--space-sm) var(--gutter);
    justify-content: center;
  }
  .calc-widget.section { margin-top: var(--gutter-lg); }
}

/* ==========================================================================
   CALCULATOR FRAME  —  reusable shell
   ==========================================================================
   This is the standard frame for ANY interactive calculator on the site, not
   just the homepage one. Its defining property: the frame never changes size.

   The keypad stage is a fixed-height box. Every mode lays out as SIX ROWS
   inside that same box, so switching modes changes only the number of
   COLUMNS — key height, stage height and shell height all stay put. Nothing
   below the calculator ever shifts.
   ========================================================================== */

:root {
  --keypad-h: 21rem;     /* stage height — the constant the frame is built on */
  --key-gap: 0.5rem;
}

.calc-widget {
  display: grid; gap: var(--gutter-lg);
  grid-template-columns: 1fr;
  align-items: stretch;
}
@media (min-width: 60rem) {
  .calc-widget {
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: var(--gutter-xl);
  }
}

/* ---------- Shell ---------- */
.calc-shell {
  position: relative; isolation: isolate;
  display: flex; flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl);
  box-shadow: var(--elev-4);
  padding: var(--gutter-lg);
  text-align: left;
  overflow: hidden;
}
.calc-shell::after {
  content: ""; position: absolute; inset-inline: 0; top: 0; height: 3px;
  background: var(--grad-brand);
}

.calc-shell__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gutter); flex-wrap: wrap; margin-bottom: var(--gutter);
}

/* ---------- Display ---------- */
.calc-display {
  background: var(--grad-sunken);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-recessed);
  padding: var(--space-md) var(--gutter);
  text-align: right;
  display: grid; gap: var(--space-xs);
  grid-template-rows: auto auto;
}
.calc-display__expr {
  font-family: var(--font-mono);
  font-feature-settings: "tnum" 1, "zero" 1;
  font-size: var(--text-body-md);
  color: var(--on-surface-muted);
  min-height: 1.25rem;
  overflow-x: auto; white-space: nowrap; scrollbar-width: none;
}
.calc-display__expr::-webkit-scrollbar { display: none; }
.calc-display__out {
  font-family: var(--font-mono);
  font-feature-settings: "tnum" 1, "zero" 1;
  font-size: clamp(2.25rem, 1.5rem + 2.8vw, 3.25rem);
  line-height: 1.1;
  font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tighter);
  background: var(--grad-brand);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  overflow-x: auto; white-space: nowrap; scrollbar-width: none;
}
.calc-display__out::-webkit-scrollbar { display: none; }
@supports not (background-clip: text) { .calc-display__out { color: var(--primary); } }
.calc-display__error {
  display: flex; align-items: center; gap: var(--space-sm); justify-content: flex-end;
  font-size: var(--text-body-sm); color: var(--danger);
}

/* ==========================================================================
   Keypad stage — the fixed-size box every mode renders into
   ========================================================================== */
/* ---------- Stage: a fixed-height box that swaps panels in 3D ----------
   Used by the keypad (standard/scientific) and by any calculator with
   several input modes. The height never changes, so switching modes never
   moves anything below it on the page. */
.stage, .keypad-stage {
  position: relative;
  perspective: 1400px;
  perspective-origin: 50% 40%;
}
.keypad-stage { height: var(--keypad-h); margin-top: var(--gutter); }
.stage { height: var(--stage-h, auto); }

.stage__panel, .keypad-panel {
  position: absolute; inset: 0;
  transform-origin: 50% 0%;
  transition:
    opacity var(--duration) var(--ease),
    transform var(--duration-slow) var(--ease-out),
    filter var(--duration) var(--ease);
  will-change: transform, opacity;
}
.keypad-panel {
  display: grid;
  grid-template-rows: repeat(6, 1fr);   /* SIX ROWS IN EVERY MODE */
  gap: var(--key-gap);
}
.stage__panel { overflow-y: auto; scrollbar-width: none; }
.stage__panel::-webkit-scrollbar { display: none; }

/* Standard: four columns */
.keypad-panel--standard { grid-template-columns: repeat(4, 1fr); }
/* Scientific: the same six rows, with two function columns added on the left.
   The standard block keeps its exact row rhythm — only column width changes. */
.keypad-panel--scientific { grid-template-columns: repeat(6, 1fr); }

/* Inactive panel: pushed back and tilted away, not just faded */
.stage__panel[aria-hidden="true"],
.keypad-panel[aria-hidden="true"] {
  opacity: 0;
  pointer-events: none;
  transform: rotateX(10deg) translateZ(-90px) scale(0.965);
  filter: blur(2px);
}
.stage__panel[aria-hidden="false"],
.keypad-panel[aria-hidden="false"] {
  opacity: 1;
  transform: none;
  filter: none;
}
/* Panels entering from the "later" side arrive from the opposite angle */
.stage[data-dir="back"] .stage__panel[aria-hidden="true"] {
  transform: rotateX(-10deg) translateZ(-90px) scale(0.965);
}
/* Direction of the flip depends on which way we are travelling */
#main-calc[data-calc-mode="scientific"] .keypad-panel--standard {
  transform: rotateX(-10deg) translateZ(-90px) scale(0.965);
}

@media (prefers-reduced-motion: reduce) {
  .stage__panel, .keypad-panel {
    transition: opacity var(--duration-fast) linear; filter: none !important;
  }
  .stage__panel[aria-hidden="true"], .keypad-panel[aria-hidden="true"] {
    transform: none; filter: none;
  }
}

/* ==========================================================================
   Keys
   ========================================================================== */
.key {
  --key-face: var(--grad-key);
  --key-text: var(--on-surface);
  --key-edge: hsl(var(--shadow-color) / 0.10);
  display: grid; place-items: center;
  border-radius: var(--radius);
  border: 1px solid var(--border);
  background: var(--key-face); color: var(--key-text);
  box-shadow:
    var(--highlight-top),
    0 1px 1px hsl(var(--shadow-color) / 0.06),
    0 2px 0 0 var(--key-edge),
    0 4px 10px -2px hsl(var(--shadow-color) / 0.10);
  font-family: var(--font-mono);
  font-size: 1.1875rem; font-weight: var(--weight-semibold);
  font-feature-settings: "tnum" 1, "zero" 1;
  line-height: 1;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform var(--duration-fast) var(--ease-out),
              box-shadow var(--duration-fast) var(--ease-out),
              background var(--duration-fast) var(--ease);
}
.key:hover {
  transform: translateY(-2px);
  box-shadow:
    var(--highlight-top),
    0 1px 1px hsl(var(--shadow-color) / 0.06),
    0 4px 0 0 var(--key-edge),
    0 10px 20px -4px hsl(var(--shadow-color) / 0.16);
}
.key:active, .key.is-active {
  transform: translateY(2px);
  box-shadow: var(--elev-pressed);
}
.key svg { width: 1.25rem; height: 1.25rem; }

/* Operator keys — clearly a different material from the digits */
.key--op {
  --key-face: linear-gradient(180deg, var(--brand-100), var(--brand-200));
  --key-text: var(--brand-800);
  --key-edge: oklch(54% 0.213 262 / 0.22);
  border-color: var(--brand-300);
  font-size: 1.375rem;
}
/* Scientific function keys — quieter, smaller label */
.key--fn {
  --key-face: linear-gradient(180deg, var(--n-0), var(--n-150));
  --key-text: var(--on-surface-variant);
  font-size: var(--text-body-md);
  font-weight: var(--weight-medium);
}
/* Clear */
.key--clear {
  --key-face: linear-gradient(180deg, var(--danger-subtle), oklch(93% 0.045 25));
  --key-text: var(--danger);
  --key-edge: oklch(57% 0.212 25 / 0.22);
  border-color: var(--danger-border);
}
/* Equals — primary action */
.key--equals {
  --key-face: var(--grad-key-primary);
  --key-text: var(--on-primary);
  border-color: transparent;
  box-shadow: var(--glow-primary);
  font-size: 1.5rem;
}
.key--equals:hover { box-shadow: var(--glow-primary-hover); transform: translateY(-2px); }
.key--equals:active, .key--equals.is-active { box-shadow: var(--elev-pressed); }

.key--span2 { grid-column: span 2; }
.key--span3 { grid-column: span 3; }

/* ---------- Footer hint ---------- */
.calc-hint {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gutter); flex-wrap: wrap;
  margin-top: var(--gutter);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
}
.kbd {
  display: inline-grid; place-items: center;
  min-width: 1.5rem; padding: 0.125rem var(--space-sm);
  font-family: var(--font-mono); font-size: var(--text-mono-sm);
  background: var(--grad-key); color: var(--on-surface-variant);
  border: 1px solid var(--border); border-radius: var(--radius-xs);
  box-shadow: var(--elev-1);
}

/* ---------- Side column ---------- */
/* The side column matches the calculator's height: the informational card
   sizes to its content and the tape takes whatever is left, so there is no
   dead space beside the keypad. */
.calc-side { display: grid; gap: var(--gutter-lg); grid-template-rows: auto 1fr; }
.calc-side > .card { display: flex; flex-direction: column; }
.tape-card__body { flex: 1; display: flex; flex-direction: column; justify-content: center; }

/* ---------- Tape ---------- */
.tape__list {
  display: grid; gap: var(--space-xs);
  max-height: 13rem; overflow-y: auto;
  margin-top: var(--space-md);
}
.tape__row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gutter); width: 100%;
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  font-family: var(--font-mono); font-size: var(--text-mono-md);
  text-align: left;
  transition: background var(--duration-fast) var(--ease);
}
.tape__row:hover { background: var(--primary-subtle); }
.tape__expr { color: var(--on-surface-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tape__result { color: var(--on-surface); font-weight: var(--weight-semibold); flex: none; }
.tape__empty {
  padding: var(--gutter-lg) var(--gutter); text-align: center;
  border: 1px dashed var(--border); border-radius: var(--radius-md);
  color: var(--on-surface-muted); font-size: var(--text-body-sm);
  text-wrap: pretty;
}
@media (max-width: 59.9375rem) {
  .calc-side { grid-template-rows: auto auto; }
}

/* ---------- Mobile ---------- */
@media (max-width: 47.9375rem) {
  :root { --keypad-h: 23rem; --key-gap: 0.4375rem; }
  .calc-shell { padding: var(--gutter); }
  .key { font-size: 1.25rem; }
  .key--op { font-size: 1.375rem; }
  /* Six columns still clears the 44px touch minimum at 390px wide
     (keys land at roughly 48 x 55px), so the layout is identical on
     every screen size. */
  .key--fn { font-size: var(--text-body-sm); }
}

/* The calculator follows the hero directly; the full section rhythm reads
   as a disconnect between them. */
.calc-widget.section { margin-top: var(--space-xl); }


/* ==========================================================================
   Mode tabs — for calculators that answer several related questions.
   A wider, wrapping variant of the segmented control.
   ========================================================================== */
.mode-tabs {
  display: grid; gap: var(--space-xs);
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  padding: var(--space-xs);
  background: var(--grad-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-recessed);
}
.mode-tab {
  padding: var(--space-md) var(--space-md);
  border-radius: var(--radius);
  font-size: var(--text-body-md); font-weight: var(--weight-medium);
  color: var(--on-surface-variant); text-align: center;
  transition: all var(--duration) var(--ease-out);
}
.mode-tab:hover { color: var(--on-surface); }
.mode-tab[aria-selected="true"] {
  background: var(--surface); color: var(--on-surface);
  font-weight: var(--weight-semibold);
  box-shadow: var(--elev-2);
}

/* A question restated above the inputs, so the page always says plainly
   what it is solving for. */
.mode-question {
  margin-top: var(--gutter-lg);
  font-size: var(--text-headline-md); line-height: var(--lh-headline-md);
  font-weight: var(--weight-semibold); letter-spacing: var(--tracking-snug);
  text-wrap: balance;
}
.mode-question em {
  font-style: normal; color: var(--primary);
}

/* Percentage calculator: the stage is sized to its TALLEST mode
   (increase/decrease, which adds a direction toggle), measured rather than
   guessed. Every mode therefore fits without scrolling and the card height
   never changes when you switch questions. */
.pct-stage { --stage-h: 14rem; margin-top: var(--gutter-lg); }
/* Below 36rem the fields stack, so every mode needs more room. */
@media (max-width: 36rem) { .pct-stage { --stage-h: 22rem; } }

/* ==========================================================================
   NUMPAD — shared component
   Any calculator can drop one in; it types into whichever input in its
   scope was last focused.
   ========================================================================== */
.numpad {
  display: grid; gap: var(--key-gap);
  grid-template-columns: repeat(4, 1fr);
  margin-top: var(--gutter);
  padding: var(--space-md);
  background: var(--grad-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-recessed);
}
.numpad .key { min-height: 2.75rem; font-size: 1.0625rem; }
.numpad .key svg { width: 1.125rem; height: 1.125rem; }
@media (max-width: 47.9375rem) { .numpad .key { min-height: 3.25rem; font-size: 1.1875rem; } }

/* The input the pad is currently typing into */
.input-group--targeted {
  border-color: var(--border-focus);
  box-shadow: var(--elev-recessed), 0 0 0 3px var(--focus-ring);
}

.numpad-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gutter); margin-top: var(--gutter-lg);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
}

/* ==========================================================================
   VISUAL BREAKDOWN
   Two forms: a radial gauge for part-of-whole, paired bars for before/after.
   Marks are thin, ends are rounded, every mark is direct-labelled, and the
   grid/axis furniture stays recessive.
   ========================================================================== */
.viz-card { position: relative; }
.viz-stage {
  position: relative;
  min-height: 13rem;
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-2xl); flex-wrap: wrap;
}
.viz-empty { color: var(--on-surface-muted); font-size: var(--text-body-md); }
.viz-note {
  margin-top: var(--gutter);
  padding-top: var(--gutter);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
  text-wrap: pretty;
}

/* ---------- Ring ---------- */
.viz-ring { position: relative; width: 11.25rem; height: 11.25rem; flex: none; }
/* The SVG canvas itself must not swallow pointer events, or the arc
   underneath can never be hovered. Only the drawn stroke is a target. */
.viz-ring__svg { width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.viz-ring__arc {
  pointer-events: stroke;
  transition: stroke-dasharray var(--duration-slow) var(--ease-out);
  filter: drop-shadow(0 2px 6px oklch(54% 0.213 262 / 0.28));
  cursor: pointer;
}
.viz-ring__arc:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 4px; }
.viz-ring__center {
  position: absolute; inset: 0;
  display: grid; place-content: center; text-align: center;
  pointer-events: none;
}
.viz-ring__pct {
  font-size: 1.75rem; font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight); color: var(--on-surface);
  line-height: 1.1;
}
.viz-ring__sub { font-size: var(--text-body-sm); color: var(--on-surface-muted); }

/* ---------- Legend ---------- */
.viz-legend { display: grid; gap: var(--space-sm); min-width: 13rem; }
.viz-legend__row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--gutter-lg);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-sm);
  font-size: var(--text-body-md);
  transition: background var(--duration-fast) var(--ease);
  cursor: default;
}
.viz-legend__row:hover { background: var(--surface-recessed); }
.viz-legend__row:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 2px; }
.viz-legend__row dt {
  display: flex; align-items: center; gap: var(--space-sm);
  color: var(--on-surface-variant);
}
.viz-legend__row dd { font-weight: var(--weight-semibold); }
.viz-legend__row--total {
  border-top: 1px solid var(--border); padding-top: var(--space-md);
  margin-top: var(--space-xs); font-weight: var(--weight-semibold);
}
.viz-swatch {
  width: 0.75rem; height: 0.75rem; border-radius: var(--radius-xs);
  flex: none; box-shadow: var(--highlight-soft);
}
.viz-swatch--part { background: var(--series-1); }
.viz-swatch--rest { background: var(--n-200); }

/* ---------- Bars ---------- */
.viz-bars {
  display: flex; align-items: flex-end; justify-content: center;
  gap: var(--space-xl);
  padding-top: var(--gutter-lg);
}
.viz-bar {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-sm);
  width: 5.5rem; cursor: default;
}
.viz-bar:focus-visible { outline: 2px solid var(--border-focus); outline-offset: 4px; border-radius: var(--radius-sm); }
.viz-bar__value {
  font-size: var(--text-body-md); font-weight: var(--weight-semibold);
  color: var(--on-surface);
}
.viz-bar__fill {
  width: 100%;
  /* Rounded data-end anchored to the baseline — square at the bottom */
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  box-shadow: var(--highlight-soft);
  transition: height var(--duration-slow) var(--ease-out),
              background var(--duration) var(--ease);
}
.viz-bar__label {
  font-size: var(--text-body-sm); color: var(--on-surface-muted);
  padding-top: var(--space-sm);
  border-top: 1px solid var(--border);
  width: 100%; text-align: center;
}
.viz-delta {
  display: grid; justify-items: center; gap: 0.125rem;
  padding-bottom: var(--space-2xl);
  color: var(--on-surface-muted);
}
.viz-delta__arrow { font-size: 1.5rem; line-height: 1; }
.viz-delta__pct { font-size: var(--text-body-lg); font-weight: var(--weight-bold); }
.viz-delta__abs { font-size: var(--text-body-sm); }
.viz-delta.is-up   { color: var(--success); }
.viz-delta.is-down { color: var(--warning-text); }

/* ---------- Tooltip ---------- */
.viz-tip {
  position: absolute; z-index: var(--z-overlay);
  transform: translate(-50%, calc(-100% - 0.5rem));
  padding: var(--space-sm) var(--space-md);
  background: var(--surface-inverse); color: var(--on-surface-inverse);
  border-radius: var(--radius-sm);
  box-shadow: var(--elev-3);
  font-size: var(--text-body-sm); white-space: nowrap;
  pointer-events: none;
}

@media (max-width: 40rem) {
  .viz-stage { gap: var(--gutter-lg); }
  .viz-ring { width: 9rem; height: 9rem; }
  .viz-ring__pct { font-size: 1.375rem; }
  .viz-legend { min-width: 0; width: 100%; }
  .viz-bars { gap: var(--gutter); }
  .viz-bar { width: 4.5rem; }
}


/* ==========================================================================
   Equal-height calculator columns
   --------------------------------------------------------------------------
   Opt-in modifier for pages where the inputs card and the result panel
   should line up top and bottom. The result panel becomes a flex column and
   its step-by-step block absorbs the slack, so the extra height reads as a
   roomier proof rather than an empty gap.

   Not the default: pages with a genuinely long input column can drop the
   modifier and get the sticky result panel instead, which needs the columns
   to size independently. The two are mutually exclusive — a sticky panel
   inside an equal-height grid has nothing to scroll within, so it detaches
   mid-scroll and leaves the left column stranded.
   ========================================================================== */
.calc-grid--equal { align-items: stretch; }
.calc-grid--equal > *:not(.calc-grid__ad) { min-height: 100%; }
/* `static` is load-bearing, not decorative: it cancels the sticky rule above.
   min-height (not height) lets the column grow past the row if content
   demands it, instead of clamping and painting over the ad beneath. */
.calc-grid--equal .calc-grid__results { position: static; min-height: 100%; }
.calc-grid--equal .calc-grid__results.stack { display: flex; flex-direction: column; }
.calc-grid--equal .result-panel {
  flex: 1; display: flex; flex-direction: column;
}
/* The slack is distributed between the result panel's sections rather than
   stretching any single one. A <details> element will not pass flex growth
   to its content (Chromium renders that content in an internal slot), so
   growing the proof box is not an option — and even if it were, an
   artificially tall step list reads worse than generous spacing. */
.calc-grid--equal .result-panel__body {
  flex: 1; display: flex; flex-direction: column;
  justify-content: space-between; gap: var(--gutter);
}
.calc-grid--equal .result-panel__body > * { margin-top: 0; }

/* Stacked on narrow screens, equal heights stop being meaningful. */
@media (max-width: 63.9375rem) {
  .calc-grid--equal > * { min-height: 0; }
  .calc-grid--equal .result-panel__body { flex: 0 1 auto; justify-content: flex-start; }
}

/* ==========================================================================
   Chart — axis, grid and hover layer
   ========================================================================== */
.chart-wrap { position: relative; margin-top: var(--gutter); }
.chart { width: 100%; height: auto; display: block; overflow: visible; touch-action: pan-y; }

.chart-axis-line { stroke: var(--border); stroke-width: 1; }
.chart-endlabel {
  font-family: var(--font-mono); font-size: 13px;
  font-weight: 600; fill: var(--success);
}
.chart-crosshair {
  stroke: var(--border-strong); stroke-width: 1; stroke-dasharray: 3 3;
}
.chart-dot { stroke: var(--surface); stroke-width: 2.5; }
.chart-dot--value   { fill: var(--series-2); }
.chart-dot--deposit { fill: var(--series-1); }

/* The legend sits in the card header on wide screens and wraps below it
   when the heading needs the room. */
.viz-card .card__header .chart-legend { margin-top: 0; }
/* `hidden` is an HTMLElement property and does nothing on an SVG node,
   so the crosshair group is toggled with a class. */
.chart-cursor.is-hidden { display: none; }

/* ==========================================================================
   LIVE GRAPH (homepage calculator)
   Function plot in scientific mode, value breakdown for plain arithmetic.
   ========================================================================== */
.graph-card { display: flex; flex-direction: column; }
.graph-stage {
  flex: 1;
  min-height: 11rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--grad-sunken);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--elev-recessed);
  padding: var(--space-md);
  overflow: hidden;
}
.plot { width: 100%; height: auto; display: block; overflow: visible; }
.plot-axis  { stroke: var(--border-strong); stroke-width: 1; }
.plot-drop  { stroke: var(--series-1); stroke-width: 1.5; stroke-dasharray: 3 3; opacity: 0.55; }

.plot-caption {
  margin-top: var(--gutter);
  font-family: var(--font-mono);
  font-size: var(--text-mono-md);
  color: var(--on-surface-variant);
  display: flex; align-items: baseline; gap: var(--space-md);
  flex-wrap: wrap;
}
.plot-caption strong { color: var(--on-surface); font-weight: var(--weight-semibold); }
.plot-caption__fn {
  margin-left: auto;
  padding: 0.125rem var(--space-sm);
  border-radius: var(--radius-xs);
  background: var(--primary-subtle); color: var(--primary);
  font-size: var(--text-mono-sm);
}

/* ---------- Value breakdown bars ---------- */
.mini-bars {
  display: flex; align-items: flex-end; justify-content: center;
  gap: var(--space-sm); width: 100%; padding-top: var(--gutter);
}
.mini-bar {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-xs);
  flex: 1; min-width: 0; max-width: 3.5rem;
}
.mini-bar__v {
  font-size: var(--text-body-sm); color: var(--on-surface-variant);
  white-space: nowrap;
}
.mini-bar__fill {
  width: 100%;
  background: var(--n-300);
  border-radius: var(--radius-xs) var(--radius-xs) 0 0;
  box-shadow: var(--highlight-soft);
  transition: height var(--duration) var(--ease-out);
}
.mini-bar--result .mini-bar__fill { background: var(--grad-key-primary); }
.mini-bar--result .mini-bar__v { color: var(--primary); font-weight: var(--weight-bold); }
.mini-bar__gap { width: 0; }
.mini-bar__eq {
  font-family: var(--font-mono); font-size: 1.125rem;
  color: var(--on-surface-muted); padding-inline: var(--space-sm);
  align-self: center;
}

/* ==========================================================================
   Tape — compact and scrollable, with a clear action
   ========================================================================== */
.tape-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--gutter); margin-bottom: var(--space-md);
  min-height: 2rem;
}
.tape__list {
  max-height: 9rem;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
  padding-right: var(--space-xs);
}
.tape__list::-webkit-scrollbar { width: 6px; }
.tape__list::-webkit-scrollbar-track { background: transparent; }
.tape__list::-webkit-scrollbar-thumb {
  background: var(--border-strong); border-radius: var(--radius-full);
}
.tape__empty { padding: var(--gutter) var(--space-md); }

/* ==========================================================================
   MOBILE: ANSWER FIRST
   --------------------------------------------------------------------------
   When the two columns stack, the result panel moves ABOVE the inputs.

   Without this, a phone user scrolls past the whole input form and the
   numpad before seeing their answer — then has to scroll back up to change
   anything. The answer is what they came for, so it goes first.

   Trade-off, stated plainly: visual order now differs from DOM order, which
   WCAG 2.4.3 cautions about. It is acceptable here because the result panel
   contains a single focusable element (the step-by-step disclosure) — tab
   order still runs inputs → result, which remains a meaningful sequence.
   Desktop is untouched.
   ========================================================================== */
@media (max-width: 63.9375rem) {
  .calc-grid__results { order: -1; }
  .calc-grid__results.stack > * + * { margin-top: var(--gutter-lg); }
}

/* The in-grid ad spans both columns on desktop, so it renders below the
   calculator exactly as a sibling would. */
.calc-grid__ad { grid-column: 1 / -1; margin-top: var(--gutter-lg); }

@media (max-width: 63.9375rem) {
  /* Stacked order: answer → ad → inputs. The ad lands at the natural break
     after the result instead of at the foot of a very long input card. */
  .calc-grid__results { order: 1; }
  .calc-grid__ad      { order: 2; margin-top: 0; }
  .calc-grid > section.card, .calc-grid > #ci-inputs { order: 3; }
}

/* ==========================================================================
   Coming-soon cards
   ==========================================================================
   A calculator that is named but not yet built renders as a card that is not
   a link, rather than as `<a href="#">`. Ten of those dead links used to sit
   on the homepage. The registry now decides this, so the state is impossible
   to get wrong by hand — but it needs to still look like part of the set,
   just visibly inert. */
.calc-card--soon {
  cursor: default;
  opacity: 0.72;
  background: var(--grad-sunken);
}
.calc-card--soon:hover { transform: none; box-shadow: var(--elev-1); }
.calc-card--soon .calc-card__meta { color: var(--on-surface-muted); }
