/* =========================================================================================
   SOLAR ASSURE · shared stylesheet
   Ported from the Tech Allies design system (C:\dev\tech-allies\app\globals.css) with Solar
   Assure brand tokens. One font (Inter), flat colour bands, hairline rules, a single accent.
   Band names: paper | cream | night | deep. See docs/operators/revamp-spec-2026-09-09.md.
   ========================================================================================= */

@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/Inter-Latin-Variable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* ----------------------------------------------------------------------------------------
   Tokens
   ---------------------------------------------------------------------------------------- */
:root {
  /* Brand colours */
  --paper: #FFFBF4;
  --cream: #FFF4E6;
  --night: #0B1424;
  --night-deep: #060C18;
  --night-panel: #14223B;
  --white: #FFFFFF;
  --ink: #0A0F1A;
  --muted: #5C6070;
  --sunset-deep: #E24A18;
  --sunset: #FF6B35;
  --amber: #FFB547;
  --gold: #FFD066; /* data-viz only: chart lines. Never text, never CTAs. */
  --rise: #F87171; /* data-viz only: rate chart, utility line */
  --calm: #34D399; /* data-viz only: rate chart, solar line */

  /* semantic surfaces and ink (paper band defaults; cream/night/deep bands override) */
  --canvas: var(--paper);
  --ink-muted: var(--muted);
  --hairline: color-mix(in oklab, var(--night) 14%, var(--paper));
  --hairline-strong: color-mix(in oklab, var(--night) 28%, var(--paper));
  --surface: var(--white);
  --surface-tint: var(--cream);
  --link: var(--sunset-deep);
  --eyebrow: var(--sunset-deep);
  --focus: var(--sunset-deep);

  /* type */
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --fs-display: clamp(2.25rem, 1.6rem + 2.9vw, 3.75rem);
  --fs-h1-inner: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);
  --fs-h2: clamp(1.75rem, 1.3rem + 1.9vw, 2.75rem);
  --fs-h3: clamp(1.125rem, 1.05rem + .35vw, 1.375rem);
  --fs-lede: clamp(1.0625rem, 1rem + .35vw, 1.25rem);
  --fs-body: 1rem;
  --fs-small: .875rem;
  --fs-label: .75rem;
  --fs-mono: .78rem;
  --w-display: 700;
  --w-h2: 680;
  --w-h3: 640;
  --w-ui: 600;
  --w-btn: 650;
  --track-display: -.03em;
  --track-h2: -.025em;
  --track-h3: -.015em;
  --track-label: .08em;
  --track-mono: .02em;
  --lh-display: 1.02;
  --lh-h2: 1.08;
  --lh-h3: 1.2;
  --lh-body: 1.55;
  --measure: 62ch;
  --measure-narrow: 46ch;

  /* spacing */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s8: 32px;
  --s10: 40px; --s12: 48px; --s14: 56px; --s16: 64px; --s18: 72px; --s24: 96px;
  --section: var(--s24);
  --gutter: clamp(20px, 5vw, 40px);
  --container: 1200px;
  --container-wide: 1360px;
  --header-h: 64px;
  --sticky-h: 64px;

  /* shape and depth */
  --r-pill: 999px;
  --r-surface: 12px;
  --r-inner: 8px;
  --shadow-float: 0 -1px 0 var(--hairline), 0 -8px 24px rgba(11, 20, 36, .08);

  /* motion */
  --ease-out: cubic-bezier(.2, .7, .2, 1);
  --ease-in-out: cubic-bezier(.5, 0, .5, 1);
  --t-micro: 100ms;
  --t-ui: 200ms;
  --t-reveal: 420ms;
  --t-draw: 700ms;

  /* Motion stage additions (docs/operators/motion-and-mobile-2026-09-09.md): spring feel without
     a library, used by the island, chips, details, rolling numbers, popovers and sheets below.
     Kept as separate tokens from the base --ease-out/--t-ui above (which pre-date this stage and
     still drive the original chrome/reveal system) rather than redefined in place, so nothing
     already shipped shifts timing. */
  --ease-spring: cubic-bezier(.22, 1, .36, 1);
  --t-m-micro: 180ms;
  --t-m-medium: 320ms;
  --t-m-large: 500ms;
  --t-m-stagger: 60ms;
}
@media (max-width: 1024px) { :root { --section: var(--s18); } }
@media (max-width: 640px) { :root { --section: var(--s14); --header-h: 60px; } }

/* Band inversions */
[data-band="cream"] {
  --canvas: var(--cream);
  --hairline: color-mix(in oklab, var(--night) 16%, var(--cream));
  --hairline-strong: color-mix(in oklab, var(--night) 32%, var(--cream));
  --surface: var(--white);
  --surface-tint: var(--white);
}
[data-band="night"] {
  --canvas: var(--night);
  --ink: var(--paper);
  --ink-muted: rgba(255, 251, 244, .72);
  --hairline: rgba(255, 251, 244, .16);
  --hairline-strong: rgba(255, 251, 244, .32);
  --surface: var(--night-panel);
  --surface-tint: var(--night-panel);
  --link: var(--amber);
  --eyebrow: var(--amber);
  --focus: var(--amber);
}
[data-band="deep"] {
  --canvas: var(--night-deep);
  --ink: var(--paper);
  --ink-muted: rgba(255, 251, 244, .62);
  --hairline: rgba(255, 251, 244, .14);
  --hairline-strong: rgba(255, 251, 244, .3);
  --surface: var(--night-panel);
  --link: var(--amber);
  --eyebrow: var(--amber);
  --focus: var(--amber);
}
[data-band] { background: var(--canvas); color: var(--ink); }

/* ----------------------------------------------------------------------------------------
   Base
   ---------------------------------------------------------------------------------------- */
* { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 12px);
}
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: var(--lh-body);
}
body[data-sticky] { padding-bottom: calc(var(--sticky-h) + env(safe-area-inset-bottom)); }
@media (min-width: 901px) { body[data-sticky] { padding-bottom: 0; } }
a { color: inherit; text-decoration: none; }
h1, h2, h3, h4 { margin: 0; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }
figure { margin: 0; }
img, svg, video { display: block; max-width: 100%; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input, textarea, select { font: inherit; color: inherit; }
[id] { scroll-margin-top: calc(var(--header-h) + 16px); }
::selection { background: var(--amber); color: var(--night); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: 2px; }
a, button, summary, label { touch-action: manipulation; -webkit-tap-highlight-color: transparent; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip-link { position: absolute; top: 8px; left: 8px; z-index: 100; padding: 10px 16px; border-radius: var(--r-pill); background: var(--night); color: var(--paper); font-weight: var(--w-ui); transform: translateY(-200%); }
.skip-link:focus-visible { transform: none; outline-color: var(--sunset); }

/* Type roles */
.display { font-size: var(--fs-display); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: var(--lh-display); }
.h1-inner { font-size: var(--fs-h1-inner); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.05; }
.h2 { font-size: var(--fs-h2); font-weight: var(--w-h2); letter-spacing: var(--track-h2); line-height: var(--lh-h2); }
.h3 { font-size: var(--fs-h3); font-weight: var(--w-h3); letter-spacing: var(--track-h3); line-height: var(--lh-h3); }
.h2, .h3 { max-width: 26ch; }
.h2.wide, .h3.wide { max-width: none; }
.lede { font-size: var(--fs-lede); line-height: 1.5; color: var(--ink-muted); max-width: var(--measure-narrow); }
.body-lg { font-size: var(--fs-lede); line-height: 1.55; }
.measure { max-width: var(--measure); }
.muted { color: var(--ink-muted); }
.small { font-size: var(--fs-small); line-height: 1.5; }
.eyebrow { margin: 0 0 var(--s4); color: var(--eyebrow); font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); text-transform: uppercase; }
.mono { font-size: 13px; font-weight: 500; letter-spacing: 0; font-variant-numeric: tabular-nums; color: var(--ink-muted); }
.num { font-variant-numeric: tabular-nums; }
.accent { color: var(--sunset); }
[data-band="paper"] .accent, [data-band="cream"] .accent { color: inherit; }
@media (max-width: 640px) { :root { --track-display: -.025em; } }

/* ----------------------------------------------------------------------------------------
   Layout primitives
   ---------------------------------------------------------------------------------------- */
.container { width: min(var(--container), 100% - 2 * var(--gutter)); margin-inline: auto; }
.container-wide { width: min(var(--container-wide), 100% - 2 * var(--gutter)); margin-inline: auto; }
.section { padding-block: var(--section); }
.section-tight { padding-block: var(--s16); }
.section-flush-top { padding-top: 0; }
.band { position: relative; }
.band + .band[data-band="paper"] { border-top: 1px solid var(--hairline); }
.band[data-band="night"] + .band[data-band="paper"], .band[data-band="cream"] + .band[data-band="paper"] { border-top: 0; }
.band-rule::before { content: ""; display: block; width: 48px; height: 4px; margin-bottom: var(--s8); background: var(--sunset); border-radius: 2px; }
.stack { display: grid; gap: var(--s4); align-content: start; }
.stack-lg { display: grid; gap: var(--s6); align-content: start; }
.stack > .lede, .stack-lg > .lede { margin-top: var(--s2); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s4) var(--s6); margin-top: var(--s4); }
.section-head { display: grid; gap: var(--s4); margin-bottom: var(--s10); max-width: 720px; }
.section-head > p { color: var(--ink-muted); max-width: var(--measure-narrow); }
.split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: var(--s16); align-items: center; }
.split-narrow { grid-template-columns: .8fr 1.2fr; align-items: start; }
.split-narrow > .sticky-intro { position: sticky; top: calc(var(--header-h) + 24px); }
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s10) var(--s16); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s10) var(--s10); }
@media (max-width: 900px) {
  .split, .split-narrow, .grid-3 { grid-template-columns: minmax(0, 1fr); gap: var(--s10); }
  .split-narrow > .sticky-intro { position: static; }
}
@media (max-width: 640px) {
  .grid-2 { grid-template-columns: 1fr; gap: var(--s8); }
  .section-head { margin-bottom: var(--s8); }
}

/* Hairline grid (stat lists, ownership-style grids) */
.hairline-grid { display: grid; gap: var(--s8) var(--s10); }
.hairline-grid > * { display: grid; gap: var(--s2); align-content: start; }
.hairline-grid[data-cols="2"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.hairline-grid[data-cols="3"] { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.hairline-grid[data-cols="4"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.hairline-grid .cell-title { display: flex; align-items: flex-start; gap: var(--s3); font-size: 1.0625rem; font-weight: var(--w-h3); letter-spacing: -.01em; }
.hairline-grid .cell-title svg { flex: 0 0 auto; margin-top: 3px; color: var(--ink); }
.hairline-grid .cell-detail { color: var(--ink-muted); font-size: 15px; line-height: 1.55; }
@media (max-width: 640px) { .hairline-grid[data-cols] { grid-template-columns: minmax(0, 1fr); gap: var(--s6); } }
@media (max-width: 900px) { .hairline-grid[data-cols="3"], .hairline-grid[data-cols="4"] { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* Stat list: value / label / note. Solar Assure addition, built on hairline-grid. No boxes. */
.stat-list .cell-value { font-size: var(--fs-h3); font-weight: var(--w-h3); letter-spacing: -.01em; font-variant-numeric: tabular-nums; }

/* M4 rolling numbers: sa.js builds a 10-row digit column per numeric character inside any
   [data-roll] element (render.mjs adds the hook to every .cell-value); non-digit runs (commas,
   $, units) stay plain text nodes alongside the columns. tabular-nums above keeps row widths
   even; it is inherited down into each column. */
.sa-roll-d { display: inline-block; height: 1em; line-height: 1; overflow: hidden; vertical-align: bottom; }
.sa-roll-t { display: block; white-space: pre; line-height: 1; text-align: center; }
.sa-roll.sa-roll-live .sa-roll-t { transition: transform 400ms var(--ease-spring); }
.stat-list .cell-label { color: var(--ink-muted); font-size: var(--fs-small); }
.stat-list .cell-note { color: var(--ink-muted); font-size: 13px; }

/* ----------------------------------------------------------------------------------------
   Buttons and links
   ---------------------------------------------------------------------------------------- */
/* Icon sizing: every inline icon SVG in this file is a bare viewBox="0 0 24 24" element with
   no intrinsic size, so without an explicit width/height it renders at the browser's default
   replaced-element size (a check mark 150px tall). Every icon-bearing component gets a fixed
   size here; matching width/height attributes on the SVGs themselves hold the size before
   sa.css loads. */
.check-list li svg, .rule-row .row-meta svg, .text-link svg, .hairline-grid .cell-title svg, .icon-btn svg, .faq summary svg, .btn svg {
  width: 18px; height: 18px; flex: 0 0 auto;
}

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: 52px; padding: 0 var(--s6); border-radius: var(--r-pill);
  border: 1px solid transparent; font-size: 15px; font-weight: var(--w-btn); letter-spacing: -.005em; line-height: 1;
  white-space: nowrap; cursor: pointer;
  transition: background-color var(--t-ui) ease, color var(--t-ui) ease, border-color var(--t-ui) ease, transform var(--t-micro) ease;
}
.btn:active { transform: scale(.97); }
.btn-primary { background: var(--sunset); color: var(--night); border-color: var(--sunset); }
@media (hover: hover) { .btn-primary:hover { background: color-mix(in srgb, var(--sunset) 86%, var(--night)); border-color: color-mix(in srgb, var(--sunset) 86%, var(--night)); } }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--hairline-strong); }
@media (hover: hover) { .btn-ghost:hover { border-color: var(--ink); } }
.btn-sm { min-height: 44px; padding: 0 var(--s5); font-size: 14px; }
/* .btn-block is width:100%, so .btn's white-space: nowrap can only ever push its container wider
   than the box it is supposed to fill. The hero submit label is city-specific and reaches 31
   characters on four city pages ("Show me my Lee's Summit numbers"); that nowrap min-content of
   311px propagated up through .form-card (353px) into the .hero-grid track and made the whole page
   13px wider than a 360px viewport -- a horizontal drag on every phone. A full-width button should
   wrap instead. Single-line labels are unchanged: .btn's min-height still governs their height. */
.btn-block { width: 100%; white-space: normal; line-height: 1.25; padding-block: var(--s3); text-wrap: balance; }
.btn[disabled] { opacity: .7; cursor: default; }
.btn-spinner { width: 14px; height: 14px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: spin .8s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
@media (max-width: 640px) { .btn-block-mobile { width: 100%; } .btn:not(.btn-sm) { min-height: 54px; } }

.text-link { display: inline-flex; align-items: center; gap: 8px; min-height: 28px; color: var(--link); font-weight: var(--w-ui); text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); text-underline-offset: .22em; text-decoration-thickness: 1px; transition: color var(--t-ui) ease, text-decoration-color var(--t-ui) ease; }
.text-link svg { flex: 0 0 auto; transition: transform var(--t-ui) var(--ease-out); }
@media (hover: hover) { .text-link:hover { text-decoration-color: currentColor; } .text-link:hover svg { transform: translateX(3px); } }
.call-line { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; color: var(--ink-muted); font-size: var(--fs-small); font-weight: var(--w-ui); }
.hero-centered .call-line { justify-content: center; }
.call-line a { color: var(--ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); text-underline-offset: .2em; }
@media (hover: hover) { .call-line a:hover { color: var(--link); text-decoration-color: currentColor; } }
.call-big { font-size: clamp(1.5rem, 1.1rem + 1.6vw, 1.9rem); font-weight: var(--w-display); letter-spacing: -.02em; color: var(--ink); }
.icon-btn { touch-action: manipulation; display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: var(--r-pill); border: 1px solid var(--hairline-strong); color: var(--ink); background: transparent; transition: border-color var(--t-ui) ease, background var(--t-ui) ease; }
.icon-btn:active { transform: scale(.96); }
@media (hover: hover) { .icon-btn:hover { border-color: var(--ink); } }

/* ----------------------------------------------------------------------------------------
   Header
   ---------------------------------------------------------------------------------------- */
.site-header { position: sticky; top: 0; z-index: 40; height: var(--header-h); background: color-mix(in srgb, var(--canvas) 92%, transparent); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border-bottom: 1px solid var(--hairline); }
.site-header-inner { display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--s6); height: 100%; }
.brand { display: inline-flex; align-items: center; gap: 12px; width: max-content; }
.brand-mark { display: block; width: 34px; height: 34px; flex: 0 0 auto; }
.brand-name { display: flex; flex-direction: column; line-height: 1.05; }
.brand-name-main { font-size: 1rem; font-weight: var(--w-display); letter-spacing: -.02em; color: var(--ink); }
.brand-name-sub { margin-top: 2px; color: var(--eyebrow); font-size: 10px; font-weight: var(--w-btn); letter-spacing: var(--track-label); text-transform: uppercase; }
.site-nav { display: flex; align-items: center; justify-content: center; gap: var(--s8); font-size: 15px; font-weight: var(--w-ui); }
.site-nav > a { position: relative; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; color: var(--ink); transition: color var(--t-ui) ease; }
/* D5 nav underline: scales in from the left on hover/focus; current page stays underlined. */
.site-nav > a::after { content: ""; position: absolute; left: 0; right: 0; bottom: 10px; height: 1.5px; background: var(--sunset); transform: scaleX(0); transform-origin: left; transition: transform var(--t-m-micro) var(--ease-out); }
.site-nav > a:hover::after, .site-nav > a:focus-visible::after, .site-nav > a[aria-current="page"]::after { transform: scaleX(1); }
@media (hover: hover) { .site-nav > a:hover { color: var(--link); } }
.header-actions { display: flex; align-items: center; justify-self: end; gap: var(--s5); }
.header-phone { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-size: 14px; font-weight: var(--w-ui); color: var(--ink); white-space: nowrap; }
.header-phone svg { width: 16px; height: 16px; flex: 0 0 auto; }
@media (hover: hover) { .header-phone:hover { color: var(--link); } }
.header-mobile { display: none; align-items: center; gap: var(--s2); }
@media (max-width: 1024px) {
  .site-nav { display: none; }
  .site-header-inner { grid-template-columns: auto 1fr; }
  .header-actions .header-phone { display: none; }
}
@media (max-width: 760px) {
  .header-actions > .btn { display: none; }
  .header-mobile { display: flex; }
}
@media (max-width: 400px) { .brand-name-main { font-size: .9rem; } }
/* M7: sa.js toggles data-hide after 80px of downward scroll, clears it on scroll up. */
@media (max-width: 640px) { .site-header { transition: transform 240ms var(--ease-out); } .site-header[data-hide="true"] { transform: translateY(-100%); } }

/* Mobile menu */
.mobile-menu { position: fixed; inset: 0; height: 100dvh; z-index: 60; display: grid; grid-template-rows: auto 1fr auto; background: var(--night); color: var(--paper); overscroll-behavior: contain; overflow: hidden; }
.mobile-menu[hidden] { display: none; }
.mobile-menu-top { display: flex; align-items: center; justify-content: space-between; height: var(--header-h); padding: 0 var(--gutter); border-bottom: 1px solid rgba(255, 251, 244, .16); }
.mobile-menu-body { overflow-y: auto; padding: var(--s6) var(--gutter); }
.mobile-menu-body a { display: grid; grid-template-columns: 1fr; align-items: center; min-height: 56px; font-family: var(--font-sans); font-size: 1.375rem; font-weight: var(--w-display); letter-spacing: -.02em; color: var(--paper); border-bottom: 1px solid rgba(255, 251, 244, .12); }
.mobile-menu-body a:active { color: var(--amber); }
.mobile-menu-bottom { display: grid; gap: var(--s3); padding: var(--s4) var(--gutter) calc(var(--s4) + env(safe-area-inset-bottom)); border-top: 1px solid rgba(255, 251, 244, .16); background: var(--night-deep); }
.mobile-menu-bottom .row { display: flex; justify-content: space-between; align-items: center; font-size: var(--fs-small); color: rgba(255, 251, 244, .72); }
.mobile-menu-bottom .row a { min-height: 44px; display: inline-flex; align-items: center; color: var(--paper); }
.mobile-menu .brand-name-main { color: var(--paper); }
.mobile-menu .icon-btn { color: var(--paper); border-color: rgba(255, 251, 244, .32); }
.mobile-menu-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
  /* Ported from a named keyframe animation to a starting-style transition so the sitewide
     keyframe allowlist (docs/operators/motion-and-mobile-2026-09-09.md) can stay exactly
     spin/sa-island-in/sa-sheet-in -- same 210ms fade-and-rise-in, driven by the browser's
     built-in before-first-paint starting style instead of a named animation. Browsers lacking
     starting-style support just show the menu without the entrance motion (menu.hidden is still
     toggled by sa.js either way). */
  .mobile-menu:not([hidden]) { transition: opacity 210ms var(--ease-out), transform 210ms var(--ease-out); }
  @starting-style { .mobile-menu:not([hidden]) { opacity: 0; transform: translateY(-8px); } }
}

/* ----------------------------------------------------------------------------------------
   Footer
   ---------------------------------------------------------------------------------------- */
.site-footer { padding: var(--s16) 0 var(--s6); }
.footer-top { display: grid; grid-template-columns: 1.2fr 2fr; gap: var(--s10) var(--s16); padding-bottom: var(--s10); border-bottom: 1px solid var(--hairline); }
.footer-top .brand-name-main { color: var(--paper); }
.footer-lines { display: grid; gap: var(--s2); margin-top: var(--s5); color: var(--ink-muted); font-size: var(--fs-small); }
.footer-lines a { color: var(--paper); }
.footer-cols { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s8); }
.footer-col { display: grid; align-content: start; gap: 2px; }
.footer-col .mono { color: var(--eyebrow); margin-bottom: var(--s2); font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); text-transform: uppercase; }
.footer-col a { display: inline-flex; align-items: center; min-height: 36px; color: rgba(255, 251, 244, .78); font-size: 15px; transition: color var(--t-ui) ease; }
@media (hover: hover) { .footer-col a:hover { color: var(--paper); } }
.footer-bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s3) var(--s6); padding-top: var(--s5); color: var(--ink-muted); font-size: var(--fs-small); }
.footer-disclosures { padding-top: var(--s8); margin-top: var(--s2); border-top: 1px solid var(--hairline); }
.footer-disclosures p { color: var(--ink-muted); font-size: 12.5px; line-height: 1.7; max-width: none; }
.footer-disclosures a { color: rgba(255, 251, 244, .78); text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); text-underline-offset: .2em; }
@media (hover: hover) { .footer-disclosures a:hover { color: var(--paper); } }
@media (max-width: 900px) { .footer-top { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .footer-cols { grid-template-columns: 1fr 1fr; } .footer-col:last-child { grid-column: 1 / -1; } .footer-col a { min-height: 44px; } .site-footer { padding-top: var(--s12); } }

/* ----------------------------------------------------------------------------------------
   Heroes
   ---------------------------------------------------------------------------------------- */
.hero { padding-block: var(--s16) var(--s18); }
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: var(--s12) var(--s16); align-items: center; }
/* .hero-form pairs a short copy column against a tall form card; centering them vertically
   (as .hero-grid does) leaves the headline stranded low in the band, so it aligns to the top
   instead and nudges the copy down slightly to clear the form card's top edge visually. */
.hero-form { display: block; }
/* Round 2 fix: the align-items:start above lives on the <section class="hero-form">, but the
   actual grid the copy column and form card sit in is the inner .hero-grid, which still
   defaulted to center. Target it directly so the headline starts at the top of the band. */
.hero-form .hero-grid { align-items: start; }
.hero-form .hero-copy { padding-top: var(--s8); }
.hero-copy { display: grid; gap: var(--s5); }
.hero-copy .display { max-width: 16ch; }
.hero-copy .h1-inner { max-width: 18ch; }
.hero-copy .lede { max-width: 44ch; }
.hero-figure { min-width: 0; }
.hero-single { padding-block: var(--s16) var(--s18); }
.hero-single .hero-copy { max-width: 640px; }
.hero-single .hero-copy .display, .hero-single .hero-copy .h1-inner { max-width: 20ch; }
@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; gap: var(--s10); }
  .hero-form .hero-copy { padding-top: 0; }
  .hero { padding-block: var(--s10) var(--s12); }
}
@media (max-width: 640px) {
  .hero { padding-block: var(--s8) var(--s10); }
  .hero-single { padding-block: var(--s8) var(--s10); }
  .hero-copy { gap: var(--s4); }
  .hero-copy .display { max-width: none; }
}

.hero-footnote { margin-top: var(--s10); max-width: 980px; }
/* D2 hero reveal: sa.js adds sa-hero-in then, next frame, is-in -- runs once on load only. */
.sa-hero-in { opacity: 0; transform: translateY(12px); transition: opacity 500ms var(--ease-out), transform 500ms var(--ease-out); transition-delay: calc(var(--i, 0) * var(--t-m-stagger)); }
.sa-hero-in.is-in { opacity: 1; transform: none; }

/* D4 footnote popovers: desktop shows on hover/focus as a small popup; phones (tap focuses the
   button, same trigger) get a bottom sheet. sa-sheet-in is the one other keyframe the sitewide
   allowlist reserves, used here since the sheet must animate in from a display:none-equivalent
   collapsed state on every open, not just a first paint (a transition would need
   allow-discrete/@starting-style wired through every re-open, which is far more fragile to get
   right without a browser to check it in). */
.sa-fn-wrap { position: relative; display: inline-block; }
.sa-fn { display: inline-flex; min-width: 1.4em; height: 1.4em; align-items: center; justify-content: center; vertical-align: super; font-size: .32em; line-height: 1; color: var(--sunset-deep); }
/* Colours set explicitly rather than left to inherit through the band: --ink itself is
   redefined to var(--paper) inside [data-band="night"]/[data-band="deep"] (see the band
   inversions above), so a popover living in a dark-band hero that just wrote "color: var(--ink)"
   rendered var(--paper) text on its own var(--paper) background -- invisible. Light bands (the
   default, paper/cream) keep --ink on --paper; dark bands get an explicit override to --paper
   on --night-panel instead of whatever --ink currently resolves to. Applies to both the desktop
   popover and the phone bottom sheet below (same element, repositioned only). */
.sa-fn-pop { position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%); margin-bottom: 6px; width: max-content; max-width: 280px; padding: var(--s3); background: var(--paper); color: var(--ink); border: 1px solid var(--hairline-strong); border-radius: var(--r-inner); font-size: 13px; font-weight: 400; text-align: left; opacity: 0; visibility: hidden; pointer-events: none; transition: opacity var(--t-ui) ease, visibility 0s var(--t-ui); z-index: 30; }
[data-band="night"] .sa-fn-pop, [data-band="deep"] .sa-fn-pop { background: var(--night-panel); color: var(--paper); border-color: var(--hairline-strong); }
.sa-fn-wrap:hover .sa-fn-pop, .sa-fn-wrap:focus-within .sa-fn-pop, .sa-fn-pop:hover { opacity: 1; visibility: visible; pointer-events: auto; transition-delay: 0s; }
.sa-fn-close { display: none; }
@media (max-width: 640px) {
  .sa-fn-pop { position: fixed; inset: auto 0 0 0; transform: none; margin: 0; max-width: none; width: auto; border-radius: 24px 24px 0 0; padding: var(--s6); }
  @media (prefers-reduced-motion: no-preference) { .sa-fn-wrap:focus-within .sa-fn-pop { animation: sa-sheet-in 320ms var(--ease-spring); } }
  @keyframes sa-sheet-in { from { transform: translateY(100%); } to { transform: translateY(0); } }
  .sa-fn-close { display: block; margin-top: var(--s4); min-height: 44px; }
}

/* Breadcrumb: sits at the top of a hero band. Solar Assure addition. */
.breadcrumb { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: var(--s5); color: var(--ink-muted); font-size: var(--fs-small); }
.breadcrumb a { color: var(--ink-muted); text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); text-underline-offset: .2em; }
@media (hover: hover) { .breadcrumb a:hover { color: var(--ink); } }
.breadcrumb-sep { opacity: .6; }

/* ----------------------------------------------------------------------------------------
   Rule rows (ledgers), chips, steps, FAQ, timeline, tiles
   ---------------------------------------------------------------------------------------- */
.rule-list, .timeline { border-top: 1px solid var(--hairline); }
/* A .rule-list with no .row-body anywhere is a label/value spec table, not a full-bleed row list.
   At container width the value ends up ~1,000px from the label it belongs to, which is what made
   /locations read as four numbers floating in space. Capping the measure keeps each pair legible.
   Link lists always carry a .row-body, so the sitewide "related guides" rows are untouched. */
.rule-list:not(:has(.row-body)):not(:has(> a.rule-row)) { max-width: min(100%, 820px); }
.rule-row { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: var(--s4) var(--s5); min-height: 84px; padding: var(--s4) 0; border-bottom: 1px solid var(--hairline); color: inherit; }
.rule-row .row-main { display: grid; grid-template-columns: minmax(12ch, 1fr) minmax(0, 1.6fr); gap: var(--s2) var(--s8); align-items: start; min-width: 0; }
.rule-row .row-main:not(:has(.row-body)) { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) {
  /* Fix round 3 item 3: the outer .rule-row grid itself stayed a fixed 2-column
     (minmax(0,1fr) auto) track at every width -- only .row-main's *inner* columns collapsed
     here, so .row-meta (an outer-grid sibling of .row-main, not a child of it) kept sharing
     row-main's own grid row instead of dropping to a new one under it, for every plain
     div.rule-row (neighborhood rows, step rows) that isn't wrapped in the M8 snap-card rule
     below. Collapsing the outer grid to one column too removes the ambiguity outright: with a
     single track, row-main and row-meta each get their own row, meta full width beneath the
     body, left-aligned. */
  .rule-row { grid-template-columns: minmax(0, 1fr); }
  .rule-row .row-main { grid-template-columns: minmax(0, 1fr); }
  .rule-row .row-meta { grid-column: 1 / -1; justify-content: flex-start; text-align: left; max-width: none; }
}
.rule-row .row-title { font-size: 1.125rem; font-weight: var(--w-h3); letter-spacing: -.01em; line-height: 1.35; }
.rule-row .row-title .eyebrow { display: block; margin-bottom: 4px; }
.rule-row .row-body { color: var(--ink-muted); font-size: 15px; line-height: 1.55; max-width: 60ch; }
.rule-row .row-body .check-list { margin-top: var(--s3); }
.rule-row .row-meta { display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--s3); max-width: 26ch; text-align: right; color: var(--ink-muted); }
/* The @media (max-width: 900px) block further up already asks for max-width:none here, but it sits
   EARLIER in the file than this base rule and has identical specificity, so it always lost -- the
   phone layout has been silently capped since the meta column was written. Re-assert it after the
   base rule so the single-column phone row really does get the full width. */
@media (max-width: 900px) { .rule-row .row-meta { max-width: none; } }
.rule-row .row-meta svg { color: var(--ink); transition: transform var(--t-ui) var(--ease-out); }
a.rule-row::before { content: ""; position: absolute; left: -14px; top: var(--s4); bottom: var(--s4); width: 3px; border-radius: 2px; background: var(--sunset); transform: scaleY(0); transform-origin: top; transition: transform var(--t-ui) ease; }
a.rule-row .row-main { transition: transform var(--t-ui) var(--ease-out); }
@media (hover: hover) {
  a.rule-row:hover::before { transform: scaleY(1); }
  a.rule-row:hover .row-main { transform: translateX(6px); }
  a.rule-row:hover .row-title { color: var(--link); }
  a.rule-row:hover .row-meta svg { transform: translate(2px, -2px); }
}
a.rule-row:active .row-main { transform: translateX(3px); }
.rule-list + .closing, .faq + .closing { margin-top: var(--s16); }
.check-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s10); border-top: 1px solid var(--hairline); }
.check-list[data-cols="1"] { grid-template-columns: 1fr; }
.check-list li { display: flex; align-items: flex-start; gap: var(--s3); min-height: 56px; padding: var(--s3) 0; border-bottom: 1px solid var(--hairline); font-size: 15px; }
.check-list li svg { flex: 0 0 auto; margin-top: 3px; color: var(--ink); }
@media (max-width: 640px) { .rule-row { min-height: 72px; } .check-list { grid-template-columns: 1fr; } }

/* M8 snap rows, phones only: any .rule-list made of link rows (every sitewide "related
   city"/"related guide" cross-link list uses a.rule-row, and only those do -- no new hook
   needed) becomes a horizontal scroll-snap strip of note-style cards. Desktop is untouched. */
@media (max-width: 640px) {
  .rule-list:has(> a.rule-row) { display: flex; gap: var(--s4); overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); border-top: 0; margin-inline: calc(var(--gutter) * -1); padding: 0 var(--gutter) var(--s2); }
  .rule-list:has(> a.rule-row) > a.rule-row { flex: 0 0 78vw; scroll-snap-align: start; min-height: 0; background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); padding: var(--s5); }
  .rule-list:has(> a.rule-row) > a.rule-row::before { content: none; }
  /* (c) snap cards: row-main/row-meta already stack via the 900px rule above (640px is
     inside that range); the arrow just needs pulling out of the meta text flow to the
     card's top-right corner instead of trailing the meta line. */
  .rule-list:has(> a.rule-row) > a.rule-row .row-meta svg { position: absolute; top: var(--s5); right: var(--s5); }
}

.chip-row { display: flex; flex-wrap: wrap; gap: var(--s2); }
.chip { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 14px; border-radius: var(--r-pill); border: 1px solid var(--hairline-strong); background: var(--surface); color: var(--ink); font-size: 14px; font-weight: var(--w-ui); }
.chip-static { min-height: 36px; background: transparent; font-weight: 500; }
label.chip { position: relative; cursor: pointer; min-height: 44px; transition: background var(--t-ui) ease, color var(--t-ui) ease, border-color var(--t-ui) ease; }
label.chip:has(input:checked) { background: var(--night); color: var(--paper); border-color: var(--night); }
label.chip:has(input:focus-visible) { outline: 2px solid var(--focus); outline-offset: 3px; }
label.chip:active { transform: scale(.97); }

/* M2 sliding pill chips: sa.js inserts .sa-chip-hl as the first child of any [data-chips]
   container and slides/resizes it (transform + width/height) behind the checked radio's label,
   measured from that label's box. Falls back to the plain per-label :has(input:checked) styling
   above with no JS. First paint sets the highlight's position with no transition (sa.js adds
   .sa-chips-live only after the first paint), so there is nothing to animate on load. */
[data-chips] { position: relative; }
[data-chips] > label { position: relative; z-index: 1; }
.sa-chip-hl { position: absolute; left: 0; top: 0; z-index: 0; pointer-events: none; opacity: 0; background: var(--ink); border-radius: var(--r-pill); }
[data-chips].sa-chips-live .sa-chip-hl { transition: transform var(--t-m-medium) var(--ease-spring), width var(--t-m-medium) var(--ease-spring), height var(--t-m-medium) var(--ease-spring); }
[data-chips].sa-chips-live label.chip:has(input:checked) { background: transparent; }
[data-chips="surface"] .sa-chip-hl { background: color-mix(in srgb, var(--sunset) 8%, var(--white)); border: 1px solid var(--sunset-deep); border-radius: var(--r-surface); }
[data-chips="surface"].sa-chips-live .batt-option.selected { border-color: transparent; }

.faq { border-top: 1px solid var(--hairline); }
.faq details { border-bottom: 1px solid var(--hairline); }
.faq summary { display: flex; justify-content: space-between; align-items: center; gap: var(--s6); min-height: 64px; padding: var(--s3) 0; cursor: pointer; list-style: none; font-size: 1.0625rem; font-weight: var(--w-h3); letter-spacing: -.01em; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary .faq-icon { flex: 0 0 auto; position: relative; width: 20px; height: 20px; color: var(--ink); }
.faq summary .faq-icon span { position: absolute; inset: 0; margin: auto; background: currentColor; border-radius: 1px; }
.faq summary .faq-icon .bar-v { width: 2px; height: 14px; transition: opacity var(--t-ui) ease; }
.faq summary .faq-icon .bar-h { width: 14px; height: 2px; }
.faq details[open] summary .faq-icon .bar-v { opacity: 0; }
/* Fix round 3 item 7: (hover: hover) alone still reads true on many touch/hybrid devices (and on
   a desktop browser emulating a phone width, which is how the review caught this), so a tap that
   opens/closes the accordion can leave the :hover style visually "stuck" on the label with no
   real mouse there to move away and clear it -- looks like the accent colour never resets on
   close. Adding pointer:fine restricts the hover accent to genuinely precise pointer devices
   (mouse/trackpad), matching what (hover:hover) alone was meant to do. */
@media (hover: hover) and (pointer: fine) { .faq summary:hover { color: var(--link); } }
.faq details > div { padding: 0 var(--s10) var(--s5) 0; color: var(--ink-muted); max-width: 62ch; }
.faq-intro { margin-bottom: var(--s6); color: var(--ink-muted); }

.tiles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }
.tile { display: grid; gap: var(--s2); align-content: start; padding: var(--s5); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); color: inherit; transition: border-color var(--t-ui) ease, transform var(--t-ui) var(--ease-out); }
.tile .tile-title { display: flex; justify-content: space-between; align-items: center; gap: var(--s3); font-weight: var(--w-h3); font-size: 1.0625rem; }
.tile p { color: var(--ink-muted); font-size: 15px; }
@media (hover: hover) { .tile:hover { border-color: var(--ink); } }
.tile:active { transform: scale(.985); }
@media (max-width: 760px) { .tiles { grid-template-columns: 1fr; } }

/* ----------------------------------------------------------------------------------------
   Table. Solar Assure addition. Full width, hairline rows, no zebra, no cell borders.
   ---------------------------------------------------------------------------------------- */
.table-wrap { overflow-x: auto; border-top: 1px solid var(--hairline); }
.table { width: 100%; min-width: 480px; border-collapse: collapse; font-size: 15px; }
.table th, .table td { text-align: left; padding: var(--s3) var(--s5) var(--s3) 0; border-bottom: 1px solid var(--hairline); }
.table th { font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-muted); }
.table td { color: var(--ink); }
.table td.num, .table th.num, .table td.mono, .table th.mono { font-variant-numeric: tabular-nums; }
.table tr > :last-child { padding-right: 0; }
/* D6 long-table comfort: sticky header on desktop, row hover, first column stays on one line. */
.table th:first-child, .table td:first-child { white-space: nowrap; }
@media (min-width: 1025px) { .table th { position: sticky; top: var(--header-h); background: var(--canvas); } }
@media (hover: hover) {
  .table tbody tr:hover { background: var(--cream); }
  [data-band="cream"] .table tbody tr:hover { background: var(--paper); }
}

/* Note: framed callout / disclaimer / landmark panel. Solar Assure addition. No icon. */
.note { display: grid; gap: var(--s3); padding: var(--s6); background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); }
.note .eyebrow { margin-bottom: 0; }
.note-title { font-size: 1.0625rem; font-weight: var(--w-h3); letter-spacing: -.01em; }
.note p { color: var(--ink-muted); font-size: 15px; line-height: 1.55; }
.note p + p { margin-top: var(--s2); }
.note ul { display: grid; gap: var(--s2); padding-left: 1.1em; list-style: disc; color: var(--ink-muted); font-size: 15px; line-height: 1.55; }

/* Author block. Solar Assure addition. */
.author { display: flex; align-items: center; gap: var(--s4); padding-top: var(--s6); margin-top: var(--s2); border-top: 1px solid var(--hairline); }
.author img { width: 56px; height: 56px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
.author-name { font-weight: var(--w-h3); font-size: 15px; }
.author-role { color: var(--ink-muted); font-size: 14px; }
.author-updated { display: block; margin-top: 2px; }

/* ----------------------------------------------------------------------------------------
   Closing band
   ---------------------------------------------------------------------------------------- */
.closing { display: grid; gap: var(--s5); max-width: 760px; }
.closing .h2 { max-width: 20ch; }
.closing .lede { color: var(--ink-muted); }
.closing-lines { margin-top: var(--s5); padding-top: var(--s5); border-top: 1px solid var(--hairline); color: var(--ink-muted); font-size: var(--fs-small); }
.closing-lines a { color: var(--ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); text-underline-offset: .2em; }
@media (hover: hover) { .closing-lines a:hover { color: var(--ink); } }
/* Phone spacing pass (docs/operators, fix round 2 item 4): the closing band's primary + ghost
   pair used the sitewide .actions flex-wrap, which lets two pills sit side by side down to their
   content width instead of stacking. Scoped to .closing only -- other .actions groups (hero,
   FAQ) are unaffected. */
@media (max-width: 640px) {
  .closing .actions { flex-direction: column; align-items: stretch; }
  .closing .actions .btn { width: 100%; }
}

/* ----------------------------------------------------------------------------------------
   Forms
   ---------------------------------------------------------------------------------------- */
.form-card { display: grid; gap: var(--s5); padding: var(--s8); background: var(--white); color: var(--ink); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); --ink: #0A0F1A; --ink-muted: var(--muted); --hairline: color-mix(in oklab, var(--night) 14%, var(--white)); --hairline-strong: color-mix(in oklab, var(--night) 30%, var(--white)); --focus: var(--sunset-deep); --link: var(--sunset-deep); --surface: var(--white); }
.form-card > .h3, .form-card > h2 { max-width: none; }
.form-card > .help { margin-top: calc(-1 * var(--s3)); }
.form-card-head { display: flex; justify-content: space-between; align-items: flex-start; gap: var(--s3); }
.form-card-head .h3 { margin: 0; }
.form-card-head .mono { text-transform: none; letter-spacing: 0; white-space: nowrap; }
.lead-form { display: grid; gap: var(--s5); }
.form-alert { padding: var(--s4); border: 1px solid var(--sunset-deep); border-radius: var(--r-inner); background: color-mix(in srgb, var(--sunset) 8%, var(--white)); color: var(--ink); display: grid; gap: var(--s2); }
.form-alert a { text-decoration: underline; font-weight: var(--w-ui); }
.field { display: grid; gap: var(--s2); }
.field > label, .field > legend { font-size: 14px; font-weight: var(--w-ui); }
.field legend { padding: 0; margin-bottom: var(--s2); }
fieldset.field { border: 0; padding: 0; margin: 0; min-width: 0; }
.input { min-height: 52px; padding: 0 14px; font-size: 16px; color: var(--ink); background: var(--white); border: 1px solid var(--hairline-strong); border-radius: var(--r-inner); width: 100%; transition: border-color var(--t-ui) ease; }
textarea.input { min-height: 96px; padding: 12px 14px; resize: vertical; }
.input::placeholder { color: color-mix(in srgb, var(--muted) 70%, transparent); }
.input:focus-visible { border-color: var(--sunset-deep); outline-offset: 1px; }
.field-invalid .input { border-color: var(--sunset-deep); }
.help { font-size: 14px; color: var(--muted); }
.error { font-size: 14px; font-weight: var(--w-ui); color: var(--ink); }
.consent { font-size: 13px; color: var(--muted); max-width: var(--measure); }
.consent a { text-decoration: underline; }
.honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
/* M6 progressive form: sa.js hides step-2 fields with [hidden] + strips required until shown.
   starting-style covers the [hidden]->shown jump (same technique as the mobile menu). Fix round
   3 item 5 root cause: .field (and fieldset.field) sets its own "display" below, and an AUTHOR
   stylesheet rule always beats the user-agent stylesheet's [hidden]{display:none} for the same
   property, regardless of specificity or source order -- so on the name/phone/email .field divs
   the hidden attribute was doing nothing at all; they stayed display:grid and fully visible. The
   .mobile-menu[hidden] rule below already carries the identical fix for the same reason; this is
   that same pattern applied to every step-2 element (.sa-p2 covers .field divs and the plain
   <p class="help"/consent"> rows alike, so one rule handles all of them). */
@media (max-width: 640px) {
  .sa-p2 { transition: transform 450ms var(--ease-spring), opacity 450ms var(--ease-spring); transition-delay: calc(var(--i, 0) * var(--t-m-stagger)); }
  .sa-p2[hidden] { display: none; }
  @starting-style { .sa-p2:not([hidden]) { opacity: 0; transform: scale(1.2) translateY(15px); } }
}
/* M5 slider feel: accent-color keeps the native sunset-filled-left/hairline-right track (a
   gradient-free fill is not otherwise achievable without JS); only the thumb is fully custom.
   height:44px grows the vertical hit area without changing the 28px visual thumb. */
input[type="range"] { width: 100%; accent-color: var(--sunset); height: 44px; cursor: pointer; }
input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 28px; height: 28px; border-radius: 50%; background: var(--paper); border: 6px solid var(--ink); transition: transform var(--t-m-micro) var(--ease-out); }
input[type="range"]::-moz-range-thumb { width: 28px; height: 28px; border-radius: 50%; background: var(--paper); border: 6px solid var(--ink); transition: transform var(--t-m-micro) var(--ease-out); }
input[type="range"]::-moz-range-track { height: 4px; background: var(--hairline-strong); border-radius: 2px; }
input[type="range"]::-moz-range-progress { height: 4px; background: var(--sunset); border-radius: 2px; }
input[type="range"]:active::-webkit-slider-thumb, input[type="range"]:active::-moz-range-thumb { transform: scale(1.08); }
.field:has(> input[type="range"]) { position: relative; }
.sa-slider-bubble { position: absolute; bottom: 100%; transform: translateX(-50%); margin-bottom: var(--s2); padding: 4px 10px; border-radius: var(--r-pill); background: var(--night); color: var(--paper); font-size: 13px; font-weight: var(--w-ui); white-space: nowrap; pointer-events: none; z-index: 2; }
@media (min-width: 641px) { .sa-slider-bubble { display: none; } }
.slider-ticks { display: flex; justify-content: space-between; margin-top: var(--s2); }
@media (max-width: 640px) { .form-card { padding: var(--s5); } }

/* ----------------------------------------------------------------------------------------
   M1 scroll island (replaces the old two-button sticky bar; #stickyBar id and the
   data-visible show/hide -- appear once the hero CTA scrolls off, hide over forms/closing
   band/while typing -- are unchanged, driven by the same sa.js block as before). Collapsed:
   a 56px pill. data-open="true": sa.js measures the list and sets --island-h, which this
   transitions to alongside width/border-radius -- "measured pixels", not an auto/guessed cap.
   ---------------------------------------------------------------------------------------- */
.sa-island { position: fixed; left: 50%; bottom: calc(14px + env(safe-area-inset-bottom)); z-index: 50; transform: translate(-50%, 130%); transition: transform 250ms var(--ease-out); }
.sa-island[data-visible="true"] { transform: translate(-50%, 0); }
@media (min-width: 901px) { .sa-island { display: none; } }
.sa-island-backdrop { position: fixed; inset: 0; background: rgba(11, 20, 36, .4); opacity: 0; pointer-events: none; transition: opacity var(--t-m-medium) var(--ease-out); z-index: -1; }
.sa-island[data-open="true"] .sa-island-backdrop { opacity: 1; pointer-events: auto; }
.sa-island-panel { width: min(92vw, 252px); height: 56px; border-radius: var(--r-pill); background: var(--night); color: var(--paper); box-shadow: var(--shadow-float); overflow: hidden; transition: width var(--t-m-large) var(--ease-spring), height var(--t-m-large) var(--ease-spring), border-radius var(--t-m-large) var(--ease-spring); }
.sa-island[data-open="true"] .sa-island-panel { width: min(92vw, 420px); height: var(--island-h, 56px); border-radius: 24px; }
.sa-island-bar { display: flex; align-items: center; gap: var(--s2); height: 56px; padding: 0 var(--s2) 0 var(--s4); }
.sa-island-open { display: flex; align-items: center; gap: var(--s2); flex: 1; min-width: 0; color: var(--paper); font-size: 13px; font-weight: var(--w-ui); }
.sa-island-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sa-island-ring { flex: 0 0 auto; }
.sa-island-ring-fill { transition: stroke-dashoffset var(--t-ui) linear; }
.sa-island-call { flex: 0 0 auto; border-color: rgba(255, 251, 244, .32); color: var(--paper); }
.sa-island-cta { flex: 0 0 auto; min-height: 40px; padding: 0 var(--s5); }
/* Josh asked for the quote button to stay on screen on mobile, so the collapsed pill keeps the
   progress ring, the call button and "Free Quote"; only the label is dropped, because it is the
   one item that will not fit at 252px and the sticky header already carries the brand. Anything
   added to .sa-island-bar from here must either fit inside that 252px or be hidden until
   [data-open="true"], or overflow:hidden will clip it into the pill the way it used to. */
.sa-island-label { display: none; }
.sa-island[data-open="true"] .sa-island-label { display: block; }
.sa-island-list { max-height: calc(var(--island-h, 56px) - 56px); overflow-y: auto; padding: 0 var(--s3) var(--s4); }
.sa-island-list a { display: block; padding: var(--s3); border-radius: var(--r-inner); color: var(--paper); font-size: 14px; opacity: 0; transform: translateY(4px); transition: opacity var(--t-m-micro) var(--ease-out), transform var(--t-m-micro) var(--ease-out), background var(--t-ui) ease; transition-delay: calc(var(--i, 0) * 40ms); }
.sa-island[data-open="true"] .sa-island-list a { opacity: 1; transform: none; }
@media (hover: hover) { .sa-island-list a:hover { background: var(--night-panel); } }

/* ----------------------------------------------------------------------------------------
   Figure (TA's illo-frame, renamed). Adapts automatically via --surface/--ink per band.
   ---------------------------------------------------------------------------------------- */
.figure { display: grid; gap: var(--s3); padding: var(--s5); background: var(--surface); color: var(--ink); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); }
.figure img, .figure video { width: 100%; height: auto; align-self: start; border-radius: var(--r-inner); }
.figure figcaption { color: var(--ink-muted); }
.figure > svg { width: 100%; height: auto; }
/* Small decorative illustrations (the five city-page sun diagrams: 220-260 unit viewBoxes, drawn for a
   ~240px slot on the legacy site). The frame is capped so the fluid SVG above reads near its designed
   size instead of stretching to the full prose measure; on phones the cap never binds. */
.figure-illo { max-width: 24rem; }
/* Round 2 fix: the review doc's prescribed selector was ".founders-grid .figure img", but the
   founders portraits use a .figure-photo class directly on the <img> (see build log entry 2
   under Stage 1) rather than that descendant selector, so no element named "founders-grid"
   exists to match. Applying the same width/height/aspect-ratio/object-position values to the
   actual .figure-photo class produces the identical fix without adding a new wrapper class. */
.figure-photo { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; object-position: center top; }
#founders .grid-2 { gap: var(--s5); }

/* Rate chart (homepage). Data-viz colours only: rise, calm, gold; text stays ink. */
.chart-svg { width: 100%; height: auto; }
.chart-axis-line { stroke: var(--hairline); stroke-width: 1; }
/* The chart-svg scales down from its viewBox (1000 wide) to fit the .figure column, so an
   SVG-unit font-size reads noticeably smaller on screen than the same CSS px value would --
   these are sized up accordingly to read at roughly 11px actual once scaled. */
.chart-axis-label { font-family: var(--font-mono); font-size: 16px; fill: var(--ink-muted); }
.chart-line { fill: none; stroke-width: 3; stroke-linecap: round; }
.chart-line-utility { stroke: var(--rise); }
.chart-line-solar { stroke: var(--calm); }
.chart-area-utility { fill: url(#utilityGrad); }
.chart-area-solar { fill: url(#solarGrad); }
.chart-area-gap { fill: url(#gapGrad); }
.chart-dot { stroke-width: 2; fill: var(--surface); }
.chart-dot.dot-utility { stroke: var(--rise); }
.chart-dot.dot-solar { stroke: var(--calm); }
.chart-end-marker { font-family: var(--font-mono); font-size: 17px; font-weight: 500; }
.chart-end-marker.utility { fill: var(--rise); }
.chart-end-marker.solar { fill: var(--calm); }
.chart-gap-label { font-family: var(--font-mono); font-size: 15px; letter-spacing: .12em; fill: var(--sunset-deep); }
.chart-legend { display: flex; gap: 24px; flex-wrap: wrap; margin-top: var(--s3); font-size: 13px; color: var(--ink-muted); }
.chart-legend-item { display: inline-flex; align-items: center; gap: 8px; }
.chart-legend-dot { width: 10px; height: 10px; border-radius: 50%; }
.chart-legend-dot.utility { background: var(--rise); }
.chart-legend-dot.solar { background: var(--calm); }

/* D1 TOC rail, guides only, >=1025px (the island covers this below that). sa.js wraps every h2
   section (first through last, inclusive) in .sa-toc-scope, then lays a full-height
   position:absolute overlay (.sa-toc-overlay, itself a .container so it shares the exact
   width/centring every other container on the page uses) across that whole scope, holding just
   the sticky rail. pointer-events stay off on the transparent overlay and on only the rail, so
   the real sections underneath (untouched, still full-bleed and alternating-band) stay clickable
   everywhere else. display:flex + align-self:start on the rail keeps it its own natural height
   (not stretched to the overlay's full, multi-section height) while position:sticky still ranges
   across that full height -- exactly the "grid row that actually stretches to the content, item
   aligned to its start" the old single-section grid never managed to be tall enough to do. */
@media (min-width: 1025px) {
  .sa-toc-scope { position: relative; }
  .sa-toc-overlay { position: absolute; inset: 0; display: flex; pointer-events: none; z-index: 1; }
  /* sa.js adds .sa-toc-reserve only to the sections it turned into rail entries, but the scope
     it wraps runs from the FIRST to the LAST id'd section inclusive -- so a section in between
     with no id (e.g. the un-headed continuation of a split "contract to PTO" timeline on the
     utility guides) kept its full-width container and rendered underneath the transparent rail
     overlay. Reserving the gutter for every section in the scope fixes that without sa.js
     having to grow past its 18 KB budget. */
  .sa-toc-reserve, .sa-toc-scope > section > .container { padding-left: calc(220px + var(--s16)); }
  /* The rail was only ever exercised on missouri-solar-cost, whose 9 entries fit. Turning it on
     across the other 18 guides brings pages with up to 13 entries and section headings up to 111
     characters, so the rail now caps its own height and scrolls, and each label clamps to three
     lines instead of wrapping to seven. */
  .sa-toc { align-self: start; position: sticky; top: calc(var(--header-h) + 16px); width: 220px; max-height: calc(100vh - var(--header-h) - 32px); overflow-y: auto; overscroll-behavior: contain; pointer-events: auto; }
  .sa-toc a { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; line-clamp: 3; overflow: hidden; padding: 8px 0 8px 14px; border-left: 2px solid var(--hairline); color: var(--ink); font-size: 15px; line-height: 1.35; transition: border-color var(--t-m-medium) var(--ease-spring), color var(--t-ui) ease; }
  .sa-toc a.is-active { border-left-color: var(--sunset); color: var(--ink); }
}
@media (max-width: 1024px) { .sa-toc-overlay { display: none; } }

/* ----------------------------------------------------------------------------------------
   Reveal system and reduced motion
   ---------------------------------------------------------------------------------------- */
.js-reveal [data-reveal] { opacity: 0; transform: translateY(12px); transition: opacity var(--t-reveal) var(--ease-out), transform var(--t-reveal) var(--ease-out); }
.js-reveal [data-reveal].is-in { opacity: 1; transform: none; }
.js-reveal [data-reveal-group] > [data-reveal], .js-reveal [data-reveal-group] > .rule-row::after { transition-delay: calc(var(--i, 0) * 50ms); }
.js-reveal .rule-row { border-bottom-color: transparent; }
.js-reveal .rule-row::after { content: ""; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px; background: var(--hairline); transform: scaleX(0); transform-origin: left; transition: transform var(--t-draw) var(--ease-out); }
.js-reveal .rule-row.is-in::after { transform: scaleX(1); }
@media (max-width: 640px) { .js-reveal [data-reveal-group] > [data-reveal], .js-reveal [data-reveal-group] > .rule-row::after { transition-delay: 0ms; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-property: color, background-color, border-color, text-decoration-color, opacity !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .js-reveal .rule-row { border-bottom-color: var(--hairline); }
  .js-reveal .rule-row::after { display: none; }
}

/* Misc */
.prose { display: grid; gap: var(--s4); max-width: var(--measure); }
.prose h2 { font-size: var(--fs-h3); font-weight: var(--w-h3); margin-top: var(--s4); }
.prose p, .prose li { color: var(--ink-muted); }
.prose ul { display: grid; gap: var(--s2); padding-left: 1.1em; list-style: disc; }

/* ----------------------------------------------------------------------------------------
   Calculator (solar-cost-calculator). Solar Assure addition. The step wizard's visibility is
   pure display:none/active toggling driven by the page's own inline script (kept verbatim from
   legacy); everything else here is restyled wrapper chrome only, no maths, no ids touched.
   ---------------------------------------------------------------------------------------- */
.calc-step { display: none; }
.calc-step.active { display: grid; gap: var(--s6); }
.calc-step-header { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
.calc-step-num { padding: 4px 10px; border: 1px solid var(--hairline-strong); border-radius: var(--r-pill); text-transform: uppercase; }
.calc-btn-row { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap; }

/* Satellite map / aerial view panel. The map, tilt button, aerial button and back button are
   injected by the page's own script via innerHTML strings, so these class names are load-bearing
   (not just visual) -- renaming any of them would leave the script's own markup unstyled. */
.calc-satellite-wrap { position: relative; min-height: 220px; display: flex; align-items: center; justify-content: center; border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); overflow: hidden; background: var(--canvas); }
.calc-satellite-wrap.has-image { padding: 0; }
.calc-satellite-placeholder { display: grid; justify-items: center; gap: var(--s3); padding: var(--s10) var(--s6); color: var(--ink-muted); text-align: center; }
.calc-satellite-wrap img, .calc-satellite-wrap video { width: 100%; height: auto; display: block; }
.calc-map { width: 100%; height: 320px; }
.map-controls { position: absolute; top: var(--s3); left: var(--s3); z-index: 2; display: flex; flex-direction: column; gap: var(--s2); }
.map-control-btn { display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 var(--s3); border-radius: var(--r-pill); border: 1px solid var(--hairline-strong); background: var(--surface); color: var(--ink); font-size: 13px; font-weight: var(--w-ui); cursor: pointer; }
.map-control-btn.active { background: var(--night); color: var(--paper); border-color: var(--night); }
.aerial-view-btn, .back-to-satellite-btn { position: absolute; top: var(--s3); right: var(--s3); z-index: 2; display: inline-flex; align-items: center; gap: 8px; min-height: 40px; padding: 0 var(--s4); border-radius: var(--r-pill); border: 1px solid transparent; font-size: 13px; font-weight: var(--w-btn); cursor: pointer; }
.aerial-view-btn { background: var(--sunset); color: var(--night); }
.back-to-satellite-btn { background: var(--night); color: var(--paper); border-color: rgba(255, 251, 244, .32); }
.calc-satellite-overlay { position: absolute; left: var(--s3); right: var(--s3); bottom: var(--s3); z-index: 2; display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-radius: var(--r-inner); background: color-mix(in srgb, var(--night) 82%, transparent); color: var(--paper); font-size: 13px; }
/* These four inline SVGs (tilt toggle, "watch 3D fly-around" play glyph, satellite/roof-confirm
   checkmark, back-to-satellite arrow) come from the same innerHTML strings and carry no
   width/height of their own, so without a sizing rule they render at their intrinsic (huge)
   size -- this is the fix for the giant checkmark on the roof-confirm overlay (screenshot
   a0086cc2). Page-scoped: all four classes are unique to this page (verified against every other
   src/pages/*.html). Do not edit the script strings themselves; size the result here instead. */
.map-control-btn svg, .aerial-view-btn svg, .back-to-satellite-btn svg, .calc-satellite-overlay svg { width: 20px; height: 20px; flex: 0 0 auto; }
.aerial-video-loading { display: grid; justify-items: center; gap: var(--s3); padding: var(--s10); color: var(--ink-muted); }

/* Loading rings. This class name is used in two places: the static step3Loading markup below
   (which also carries .btn-spinner, so it spins by reusing the one sitewide spin animation the
   spec allows -- no new looping animation rule is defined here) and inside an innerHTML string
   in the page's own kept-verbatim script (the Aerial View "loading video" state), which cannot
   be given a second class without editing that script. Standalone (without .btn-spinner) this
   renders as a static ring -- no spin -- which is fine for that brief, secondary loading state. */
.calc-loading { display: grid; justify-items: center; gap: var(--s4); padding: var(--s16) 0; text-align: center; }
.calc-loading-ring { width: 40px; height: 40px; border-radius: 50%; border: 3px solid var(--hairline-strong); border-top-color: var(--sunset); }

/* Battery option cards + quantity stepper */
.batt-options { display: grid; gap: var(--s3); }
.batt-option { position: relative; display: grid; grid-template-columns: 22px 1fr; column-gap: var(--s3); row-gap: 2px; align-items: start; padding: var(--s4); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); cursor: pointer; transition: border-color var(--t-ui) ease; }
.batt-option-input { position: absolute; opacity: 0; pointer-events: none; }
.batt-option-radio { grid-row: 1 / span 2; width: 20px; height: 20px; margin-top: 2px; border-radius: 50%; border: 2px solid var(--hairline-strong); position: relative; }
.batt-option.selected { border-color: var(--sunset-deep); }
.batt-option.selected .batt-option-radio { border-color: var(--sunset-deep); }
.batt-option.selected .batt-option-radio::after { content: ""; position: absolute; inset: 3px; border-radius: 50%; background: var(--sunset-deep); }
.batt-option-title { font-weight: var(--w-h3); font-size: 15px; }
.batt-option-desc { color: var(--ink-muted); font-size: 14px; line-height: 1.5; }
@media (hover: hover) { .batt-option:hover { border-color: var(--ink); } }
.batt-counter-wrap { display: none; }
.batt-counter-wrap.visible { display: grid; gap: var(--s5); margin-top: var(--s2); }
.batt-counter { display: flex; align-items: center; justify-content: center; gap: var(--s6); }
.batt-counter-btn { width: 44px; height: 44px; min-height: 44px; padding: 0; border-radius: 50%; }
.batt-counter-display { display: grid; justify-items: center; min-width: 96px; }

/* Bill slider (plain input[type=range], sunset accent-color, already global -- see Forms) */
.bill-slider-wrap { display: grid; gap: var(--s2); text-align: center; padding: var(--s6) 0; }
.bill-slider-meta { display: flex; justify-content: space-between; margin-top: 2px; }

/* Results badge + math notation */
.results-data-source { display: inline-flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: var(--r-pill); border: 1px solid var(--hairline-strong); }
.results-data-source.fallback { color: var(--sunset-deep); border-color: color-mix(in srgb, var(--sunset-deep) 35%, transparent); }
.results-data-source.solar-api { color: var(--ink); }
.formula { display: inline-block; font-family: var(--font-mono); font-size: 14px; padding: 2px 8px; background: var(--surface); border: 1px solid var(--hairline); border-radius: 4px; }

/* Lead capture fields (Step 4) */
.lead-fields { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
.lead-fields .lead-field.full { grid-column: 1 / -1; }
@media (max-width: 640px) { .lead-fields { grid-template-columns: 1fr; } }
/* ----------------------------------------------------------------------------------------
   /when-not-to-install-solar components
   ----------------------------------------------------------------------------------------
   Five class families arrived from the legacy site with markup but no stylesheet at all:
   .toc-nav/.toc-list/.toc-num, .reason-*, .flip-card-marker, .checklist-*, .stat-callout.
   Every one of them rendered as bare stacked text -- the "01" numerals, the Financial/Physical
   tags and the two compare markers all read as loose body copy with no relationship to what
   they labelled. Two earlier passes left the page alone deliberately because it needs genuinely
   new component treatments rather than a reuse of .rule-row or .tile.

   Three new treatments live here, built only from existing tokens so every band override keeps
   working unchanged:
     1. .reason-card  -- numbered reason card, 8 on the page
     2. .compare-pair -- the two-panel "does not / typically works" comparison, which replaces
                         the two orphaned .flip-card-marker divs in the source markup
     3. .checklist    -- the printable self-assessment, numbered via a CSS counter
   .stat-callout and .toc-nav are the two smaller orphans, styled in place.

   The JSON-LD speakable block on this page points at .reason-summary, so that class name is
   load-bearing for search and must not be renamed. It is kept, and given the visual weight the
   selector implies: the one-sentence answer, set apart from the detail beneath it.
   ---------------------------------------------------------------------------------------- */

/* Inline figure inside reason prose ("$18K to $30K"). Emphasis without a colour change, so it
   still reads correctly on the cream band where .accent is deliberately neutralised. */
.stat-callout { font-weight: var(--w-h3); color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* "Jump to a reason": an in-page index inside .prose. Distinct from the sticky .sa-toc rail,
   which is injected by sa.js and only appears at >=1024px. */
.toc-nav { display: grid; gap: var(--s4); padding: var(--s6); background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); }
.toc-nav h3 { color: var(--eyebrow); font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); text-transform: uppercase; }
.toc-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--s8); margin: 0; padding: 0; list-style: none; }
.toc-list li { border-top: 1px solid var(--hairline); }
.toc-list li:nth-child(-n+2) { border-top: 0; }
.toc-list a { display: flex; align-items: baseline; gap: var(--s3); min-height: 44px; padding: var(--s2) 0; color: var(--ink); font-size: 15px; font-weight: var(--w-ui); transition: color var(--t-ui) ease; }
.toc-num { flex: 0 0 auto; color: var(--sunset-deep); font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); font-variant-numeric: tabular-nums; }
@media (hover: hover) { .toc-list a:hover { color: var(--link); } }
@media (max-width: 640px) {
  .toc-list { grid-template-columns: minmax(0, 1fr); }
  .toc-list li:nth-child(2) { border-top: 1px solid var(--hairline); }
}

/* Numbered reason card. Lifted out of .prose in the source markup so the card fills the
   container while its copy stays capped at the reading measure. */
.reason-list { display: grid; gap: var(--s6); margin: 0; padding: 0; list-style: none; }
.reason-card { display: grid; gap: var(--s5); padding: var(--s8); background: var(--surface); border: 1px solid var(--hairline-strong); border-radius: var(--r-surface); }
.reason-header { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3) var(--s5); align-items: start; }
.reason-num { color: var(--sunset); font-size: clamp(2.25rem, 1.7rem + 1.8vw, 3.25rem); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: .9; font-variant-numeric: tabular-nums; }
.reason-headline { display: grid; gap: var(--s3); justify-items: start; }
.reason-headline h3 { max-width: 28ch; font-size: var(--fs-h3); font-weight: var(--w-h3); letter-spacing: var(--track-h3); line-height: var(--lh-h3); }
.reason-headline h3 em { font-style: normal; text-decoration: underline; text-decoration-color: var(--sunset); text-decoration-thickness: 2px; text-underline-offset: .18em; }
.reason-tag { display: inline-flex; align-items: center; min-height: 24px; padding: 2px 10px; border: 1px solid var(--hairline-strong); border-radius: var(--r-pill); color: var(--ink-muted); font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); text-transform: uppercase; }
.reason-summary { max-width: var(--measure); padding-left: var(--s5); border-left: 2px solid var(--sunset); color: var(--ink); font-size: var(--fs-lede); line-height: 1.5; }
.reason-detail { display: grid; gap: var(--s4); max-width: var(--measure); color: var(--ink-muted); font-size: 15px; line-height: 1.6; }
.reason-detail strong { color: var(--ink); font-weight: var(--w-ui); }
@media (max-width: 640px) {
  .reason-card { gap: var(--s4); padding: var(--s5); }
  .reason-header { grid-template-columns: minmax(0, 1fr); gap: var(--s2); }
  .reason-summary { padding-left: var(--s4); }
}

/* Compare pair. --rise/--calm are reserved for data-viz by the token block above, so the two
   panels are separated by weight and by the brand accent instead of by a red/green pair:
   neutral ink for the "not yet" side, sunset for the side that leads to a quote. */
.compare-pair { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5); }
.compare-panel { display: grid; gap: var(--s4); align-content: start; padding: var(--s6); background: var(--surface); border: 1px solid var(--hairline-strong); border-top: 3px solid var(--ink); border-radius: var(--r-surface); }
.compare-panel[data-tone="go"] { border-top-color: var(--sunset); }
.compare-panel:nth-child(2) { --i: 1; }
.compare-panel .eyebrow { margin-bottom: 0; }
.compare-panel h3 { font-size: 1.0625rem; font-weight: var(--w-h3); letter-spacing: -.01em; line-height: 1.35; }
.compare-list { display: grid; margin: 0; padding: 0; list-style: none; }
.compare-list li { padding: var(--s3) 0; border-top: 1px solid var(--hairline); color: var(--ink-muted); font-size: 15px; line-height: 1.55; }
.compare-list li:first-child { padding-top: 0; border-top: 0; }
@media (max-width: 900px) { .compare-pair { grid-template-columns: minmax(0, 1fr); } }

/* Printable self-assessment checklist. The numeral is a CSS counter rather than markup, and the
   dashed rule under each question is the line the page tells the reader to write on. */
.checklist { display: grid; margin: 0; padding: 0; list-style: none; counter-reset: checklist; border-top: 1px solid var(--hairline); }
.checklist-item { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s2) var(--s4); align-items: start; padding: var(--s4) 0; border-bottom: 1px solid var(--hairline); counter-increment: checklist; }
.checklist-item::before { content: counter(checklist, decimal-leading-zero); color: var(--sunset-deep); font-size: var(--fs-label); font-weight: var(--w-btn); letter-spacing: var(--track-label); font-variant-numeric: tabular-nums; line-height: 1.7; }
.checklist-item::after { content: ""; grid-column: 2; height: 26px; border-bottom: 1px dashed var(--hairline-strong); }
.checklist-item-q { max-width: var(--measure); color: var(--ink); font-size: 15px; line-height: 1.55; }

@media print {
  .sa-toc, .toc-nav { display: none; }
  .checklist-item { break-inside: avoid; }
  .checklist-item::after { height: 34px; border-bottom-color: var(--ink); }
}
