/* =============================================================================
   MASTER: finance-nexledger-static - concept preview by PXLNorth
   Parameterized from the operator-approved nhttax.com recreation of the
   nexledger blueprint (templates/blueprints/finance/nexledger, visual system)
   on the kruze structure (templates/blueprints/finance/kruze). Structure and
   density come from the blueprints; every color and font below is a slot the
   tailor pass fills per prospect.

   TYPE PAIRING
   ------------
   The font custom properties and the Google Fonts link are content-driven
   (content.json fonts object). The shipped default is the source build's
   pairing: Manrope 800 for display (a heavy geometric grotesk with tight, even
   counters and tabular figures, so the stat strip lines up) plus IBM Plex Sans
   for body (a humanist-leaning sans built for long reading of dense, factual
   text - an accounting firm publishes lists of tax items, not taglines). The
   tailor pass picks a pairing for each prospect's identity and documents the
   choice in the run. Never Fraunces (operator taste rule).

   COLOR SLOTS - every slot reads the fill-static palette (paletteMode pro);
   theme.json SHOULD pin the full scale via its pro object (see template.json).
   The prospect's real site scheme drives the slots, logo colors are accents:
     navy slots (900/800/700) : the DEEP GROUND - hero duotone, CTA band,
                                contact band, footer. Derived from a real dark
                                surface or button of THEIR site, never from the
                                logo. Surfaces stay light (paper/paper-2).
     duotone                  : the solid color the photo tints mix from
                                (hero, band, contact). A navy-family hue.
     blue / blue-strong       : the prospect's PRIMARY brand color, spent as an
                                ACCENT ONLY - links, rules, the float-card art,
                                the solid CTA pill. Never a canvas.
     blue-light / blue-wash   : pale relatives of the accent (focus ring, the
                                contact-person rule, the white pill hover).
     ink slots                : near-black text scale; line, paper, paper-2.
   Master-specific slot names fall back to derived standard keys (or a
   color-mix of the accent) when unpinned, so an unpinned theme still renders
   a coherent AA page, never an empty var. Photo tints use color-mix from the
   vars, so the whole page re-themes from the palette alone.
   ========================================================================== */

:root {
  --navy-900: #05263a;
  --navy-800: #08364f;
  --navy-700: #0a4a6e;
  --duotone: #073450;
  --blue: #005090;
  --blue-strong: #003f73;
  --blue-light: #a7c5d8;
  --blue-wash: #e9f4fa;
  --ink: #101828;
  --ink-2: #344054;
  --ink-3: #5b6578;
  --line: #dfe4ec;
  --white: #ffffff;

  /* FLEET TOKEN ALIASES. The presentation resolver emits accent-discipline as one of the
     literals `var(--ink-3)` / `var(--brand)` / `var(--accent)` - fleet token names, not
     this master's. This master calls the same two colours --blue-strong and --blue, so
     without these aliases the resolved value would name a variable that does not exist
     and the eyebrow would render with no colour at all. Aliases, not new colours: nothing
     below reads them except the resolved literal. */
  --brand: var(--blue-strong);
  --accent: var(--blue);

  /* SURFACE TEMPERATURE (presentation axis 2, `$presentation.temperatureMode: "css"`,
     ported 2026-08-30 from law-malmanlaw-static, which docs/PRESENTATION_MATRIX.md §8
     names as the reference port). The two light canvases are mixed HERE rather than
     handed over pre-mixed, so the base values stay readable in the built stylesheet and
     one place owns the arithmetic. THE AMOUNT IS NOT A DESIGN CHOICE MADE IN CSS:
     fillStatic measures every ink this master paints on these grounds against 4.5:1 and
     walks the mix down until they all clear, so `--temp-amt` is whatever survived that
     guard (0% is a legitimate answer and is recorded in runs/<domain>/presentation.json
     with the pair that blocked it). Neutral mixes a base with itself, a no-op by
     construction. The base is named --canvas-base on purpose: that is the token the
     resolver's own neutral fallback literal points at.
     The DARK grounds (--navy-*, --duotone) are deliberately untouched - the temperature
     axis moves light surfaces only (docs/PRESENTATION_MATRIX.md §6). */
  --canvas-base: #ffffff;
  --paper-2-base: #f3f6f9;
  --temp-tint: var(--canvas-base);
  --temp-amt: 0%;
  --paper: color-mix(in srgb, var(--temp-tint) var(--temp-amt), var(--canvas-base));
  --paper-2: color-mix(in srgb, var(--temp-tint) var(--temp-amt), var(--paper-2-base));

  --font-display: "Manrope", "Segoe UI", system-ui, sans-serif;
  --font-body: "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;

  --radius-xl: 24px;
  --radius-lg: 18px;
  --radius-md: 12px;
  --radius-pill: 999px;

  --wrap: 1220px;
  --gutter: clamp(18px, 4vw, 40px);

  /* ---------- SUB-NICHE PRESENTATION MATRIX (TASTE_LEDGER #69) ----------
     Ported 2026-08-30. Before it this master declared NO $presentation block at all, so
     all seven axes were reported UNDECLARED and every sub-niche of the accountant niche
     rendered the identical page. Six axes now paint; artDirection stays with the imagery
     engine and section ORDER is not expressible by any master.

     Every value arrives as a finished literal (the resolver does the arithmetic; a
     mustache template cannot), and every one carries a fallback equal to THIS MASTER'S
     OWN shipped value, so a fill from any older path renders what it rendered before -
     with ONE deliberate exception, --section, called out below.                        */
  --display-scale: 1;
  --display-weight: 800;
  --eyebrow-case: uppercase;
  --eyebrow-track: 0.2em;
  --eyebrow-color: var(--brand);
  /* SECTION RHYTHM, and the one deliberate render change in this port. --section was
     `clamp(56px, 9vw, 120px)`, the PRE-#52 gap: the operator's TASTE_LEDGER #52 rhythm
     directive ("reduce the gap between sections vertically by 40% on all templates")
     reached the clinical master on 2026-08-29 and both law masters on 2026-08-30, and
     never reached this one. `--rhythm` is `clamp(2.1rem, 4.2vw, 3.9rem)` - the approved
     medical demo's exact figure, now carried by all three sibling masters - times the
     density axis, so rhythm-scale 1 IS #52 and the axis varies around the approved
     rhythm rather than around the old gaps. */
  --rhythm-scale: 1;
  --section: calc(clamp(2.1rem, 4.2vw, 3.9rem) * var(--rhythm-scale));
  --measure: 60ch;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  overflow-x: hidden;
}
img { max-width: 100%; height: auto; display: block; }
h1, h2, h3 { font-family: var(--font-display); line-height: 1.1; margin: 0 0 .5em; letter-spacing: -0.01em; }
/* displayRegister axis on the two DISPLAY headings - SCALE varies, weight and tracking
   are pinned, and both pins are measured decisions rather than laziness. See
   template.json $presentation.$displayRegisterNote for the full reasoning; in short:
   templates/variants/accountant.json carries no `presentationDefault`, so every accountant
   fill resolves the FLEET baseline (weight 600, tracking normal -0.005em). Wiring those
   two through would not have differentiated one sub-niche from another - it would have
   quietly moved the operator-APPROVED nhttax render, dropping h1/h2 from 800 to 700 (the
   same weight as h3, collapsing the one weight step this hierarchy is built on) and
   loosening a tight grotesk from -0.02em to -0.005em. headingWeights is therefore declared
   [800] so the resolver clamps to this master's own weight and PRINTS the clamp as an
   issue on every fill, and h2 keeps its own tracking. h3 is off the axis entirely: it is a
   card title beside body text, not display type. --display-weight is still read here so
   the pin lives in one place and a future accountant presentationDefault only has to
   declare 800 to take control of it. */
h1 { font-weight: var(--display-weight, 800); font-size: calc(clamp(2.2rem, 1.1rem + 3.2vw, 3.5rem) * var(--display-scale, 1)); letter-spacing: -0.025em; line-height: 1.05; }
h2 { font-weight: var(--display-weight, 800); font-size: calc(clamp(1.7rem, 1.1rem + 2.2vw, 2.75rem) * var(--display-scale, 1)); letter-spacing: -0.02em; }
h3 { font-weight: 700; font-size: 1.25rem; }
p { margin: 0 0 1em; }
a { color: var(--blue-strong); text-decoration-thickness: 1px; text-underline-offset: 3px; }
ul, ol { margin: 0; padding: 0; list-style: none; }
.wrap { width: min(var(--wrap), 100% - var(--gutter) * 2); margin-inline: auto; }

.skip-link { position: absolute; left: -999px; top: 8px; background: var(--white); color: var(--ink); padding: 8px 14px; border-radius: 8px; z-index: 100; }
.skip-link:focus { left: 8px; }
:focus-visible { outline: 3px solid var(--blue-light); outline-offset: 3px; }

.eyebrow {
  font-family: var(--font-display);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: var(--eyebrow-track, .18em);
  text-transform: var(--eyebrow-case, uppercase);
  color: rgba(255,255,255,.78);
  margin: 0 0 14px;
}
/* Accent discipline (paletteTemperature axis) lands HERE and only here on this master:
   --eyebrow-color is the resolver's accent-reach literal, and .eyebrow-dark is the one
   element that repeats on every light section. The on-dark .eyebrow above keeps its fixed
   white tint - accent reach must never move an on-dark label off a measured contrast. */
.eyebrow-dark { color: var(--eyebrow-color, var(--blue-strong)); }

/* ---------- SECTION EMPHASIS (presentation axis 4) ----------
   The renderer the emitted `variantEmphasis`/`variantCompact` never had on this master.
   `data-emph` is the section this sub-niche LEADS on - more air around it and a larger
   head; `data-compact` is one that recedes without disappearing. Both are relative to
   whatever rhythm the density axis already set, so the two axes compose instead of
   fighting. Each section sets its own padding here (there is no shared `.section` class
   on this master), so the pairs are written per section rather than once. `.proof` pads
   its TOP only by design - it butts onto the hero - so it moves only that edge. */
.proof[data-emph] { padding-top: calc(var(--section) * 1.22); }
.proof[data-compact] { padding-top: calc(var(--section) * 0.74); }
.why[data-emph], .services[data-emph], .reviews[data-emph], .faq[data-emph] { padding: calc(var(--section) * 1.22) 0; }
.why[data-compact], .services[data-compact], .reviews[data-compact], .faq[data-compact] { padding: calc(var(--section) * 0.74) 0; }
.contact[data-emph] { padding: calc(var(--section) * 1.15) 0; }
.contact[data-compact] { padding: calc(var(--section) * 0.78) 0; }
[data-emph] > .wrap > .why-head h2,
[data-emph] > .wrap > .services-head h2,
[data-emph] > .wrap > .reviews-head h2 { font-size: calc(clamp(1.7rem, 1.1rem + 2.2vw, 2.75rem) * var(--display-scale, 1) * 1.08); }
[data-compact] > .wrap > .why-head,
[data-compact] > .wrap > .services-head,
[data-compact] > .wrap > .reviews-head { margin-bottom: 26px; }
/* The stat strip is not a section - it lives inside the hero grid - so emphasis reaches
   it as the numeral's own scale rather than as padding. Kept distinct from the
   trustSignal treatment below: this one says "this sub-niche leads on its numbers", that
   one says "this business's proof IS numbers". They compose. */
.stats[data-emph] .stat dd { font-size: clamp(2.1rem, 1.5rem + 1.9vw, 3rem); }
.stats[data-compact] .stat dd { font-size: clamp(1.6rem, 1.2rem + 1.2vw, 2.1rem); }

/* ---------- TYPE REGISTER (presentation axis 1) ----------
   Weight, tracking and scale are already custom properties above; these rules are the
   part a number cannot carry - the SHAPE of the setting. This master's own setting is
   `grotesque` (Manrope display over IBM Plex Sans body), so THAT is the register declared
   empty here: a page that resolves grotesque renders exactly as this master always has.
   The two that are declared are the departures from it.

   WEIGHT CONTRACT: nothing below introduces a weight. The heading weight comes from
   --display-weight, clamped by the resolver to $presentation.headingWeights [700, 800],
   so blueprint-gate's faux-bold check cannot regress through this layer. */
body[data-register="editorial"] h1,
body[data-register="editorial"] h2 { line-height: 1.14; letter-spacing: -0.012em; }
body[data-register="editorial"] { line-height: 1.72; }

body[data-register="humanist"] h1,
body[data-register="humanist"] h2,
body[data-register="humanist"] h3 { line-height: 1.2; letter-spacing: 0; }
body[data-register="humanist"] { line-height: 1.72; }
body[data-register="humanist"] .why-head p, body[data-register="humanist"] .services-head p { max-width: 46ch; }

/* ---------- PROOF BAND (presentation axis 7, trustSignal) ----------
   trustSignal resolved to the one decision this page can actually paint: whether the stat
   strip in the hero shouts or sits quiet. Numbers-led signals (credentials / results /
   years) set the real figures off with a rule and size them up, where they read as a
   claim; people-led ones (warmth / reviews / availability) leave the strip as the quiet
   footnote it is, so the page does not open with a scoreboard at a reader who came for a
   person. It never invents a figure - the whole strip is still behind the template's own
   stats conditional. (Written without mustache braces on purpose: css/style.css is
   token-rendered, so a block tag inside a CSS COMMENT is still a block tag.)
   The loud treatment is deliberately SIZE AND RULE, not colour: the strip sits on the
   navy hero ground whose exact hue is per-prospect, and a tinted numeral would need a
   contrast measurement this layer has no way to take. */
body[data-proof="loud"] .stats { border-top: 1px solid rgba(255,255,255,.35); padding-top: 26px; }
body[data-proof="loud"] .stat dd { font-size: clamp(2.2rem, 1.5rem + 2vw, 3.2rem); }

/* ---- Buttons -------------------------------------------------------------- */
.pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 24px;
  border-radius: var(--radius-pill);
  font-family: var(--font-display); font-weight: 700; font-size: .95rem;
  text-decoration: none; border: 1.5px solid transparent; cursor: pointer;
  transition: background .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
}
.pill:hover { transform: translateY(-1px); }
.pill-solid { background: var(--blue); color: var(--white); }
.pill-solid:hover { background: var(--blue-strong); }
.pill-white { background: var(--white); color: var(--navy-800); }
.pill-white:hover { background: var(--blue-wash); }
.pill-outline { background: transparent; color: var(--white); border-color: rgba(255,255,255,.7); }
.pill-outline:hover { background: rgba(255,255,255,.12); }
.pill-ghost { background: transparent; color: var(--white); border-color: transparent; text-decoration: underline; text-underline-offset: 5px; }

/* ---- Stage + header ------------------------------------------------------ */
.stage { background: var(--paper); }

.site-header { position: absolute; inset: 0 0 auto 0; z-index: 20; color: var(--white); }
.utility { border-bottom: 1px solid rgba(255,255,255,.12); }
.utility-row { display: flex; justify-content: space-between; align-items: center; min-height: 34px; font-size: .72rem; letter-spacing: .14em; text-transform: uppercase; font-family: var(--font-display); font-weight: 600; }
.utility-links { display: flex; gap: 22px; }
.utility a { color: rgba(255,255,255,.82); text-decoration: none; }
.utility a:hover { color: var(--white); }
.utility-hours { margin: 0; color: rgba(255,255,255,.82); }

.nav { backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }
.nav-row { display: flex; align-items: center; justify-content: space-between; gap: 20px; min-height: 80px; }
.brand { display: inline-flex; align-items: center; min-width: 0; }
.brand-logo { max-height: 46px; height: auto; width: auto; max-width: 100%; min-width: 0; object-fit: contain; }
.nav-links { display: flex; gap: 28px; }
.nav-links a {
  color: rgba(255,255,255,.9); text-decoration: none;
  font-family: var(--font-display); font-weight: 700; font-size: .8rem; letter-spacing: .14em; text-transform: uppercase;
}
.nav-links a:hover { color: var(--white); }
.nav-mobile-only { display: none; }
.nav-actions { display: flex; align-items: center; gap: 14px; }
.nav-phone { color: var(--white); text-decoration: none; font-family: var(--font-display); font-weight: 700; font-size: .9rem; white-space: nowrap; }
.nav-phone-label { font-weight: 600; font-size: .7rem; letter-spacing: .14em; text-transform: uppercase; opacity: .75; margin-right: 6px; }
.nav-burger {
  display: none; width: 46px; height: 46px; border-radius: 50%;
  border: 1.5px solid rgba(255,255,255,.5); background: transparent; cursor: pointer;
  flex-direction: column; align-items: center; justify-content: center; gap: 5px; flex-shrink: 0;
}
.nav-burger span { width: 18px; height: 2px; background: var(--white); border-radius: 2px; transition: transform .2s ease, opacity .2s ease; }
.nav-burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ---- Hero ----------------------------------------------------------------- */
.hero { padding: 0; background: var(--paper); }
.hero-frame {
  position: relative; overflow: hidden; isolation: isolate;
  min-height: 100svh;
  display: flex; align-items: stretch;
}
/* PHOTO TINTS, LIGHTENED 2026-08-29 (template-quality-loop batch 5 #7, the overlay-drowning
   defect class). The stacks below used to composite to ~0.67 navy at the band's LIGHTEST
   point, so a real photograph rendered as texture on a navy rectangle: the page paid the
   bytes and the reader saw a solid. Measured on nhttax.com and now gated by
   blueprint-gate's `band-photo-perceptible` (scripts/lib/bandPhoto.mjs).

   The rule the numbers follow: the tint stays FULL STRENGTH wherever copy sits, and falls
   away only where nothing is set. So each stop moved for a reason that can be pointed at on
   the page, never as a uniform "lighten by 20%". */
.hero-photo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 68% 45%;
  /* brightness(.95) dropped with the tint: it darkened the photo a second time, under the
     scrim, where nothing could get it back. */
  filter: saturate(.72) contrast(1.06);
  z-index: -2;
}
.hero-tint {
  position: absolute; inset: 0; z-index: -1;
  background:
    /* The dark plateau now reaches 44% before falling away, because the h1's accent word
       runs to about 49% of the band at 1440 and overlay-legibility measured it at 2.8:1
       when the falloff started at 36%. Everything left of the float card (which begins at
       ~65%) is at least as dark as it was; the photo breathes from 68% rightward, where
       nothing is set. */
    linear-gradient(90deg, color-mix(in srgb, var(--navy-900) 92%, transparent) 0%, color-mix(in srgb, var(--navy-900) 86%, transparent) 44%, color-mix(in srgb, var(--navy-900) 30%, transparent) 68%, color-mix(in srgb, var(--navy-900) 10%, transparent) 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--navy-900) 46%, transparent) 0%, color-mix(in srgb, var(--navy-900) 5%, transparent) 30%, color-mix(in srgb, var(--navy-900) 24%, transparent) 72%, color-mix(in srgb, var(--navy-900) 86%, transparent) 100%),
    color-mix(in srgb, var(--duotone) 14%, transparent);
  mix-blend-mode: normal;
}
.hero-grid {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  grid-template-areas:
    "copy card"
    "stats stats";
  column-gap: 48px;
  padding-top: 150px;
  padding-bottom: 48px;
  align-content: end;
  color: var(--white);
}
/* Taste ledger #44: side-by-side hero elements TOP-ALIGN deliberately. Both items
   carry align-self:start so neither can sink below its row sibling. */
.hero-copy { grid-area: copy; align-self: start; max-width: 660px; }
.hero-copy h1 { color: var(--white); margin-bottom: 22px; text-wrap: balance; }
.hero-lead { font-size: clamp(1rem, .95rem + .3vw, 1.08rem); line-height: 1.6; color: rgba(255,255,255,.88); max-width: 560px; margin-bottom: 26px; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; }
.hero-call { display: none; }

.float-card {
  grid-area: card; justify-self: end; align-self: start;
  width: min(380px, 100%);
  background: var(--white); color: var(--ink);
  border-radius: var(--radius-lg); padding: 30px 30px 28px;
  box-shadow: 0 30px 60px -20px rgba(0,0,0,.55);
}
.float-card-art { width: 64px; height: 64px; color: var(--blue); margin-bottom: 14px; }
.float-card-title { font-size: 1.3rem; margin-bottom: 8px; }
.float-card p { font-size: .95rem; color: var(--ink-2); margin-bottom: 20px; }
.stats {
  grid-area: stats; margin: 40px 0 0;
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px 28px;
  padding-top: 28px; border-top: 1px solid rgba(255,255,255,.22);
}
.stat { display: grid; grid-template-rows: auto auto; gap: 6px; align-content: start; }
.stat dd { grid-row: 1; }
.stat dt { grid-row: 2; }
.stat dd { margin: 0; font-family: var(--font-display); font-weight: 800; font-size: clamp(1.9rem, 1.4rem + 1.6vw, 2.7rem); line-height: 1; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.stat dt { font-family: var(--font-display); font-size: .68rem; font-weight: 600; letter-spacing: .14em; text-transform: uppercase; color: rgba(255,255,255,.78); }

.scroll-cue { position: absolute; left: 50%; bottom: 16px; transform: translateX(-50%); width: 26px; height: 42px; border: 1.5px solid rgba(255,255,255,.5); border-radius: 14px; display: none; }
.scroll-cue span { position: absolute; left: 50%; top: 8px; width: 3px; height: 8px; margin-left: -1.5px; border-radius: 2px; background: var(--white); animation: cue 1.8s ease-in-out infinite; }
@keyframes cue { 0%, 100% { transform: translateY(0); opacity: 1; } 60% { transform: translateY(12px); opacity: 0; } }

@media (min-width: 1024px) {
  .hero { padding: clamp(12px, 1.6vw, 24px); }
  .hero-frame { border-radius: var(--radius-xl); min-height: min(860px, calc(100svh - 24px)); }
}

/* ---- Light page body ------------------------------------------------------ */
main > section:not(.hero):not(.band):not(.faq):not(.contact) { background: var(--paper); }
.proof { background: var(--paper); padding: var(--section) 0 0; }
.proof-card {
  display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 44px; align-items: center;
  background: var(--paper-2); border-radius: var(--radius-xl); padding: clamp(24px, 4vw, 48px);
}
.proof-photo img { border-radius: var(--radius-lg); aspect-ratio: 1; object-fit: cover; }
.proof-body h2 { margin-bottom: 16px; }
.proof-body p { color: var(--ink-2); }
.proof-person { margin-top: 18px; padding-top: 18px; border-top: 2px solid var(--blue); display: flex; flex-direction: column; gap: 2px; }
.proof-person strong { font-family: var(--font-display); font-size: 1.05rem; }
.proof-person span { font-size: .9rem; color: var(--ink-3); }

.why { padding: var(--section) 0; }
.why-head { max-width: var(--measure, 760px); margin-bottom: 44px; }
.why-grid { display: grid; grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr); gap: 48px; align-items: start; }
.why-photo { margin: 0; position: sticky; top: 24px; }
.why-photo img { border-radius: var(--radius-lg); aspect-ratio: 4 / 5; object-fit: cover; }
.why-list { display: grid; gap: 10px; }
.why-list li { display: grid; grid-template-columns: 56px minmax(0, 1fr); column-gap: 16px; padding: 22px 0; border-top: 1px solid var(--line); }
.why-list li:last-child { border-bottom: 1px solid var(--line); }
.why-num { font-family: var(--font-display); font-weight: 800; color: var(--blue); font-size: 1.1rem; padding-top: 3px; }
.why-list h3 { grid-column: 2; margin-bottom: 6px; }
.why-list p { grid-column: 2; margin: 0; color: var(--ink-2); }

.steps { margin-top: 64px; background: var(--paper-2); border-radius: var(--radius-xl); padding: clamp(24px, 4vw, 44px); }
.steps-title { margin-bottom: 22px; }
.steps-list { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 28px; counter-reset: step; }
.steps-list li { display: flex; flex-direction: column; gap: 6px; padding-left: 18px; border-left: 2px solid var(--blue); }
.step-num { font-family: var(--font-display); font-size: .72rem; letter-spacing: .16em; text-transform: uppercase; color: var(--blue-strong); font-weight: 700; }
.steps-list strong { font-family: var(--font-display); font-size: 1.05rem; }
.steps-list p { margin: 0; color: var(--ink-2); font-size: .95rem; }

/* ---- Deep CTA band -------------------------------------------------------- */
.band {
  position: relative; overflow: hidden; isolation: isolate;
  background: var(--navy-800); color: var(--white); padding: clamp(48px, 7vw, 88px) 0;
}
/* Same duotone system as the hero: desaturated photo under a navy gradient. */
.band-photo {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: -2;
  filter: saturate(.72) contrast(1.06);
}
.band-photo { object-position: 50% 62%; }
.band-tint, .contact-tint { position: absolute; inset: 0; z-index: -1; }
/* Lightened with the hero (2026-08-29). The old stack ended at 62% navy over a 45% flat
   wash, so even the band's brightest edge composited to 79% opaque and left a fifth of the
   photograph: staged with a real office photo it measured 1.79 on the perceptibility scale
   where a flat band scores under 1.6 and a legible one over 2.0. The heading is capped at
   760px and .band-actions sits at the right edge, so the copy occupies roughly the left
   half; the falloff starts after it and stops short of full transparency because the outline
   CTA is white-on-photo and still has to clear overlay-legibility. */
.band-tint {
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--navy-900) 92%, transparent) 0%, color-mix(in srgb, var(--navy-900) 84%, transparent) 46%, color-mix(in srgb, var(--navy-900) 52%, transparent) 78%, color-mix(in srgb, var(--navy-900) 44%, transparent) 100%),
    color-mix(in srgb, var(--duotone) 16%, transparent);
}
.band-row { position: relative; }
.band-row { display: grid; grid-template-columns: minmax(0, 1.4fr) auto; gap: 32px; align-items: center; }
.band h2 { color: var(--white); font-size: clamp(1.5rem, 1rem + 1.8vw, 2.2rem); max-width: 760px; }
.band p { color: rgba(255,255,255,.8); margin: 0; }
.band-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* ---- Services ------------------------------------------------------------- */
.services { padding: var(--section) 0; }
.services-head { max-width: var(--measure, 760px); margin-bottom: 40px; }
.service-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 28px; }
.service { background: var(--paper-2); border-radius: var(--radius-xl); overflow: hidden; display: grid; grid-template-rows: auto 1fr; }
.service-photo { margin: 0; }
.service-photo img { aspect-ratio: 16 / 9; object-fit: cover; width: 100%; }
.service-body { padding: 26px 28px 30px; }
.service-body h3 { font-size: 1.35rem; }
.service-body p { color: var(--ink-2); }
.service-body ul { display: grid; gap: 6px; margin-top: 14px; }
.service-body li { position: relative; padding-left: 18px; font-size: .95rem; color: var(--ink-2); }
.service-body li::before { content: ""; position: absolute; left: 0; top: .62em; width: 8px; height: 2px; background: var(--blue); }

/* ---- FAQ ------------------------------------------------------------------ */
.faq { padding: var(--section) 0; background: var(--paper-2); }
.faq-grid { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: 48px; }
.faq-head p { color: var(--ink-2); }
.faq-item { background: var(--paper); border-radius: var(--radius-md); border: 1px solid var(--line); margin-bottom: 10px; }
.faq-item summary {
  cursor: pointer; list-style: none; padding: 18px 52px 18px 22px; position: relative;
  font-family: var(--font-display); font-weight: 700; font-size: 1.02rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: "+"; position: absolute; right: 20px; top: 50%; transform: translateY(-50%);
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  color: var(--blue-strong); border: 1.5px solid var(--blue-strong); font-weight: 600; line-height: 1;
}
.faq-item[open] summary::after { content: "\2212"; }
.faq-item p { margin: 0; padding: 0 22px 20px; color: var(--ink-2); }

/* ---- Resources ------------------------------------------------------------ */
.resources { padding: var(--section) 0; }
.resources-row { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); gap: 48px; align-items: center; }
.resources-head p { color: var(--ink-2); }
.resource-list { display: grid; gap: 14px; }
.resource {
  display: flex; flex-direction: column; gap: 2px; padding: 20px 24px;
  border: 1px solid var(--line); border-radius: var(--radius-md); text-decoration: none; color: var(--ink);
  transition: border-color .18s ease, box-shadow .18s ease;
}
.resource:hover { border-color: var(--blue); box-shadow: 0 10px 30px -18px color-mix(in srgb, var(--blue) 50%, transparent); }
.resource strong { font-family: var(--font-display); }
.resource span { font-size: .85rem; color: var(--ink-3); }

/* ---- Contact / lead form -------------------------------------------------- */
.contact {
  position: relative; overflow: hidden; isolation: isolate;
  padding: var(--section) 0; background: var(--navy-900); color: var(--white);
}
/* NO PHOTO SLOT HERE, AND THAT IS A MEASURED DECISION (2026-08-29).
   The contact band used to accept a background photograph. It could never show one: at 1440
   the lead card covers 52-92% of the band's width and the intro copy needs 0-52% dark, so
   there is nowhere for a horizontal falloff to land; at 390 the stacked card takes the lower
   band and the copy the upper. A lightened tint was deployed and photographed on nhttax.com
   to confirm it rather than argue it, and the office was still invisible. So the band keeps
   its scrim over var(--navy-900) and renders exactly as it always did, minus ~150KB nobody
   could ever see. `imagerySlots.consult` is empty for the same reason — a slot the
   composition cannot show must not be offered to the imagery engine, or every tailor pays
   the bytes again. The tint below is unchanged; it now paints over the solid ground. */
.contact-tint {
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--navy-900) 94%, transparent) 0%, color-mix(in srgb, var(--navy-900) 84%, transparent) 42%, color-mix(in srgb, var(--navy-900) 42%, transparent) 68%, color-mix(in srgb, var(--navy-900) 22%, transparent) 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--navy-900) 40%, transparent) 0%, color-mix(in srgb, var(--navy-900) 8%, transparent) 40%, color-mix(in srgb, var(--navy-900) 55%, transparent) 100%),
    color-mix(in srgb, var(--duotone) 30%, transparent);
}
.contact-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 56px; align-items: start; }
.contact-intro h2 { color: var(--white); }
.contact-intro p { color: rgba(255,255,255,.85); }
.contact-intro a { color: var(--white); }
.contact-person { margin: 18px 0 28px; padding-left: 16px; border-left: 2px solid var(--blue-light); }
.contact-person strong { font-family: var(--font-display); color: var(--white); }
.contact-offices { font-style: normal; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; font-size: .92rem; color: rgba(255,255,255,.85); line-height: 1.55; }
.contact-offices strong { display: block; font-family: var(--font-display); color: var(--white); margin-bottom: 4px; }

.lead-card { background: var(--paper); color: var(--ink); border-radius: var(--radius-xl); padding: clamp(22px, 3vw, 36px); box-shadow: 0 24px 60px -30px rgba(0,0,0,.6); }
.lead-title { margin-bottom: 18px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.field label { font-family: var(--font-display); font-size: .82rem; font-weight: 700; color: var(--ink-2); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 1rem; color: var(--ink);
  padding: 12px 14px; border: 1px solid var(--line); border-radius: 10px; background: var(--white);
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--blue); outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--blue) 15%, transparent); }
.field textarea { resize: vertical; min-height: 110px; }
.form-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 4px; }
.call-link { font-family: var(--font-display); font-weight: 700; font-size: .95rem; }
.form-note { margin: 16px 0 0; font-size: .82rem; color: var(--ink-3); line-height: 1.5; }
.form-error { margin: 12px 0 0; padding: 12px 14px; border-radius: 10px; background: #fff4e5; color: #6b3d00; font-size: .9rem; }
.form-error[hidden] { display: none; }

/* ---- Footer --------------------------------------------------------------- */
.footer { background: var(--navy-900); color: rgba(255,255,255,.82); padding: clamp(48px, 6vw, 80px) 0 28px; }
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr .8fr .8fr; gap: 40px; }
.footer-brand img { max-height: 56px; width: auto; height: auto; max-width: 100%; min-width: 0; object-fit: contain; margin-bottom: 18px; }
.footer-brand p { font-size: .95rem; }
.footer-cred { font-size: .82rem; color: rgba(255,255,255,.6); }
.footer-col h3 { color: var(--white); font-size: .78rem; letter-spacing: .16em; text-transform: uppercase; margin-bottom: 16px; }
.footer-col p { font-size: .92rem; }
.footer-col ul { display: grid; gap: 8px; }
.footer a { color: rgba(255,255,255,.88); text-decoration: none; }
.footer a:hover { color: var(--white); text-decoration: underline; }
.footer-bottom { margin-top: 44px; padding-top: 22px; border-top: 1px solid rgba(255,255,255,.14); display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px; font-size: .8rem; color: rgba(255,255,255,.6); }

/* ---- Preview badge (PXLNorth chrome) --------------------------------------- */
.preview-badge {
  position: fixed; right: 12px; bottom: 12px; z-index: 60;
  display: flex; gap: 8px; align-items: center;
  font-size: .72rem; font-family: var(--font-body);
}
.preview-badge a { background: rgba(16,24,40,.92); color: #fff; padding: 7px 11px; border-radius: 999px; text-decoration: none; border: 1px solid rgba(255,255,255,.25); }
.preview-badge-cta { background: var(--blue) !important; }

/* ---- Master additions ------------------------------------------------------
   Conditionals the approved nhttax build never exercised. Each rule fires only
   on a fill whose content LACKS something the source build had (no logo, no
   hero photo, no headshot, no why-photo, no published email) or HAS something
   it lacked (real reviews). With the oracle content every rule is inert. */
.brand-wordmark, .footer-wordmark { font-family: var(--font-display); font-weight: 800; font-size: 1.35rem; letter-spacing: -0.02em; color: var(--white); white-space: nowrap; }
.brand:has(.brand-wordmark) { text-decoration: none; }
.footer-wordmark { display: inline-block; margin-bottom: 18px; }
.hero-frame:not(:has(.hero-photo)) { background: linear-gradient(160deg, var(--navy-800), var(--navy-900)); }
.proof-card:not(:has(.proof-photo)) { grid-template-columns: minmax(0, 1fr); }
.proof-card:not(:has(.proof-photo)) .proof-body { max-width: 860px; }
.why-grid:not(:has(.why-photo)) { grid-template-columns: minmax(0, 1fr); }

.reviews { padding: var(--section) 0; }
.reviews-head { max-width: var(--measure, 760px); margin-bottom: 40px; }
.reviews-head p:not(.eyebrow) { color: var(--ink-2); }
.review-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 24px; }
.review { margin: 0; background: var(--paper-2); border-radius: var(--radius-lg); padding: 26px 28px; display: flex; flex-direction: column; gap: 16px; }
.review blockquote { margin: 0; font-size: 1.02rem; line-height: 1.6; color: var(--ink); }
.review figcaption { display: flex; flex-direction: column; gap: 2px; font-size: .9rem; padding-top: 14px; border-top: 2px solid var(--blue); margin-top: auto; }
.review figcaption strong { font-family: var(--font-display); }
.review figcaption span { color: var(--ink-3); }

/* STAR ROWS ARE DATA (2026-08-30, ported from clinical-ivyrehab-static,
   TASTE_LEDGER #49/#57/#63). A track/fill pair over one sprite, clipped to
   --stars-pct. The fill fraction is the REAL rating and nothing else:
   --stars-pct defaults to 0%, so a row whose rating did not come through draws
   an EMPTY bar rather than a flattering full one. Per card the integer rating
   drives it through data-stars; the head strip carries the decimal rating and
   sets --stars-pct inline (round(rating / 5 * 100)%). Nothing here fires
   without authored rating data, so a build with plain unrated quotes renders
   exactly as it did before this existed. */
.star-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.stars-bar {
  position: relative; display: inline-block; line-height: 0;
  --stars-pct: 0%;
}
.stars-bar[data-stars="1"] { --stars-pct: 20%; }
.stars-bar[data-stars="2"] { --stars-pct: 40%; }
.stars-bar[data-stars="3"] { --stars-pct: 60%; }
.stars-bar[data-stars="4"] { --stars-pct: 80%; }
.stars-bar[data-stars="5"] { --stars-pct: 100%; }
.stars { display: block; height: 15px; width: auto; }
.stars-track { fill: color-mix(in srgb, var(--ink) 18%, transparent); }
.stars-fill {
  position: absolute; left: 0; top: 0; height: 100%;
  fill: #d99b1d;
  clip-path: inset(0 calc(100% - var(--stars-pct)) 0 0);
}
.stars-bar-lg .stars { height: 21px; }
/* SOURCE ATTRIBUTION ONLY (#49): the mark says where the words came from. It
   is never a badge, never a rating, and claims nothing beyond the source. */
.rating-strip { display: flex; align-items: center; gap: 12px; margin: 18px 0 0; }
/* 800 to match .stat dd and the rest of this master's display numerals; the
   $fontWeights contract already fetches Manrope at 800, so this adds no weight
   the href does not request. */
.rating-strip b { font-family: var(--font-display); font-weight: 800; font-size: 1.75rem; line-height: 1; color: var(--ink); }
.g-mark { display: block; width: 18px; height: 18px; }
.card-stars { margin: 0; line-height: 0; }
/* When the review was written (#63), from its real publishedAt and never
   approximated. Tabular figures so a column of dates lines up on the slashes. */
.review-date { font-variant-numeric: tabular-nums; letter-spacing: .02em; }

.lead-card-phone { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.lead-card-phone .lead-title { margin-bottom: 0; }
.lead-phone-note { margin: 0; color: var(--ink-2); }
.lead-phone-note a { color: var(--blue-strong); font-weight: 600; }
.lead-phone-cta { align-self: stretch; font-size: 1.05rem; min-height: 54px; }
.lead-phone-hours { margin: 0; font-size: .9rem; color: var(--ink-3); }

/* ---- Motion --------------------------------------------------------------- */
.fade-up { opacity: 0; transform: translateY(18px); transition: opacity .6s ease, transform .6s ease; }
.fade-up.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .fade-up { opacity: 1; transform: none; transition: none; }
  .scroll-cue span { animation: none; }
  .pill:hover { transform: none; }
}

/* ---- Responsive ----------------------------------------------------------- */
@media (max-width: 1023px) {
  .utility { display: none; }
  .nav { background: color-mix(in srgb, var(--navy-900) 55%, transparent); }
  .nav-row { min-height: 68px; }
  .brand-logo { max-height: 40px; }
  .nav-links {
    position: fixed; inset: 68px 0 0 0; z-index: 30;
    flex-direction: column; gap: 0; padding: 12px var(--gutter) 24px;
    background: var(--navy-900); transform: translateX(100%); transition: transform .25s ease;
  }
  .nav-links.open { transform: none; }
  .nav-links li { border-bottom: 1px solid rgba(255,255,255,.1); }
  .nav-links a { display: block; padding: 16px 0; font-size: .95rem; }
  .nav-mobile-only { display: block; }
  .nav-phone { display: none; }
  .nav-burger { display: flex; }
  .nav-actions .pill-white { min-height: 42px; padding: 0 18px; font-size: .85rem; }

  /* Single column below 1024: the copy now spans the WHOLE band, including the side the
     desktop tint deliberately lightened, so the horizontal falloff is replaced by an even
     scrim. Lightening the desktop tint without this would have put white hero text over a
     bright office photo at 390. */
  .hero-tint {
    background:
      linear-gradient(180deg, color-mix(in srgb, var(--navy-900) 88%, transparent) 0%, color-mix(in srgb, var(--navy-900) 70%, transparent) 42%, color-mix(in srgb, var(--navy-900) 86%, transparent) 100%),
      color-mix(in srgb, var(--duotone) 22%, transparent);
  }
  .hero-grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "copy" "card" "stats";
    padding-top: 100px; padding-bottom: 56px; row-gap: 0;
  }
  .hero-frame { min-height: 0; }
  .hero-photo { object-position: 62% 40%; }
  .float-card { justify-self: stretch; width: 100%; margin-top: 36px; }
  .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 40px; }
  .hero-call { display: inline-flex; }

  .proof-card { grid-template-columns: minmax(0, 1fr); }
  .proof-photo img { max-width: 280px; }
  .why-grid { grid-template-columns: minmax(0, 1fr); }
  .why-photo { position: static; }
  .why-photo img { aspect-ratio: 16 / 10; }
  .steps-list { grid-template-columns: minmax(0, 1fr); }
  .band-row { grid-template-columns: minmax(0, 1fr); }
  .service-grid { grid-template-columns: minmax(0, 1fr); }
  .review-grid { grid-template-columns: minmax(0, 1fr); }
  .faq-grid, .resources-row, .contact-grid { grid-template-columns: minmax(0, 1fr); gap: 32px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 560px) {
  body { font-size: 16px; }
  .hero-grid { padding-top: 92px; }
  .field-row { grid-template-columns: 1fr; gap: 0; }
  .contact-offices { grid-template-columns: minmax(0, 1fr); }
  .footer-grid { grid-template-columns: minmax(0, 1fr); }
  .stats { gap: 18px 16px; }
  .preview-badge { right: 8px; bottom: 8px; }
  .preview-badge-info { display: none; }
}
