/* ============================================================================
   niftimobility.com — SITE STYLES
   Hand-written. No framework, no page builder, no preprocessor.
   Reads tokens.css. Load order: tokens.css, then this file.
   ========================================================================== */

/* ---------------------------------------------------------------- reset --- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Anchor targets must not land under the sticky header. */
  scroll-padding-top: calc(var(--header-h) + var(--s-5));
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1, h2, h3, h4, p, ul, ol, blockquote, figure { margin: 0; }
ul, ol { padding: 0; list-style: none; }

img, svg, picture { display: block; max-width: 100%; height: auto; }

a { color: var(--orange-d); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--ink); }

button, input, textarea { font: inherit; color: inherit; }

/* One visible focus style for the whole site. Never remove it — only replace
   it with something at least as visible. */
:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
  border-radius: 3px;
}

::selection { background: var(--soft); color: var(--ink); }

/* ------------------------------------------------------------ scaffolding - */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: clamp(1.25rem, 0.6rem + 2.6vw, 2.75rem);
}
.shell--narrow { max-width: var(--shell-narrow); }

.section { padding-block: var(--section-y); }
.section--wash { background: var(--wash); }
.section--paper { background: var(--paper); }

/* A hairline that reads on cream. Used between major sections instead of a
   heavier border, so the page feels like a printed spread. */
.rule { height: 1px; background: var(--line-2); border: 0; margin: 0; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: var(--s-4); top: var(--s-4);
  z-index: 200;
  transform: translateY(-200%);
  background: var(--ink); color: #fff;
  padding: var(--s-3) var(--s-5);
  border-radius: var(--r-sm);
  font-size: var(--fs-sm); font-weight: 700;
  text-decoration: none;
  transition: transform var(--dur-fast) var(--ease);
}
.skip-link:focus-visible { transform: translateY(0); color: #fff; }

/* ------------------------------------------------------------- typography - */

.eyebrow {
  font-size: var(--fs-eyebrow);
  font-weight: 800;
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--orange-d);
  line-height: 1;
  margin-bottom: var(--s-4);
  display: flex;
  align-items: center;
  gap: var(--s-3);
}
/* The small rule beside an eyebrow is the one recurring ornament on the site. */
.eyebrow::before {
  content: "";
  width: 28px; height: 2px;
  background: var(--orange);
  flex: none;
}

.h1 {
  font-family: var(--display);
  font-weight: 400;              /* Archivo Black has one weight */
  font-size: var(--fs-hero);
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-tight);
  text-wrap: balance;
}

/* Section headings deliberately do NOT use Archivo Black. Reserving the
   display face for the wordmark and hero is what gives this site its calmer
   parent-brand register while staying inside the family palette + fonts. */
.h2 {
  font-size: var(--fs-h2);
  font-weight: 800;
  line-height: var(--lh-snug);
  letter-spacing: var(--tr-tight);
  text-wrap: balance;
}

.h3 {
  font-size: var(--fs-h3);
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.h4 {
  font-size: var(--fs-h4);
  font-weight: 800;
  line-height: 1.4;
}

/* Standfirst — the grey line under a section heading. */
.standfirst {
  font-size: var(--fs-lede);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 56ch;
  margin-top: var(--s-4);
  text-wrap: pretty;
}

/* Lede — the bold opening statement inside a section body. */
.lede {
  font-size: var(--fs-lede);
  line-height: 1.5;
  font-weight: 700;
  letter-spacing: -0.012em;
  color: var(--ink);
  max-width: 46ch;
  text-wrap: pretty;
}

.prose > * + * { margin-top: var(--s-5); }
.prose { max-width: var(--measure); color: var(--ink-3); text-wrap: pretty; }
.prose strong { color: var(--ink); font-weight: 700; }
.prose em { font-style: italic; }

.muted { color: var(--muted); }
.text-sm { font-size: var(--fs-sm); }

/* Pull quote — used for the two aphorisms in the copy. */
.pullquote {
  font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.75rem);
  line-height: 1.4;
  font-weight: 700;
  font-style: italic;
  letter-spacing: -0.015em;
  color: var(--ink);
  max-width: 34ch;
  padding-left: var(--s-5);
  border-left: 3px solid var(--orange);
  text-wrap: pretty;
}
.pullquote--center {
  margin-inline: auto;
  text-align: center;
  border-left: 0;
  padding-left: 0;
  padding-block: var(--s-5);
  border-top: 1px solid var(--line-2);
  border-bottom: 1px solid var(--line-2);
  max-width: 42ch;
}

/* ---------------------------------------------------------------- header -- */

.site-header {
  position: sticky; top: 0; z-index: 100;
  min-height: var(--header-h);
  display: flex; align-items: center;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease),
              background   var(--dur) var(--ease),
              box-shadow   var(--dur) var(--ease);
}
@supports (backdrop-filter: blur(1px)) {
  .site-header { backdrop-filter: saturate(180%) blur(14px); }
}
/* .is-stuck is toggled by site.js once the page has scrolled. Without JS the
   header simply stays in its flat state — no loss of function. */
.site-header.is-stuck {
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  border-bottom-color: var(--line-2);
  box-shadow: var(--shadow-1);
}

.header-bar {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s-5);
}

/* Wordmark: mark + two-tone name, the same two-tone convention as
   brand.py's wordmark_html(). */
.wordmark {
  display: inline-flex; align-items: center;
  text-decoration: none; color: var(--ink);
  flex: none;
}
.wordmark__text {
  font-family: var(--display);
  font-size: clamp(1.25rem, 1.13rem + 0.5vw, 1.5rem);
  letter-spacing: -0.03em;
  line-height: 1;
  white-space: nowrap;
}
.wordmark__text .dot { color: var(--orange); }
.wordmark__sub {
  display: block;
  font-family: var(--body);
  font-weight: 700;
  font-size: 0.625rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--muted);
  margin-top: 5px;
}

.nav { display: flex; align-items: center; gap: clamp(1rem, 0.3rem + 1.4vw, 2rem); }
.nav a {
  color: var(--ink);
  font-size: var(--fs-sm); font-weight: 600;
  text-decoration: none;
  padding-block: 4px;
  position: relative;
}
.nav a::after {
  content: ""; position: absolute;
  left: 0; right: 0; bottom: 0; height: 2px;
  background: var(--orange);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur) var(--ease);
}
.nav a:hover::after,
.nav a[aria-current="true"]::after { transform: scaleX(1); }
.nav a[aria-current="true"] { color: var(--orange-d); }

.header-actions { display: flex; align-items: center; gap: var(--s-4); }

/* --------------------------------------------------------------- buttons -- */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  border: 1.5px solid transparent;
  border-radius: var(--r-pill);
  padding: 0.8125rem 1.5rem;
  font-size: var(--fs-sm); font-weight: 700;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease),
              color      var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              transform  var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.btn:active { transform: translateY(1px); }

.btn--primary { background: var(--ink); color: #fff; }
.btn--primary:hover { background: var(--orange-d); color: #fff; box-shadow: var(--shadow-2); }

.btn--accent { background: var(--orange); color: #fff; }
.btn--accent:hover { background: var(--orange-d); color: #fff; box-shadow: var(--shadow-2); }

.btn--ghost { border-color: var(--ink); color: var(--ink); background: transparent; }
.btn--ghost:hover { background: var(--ink); color: #fff; }

.btn--sm { padding: 0.5625rem 1.125rem; font-size: var(--fs-xs); }
.btn--lg { padding: 1rem 1.875rem; font-size: 1rem; }

/* Text link with a sliding arrow. Used for every "read more" affordance. */
.link-arrow {
  display: inline-flex; align-items: baseline; gap: 0.5em;
  font-weight: 700; font-size: var(--fs-sm);
  color: var(--orange-d);
  text-decoration: none;
}
.link-arrow__arrow { transition: transform var(--dur) var(--ease-out); }
.link-arrow:hover { color: var(--ink); }
.link-arrow:hover .link-arrow__arrow { transform: translateX(5px); }

/* ------------------------------------------------------------------ hero -- */

.hero { padding-block: clamp(3.5rem, 1.8rem + 7vw, 8.5rem) var(--section-y); }
/* Two columns from 940px: headline left, supporting text and actions right,
   bottom-aligned so the headline's last line and the first CTA share a baseline.
   Below 940px it collapses to one column and the headline runs full width.

   NOTE on `ch`: never put a ch-based max-width on the hero WRAPPER. `ch`
   resolves against the element's OWN font-size, so 22ch on a wrapper set in
   18px body text is about 200px — which crushed the 72px headline into one word
   per line and left the right half of the screen empty. A measure in ch belongs
   on the element that actually carries the large type. */
.hero__grid {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: 1fr;
}
@media (min-width: 940px) {
  .hero__grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
    gap: clamp(2.5rem, 1rem + 4vw, 5.5rem);
    align-items: end;
  }
}

.hero .h1 { max-width: 15ch; }   /* on the h1 itself — about 3 lines at full size */

.hero__body { max-width: 44ch; }
.hero__body p { font-size: var(--fs-lede); line-height: 1.55; color: var(--ink-2); }
.hero__body p + p { margin-top: var(--s-4); }
.hero__actions {
  margin-top: var(--s-6);
  display: flex; flex-wrap: wrap; gap: var(--s-4); align-items: center;
}

/* A wide, quiet strip of the brand family under the hero. */
.family-strip {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: var(--s-3) var(--s-5);
  padding-top: var(--s-7);
  margin-top: var(--s-7);
  border-top: 1px solid var(--line-2);
  font-size: var(--fs-xs);
  color: var(--muted);
}
.family-strip dt {
  font-weight: 800; text-transform: uppercase; letter-spacing: var(--tr-wide);
}
.family-strip dd { margin: 0; }

/* --------------------------------------------------------- section layout - */

/* Two-column editorial split: heading rail on the left, body on the right.
   Collapses to a single column below 900px. */
.split {
  display: grid;
  gap: var(--s-6) clamp(2rem, 0.5rem + 4vw, 5rem);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .split { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--s-8); }
  .split__head { position: sticky; top: calc(var(--header-h) + var(--s-6)); align-self: start; }
}

/* ------------------------------------------------------------ focus list -- */

/* The ✓ lists from the live site, rebuilt as a real <ul>. The check is a
   pseudo-element so screen readers announce list items, not decorative glyphs. */
.focus-list { display: grid; gap: var(--s-3); }
.focus-list--2col { grid-template-columns: 1fr; }
@media (min-width: 620px) { .focus-list--2col { grid-template-columns: 1fr 1fr; gap: var(--s-3) var(--s-5); } }

.focus-list li {
  position: relative;
  padding-left: 2rem;
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--ink-3);
}
.focus-list li::before {
  content: "";
  position: absolute; left: 0; top: 0.44em;
  width: 1.125rem; height: 1.125rem;
  border-radius: var(--r-pill);
  background: var(--soft) center / 0.6875rem no-repeat;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M1.6 6.4l2.6 2.6L10.4 2.8' fill='none' stroke='%23ea580c' stroke-width='2.1' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Longer, sentence-length items read better single-column with more air. */
.focus-list--prose li { padding-left: 2.25rem; }
.focus-list--prose { gap: var(--s-4); }

/* ----------------------------------------------------------------- cards -- */

.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 1rem + 2vw, 2.75rem);
  box-shadow: var(--shadow-1);
}

/* ---------------------------------------------------------- service grid -- */
/* The four service pillars. Two columns on wider screens, one on a phone.
   Each cell is a .card, so padding/border/elevation are inherited — this only
   lays them out and lets the "learn more" link sit flush at the bottom. */
.service-grid {
  display: grid;
  gap: var(--s-5);
  grid-template-columns: 1fr;
  margin-top: var(--s-7);
}
@media (min-width: 720px) {
  .service-grid { grid-template-columns: 1fr 1fr; gap: var(--s-6); }
}
.service-card { display: flex; flex-direction: column; }
.service-card > * + * { margin-top: var(--s-4); }
.service-card h3 { margin: 0; }
.service-card .focus-list { margin-top: var(--s-2); }
.service-card__more { margin-top: auto; padding-top: var(--s-4); }

/* Featured perspective — the one editorially "loud" block on the home page. */
.feature {
  display: grid;
  gap: var(--s-6);
  grid-template-columns: 1fr;
  align-items: start;
}
@media (min-width: 860px) {
  .feature { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); gap: var(--s-8); align-items: center; }
}
.feature__media {
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--wash);
  box-shadow: var(--shadow-2);
}
.feature__media img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.feature:hover .feature__media img { transform: scale(1.025); }

/* The inline artwork variant. No shadow and no crop — it is a drawing on the
   page, not a photograph in a frame, so it sits on the section background. */
.feature__media--art {
  background: transparent;
  box-shadow: none;
  overflow: visible;
  padding: var(--s-4);
}
.feature__body > * + * { margin-top: var(--s-4); }
.feature__meta {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4);
  font-size: var(--fs-xs); color: var(--muted);
  font-weight: 600;
}
.feature__meta .dot-sep::before { content: "·"; margin-right: var(--s-4); color: var(--line-2); }

.tag {
  display: inline-block;
  background: var(--soft); color: var(--orange-d);
  border-radius: var(--r-pill);
  padding: 0.25rem 0.75rem;
  font-size: var(--fs-xs); font-weight: 800;
  letter-spacing: 0.02em;
}

/* ------------------------------------------------------------------ form -- */

.form { display: grid; gap: var(--s-5); }
.field { display: grid; gap: var(--s-2); }

.field label {
  font-size: var(--fs-eyebrow);
  font-weight: 800;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
}
.field input, .field textarea {
  width: 100%;
  padding: 0.8125rem 1rem;
  background: var(--paper);
  border: 1.5px solid var(--line-2);
  border-radius: var(--r);
  font-size: 1rem;
  transition: border-color var(--dur-fast) var(--ease),
              box-shadow   var(--dur-fast) var(--ease);
}
.field textarea { min-height: 8.5rem; resize: vertical; }
.field input:hover, .field textarea:hover { border-color: var(--muted); }
.field input:focus, .field textarea:focus {
  outline: 0;
  border-color: var(--orange);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--orange) 16%, transparent);
}
.field input[aria-invalid="true"], .field textarea[aria-invalid="true"] { border-color: var(--red); }
.field__error { font-size: var(--fs-xs); color: var(--red); font-weight: 600; }
.field__error:empty { display: none; }

/* Honeypot. Bots fill it, humans never see it. Must not be display:none —
   some bots skip hidden fields. */
.hp { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }

.form-note { font-size: var(--fs-sm); color: var(--muted); max-width: 48ch; }

/* Server/JS response message. Styled once, like brand.py's .flash. */
.notice {
  border-radius: var(--r);
  padding: var(--s-4) var(--s-5);
  font-size: var(--fs-sm); line-height: 1.55;
  display: flex; gap: var(--s-3); align-items: flex-start;
  border: 1px solid var(--line-2);
  background: var(--paper);
}
.notice::before { flex: none; font-size: 1.05rem; line-height: 1.45; }
.notice.is-ok  { background: #e7f4ec; border-color: #bfe3cc; border-left: 4px solid var(--green); }
.notice.is-ok::before  { content: "\2713"; color: var(--green); }
.notice.is-err { background: var(--soft); border-color: #f6d3ad; border-left: 4px solid var(--orange); }
.notice.is-err::before { content: "\26A0"; color: var(--orange-d); }
.notice[hidden] { display: none; }

/* ---------------------------------------------------------------- contact - */

.contact {
  display: grid; gap: var(--s-7);
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .contact { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: var(--s-8); align-items: start; }
}
.contact__aside > * + * { margin-top: var(--s-5); }

.contact-details {
  font-size: var(--fs-body);
  line-height: 1.7;
  font-style: normal;   /* it is an <address>, but it should not be italic */
}
.contact-details a { font-weight: 600; }

/* ---------------------------------------------------------------- article - */

.article-header { padding-block: clamp(2.5rem, 1.5rem + 4vw, 5rem) var(--s-6); }
.article-header .h1 { max-width: 26ch; }

.article__deck {
  font-size: var(--fs-lede);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 54ch;
  margin-top: var(--s-5);
  text-wrap: pretty;
}
.article__byline {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4);
  margin-top: var(--s-6);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line-2);
  font-size: var(--fs-sm); color: var(--muted);
}
.article__byline strong { color: var(--ink); font-weight: 700; }

/* The article opens on the inline artwork rather than a photograph, so it gets
   air instead of a frame — no border, no shadow, no crop. */
.article__hero {
  margin-block: var(--s-5) var(--s-8);
}
.article__hero .artwork { max-width: 40rem; margin-inline: auto; }

/* Long-form body. Everything inside .article-body is authored as plain
   semantic HTML — headings, paragraphs, lists — and styled here, so the
   markup stays readable and the copy stays editable. */
.article-body {
  max-width: var(--measure);
  margin-inline: auto;
  color: var(--ink-3);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  text-wrap: pretty;
}
.article-body > * + * { margin-top: var(--s-5); }

.article-body strong { color: var(--ink); font-weight: 700; }

/* A standalone bold paragraph is a rhetorical beat in this writing, not a
   heading. Give it weight without promoting it in the document outline. */
.article-body .beat {
  font-size: var(--fs-lede);
  line-height: 1.45;
  font-weight: 700;
  letter-spacing: -0.012em;
  color: var(--ink);
  margin-top: var(--s-7);
}

.article-body h2 {
  font-size: var(--fs-h3);
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--ink);
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line-2);
  text-wrap: balance;
}

/* The nine numbered "trust" sections. The number is generated, so the
   heading text stays clean and reorderable. */
.article-body .trust-h {
  counter-increment: trust;
  display: flex; align-items: baseline; gap: var(--s-4);
  border-top: 1px solid var(--line-2);
}
.article-body { counter-reset: trust; }
.article-body .trust-h::before {
  content: counter(trust);
  font-family: var(--display);
  font-size: 0.8em;
  color: var(--orange);
  line-height: 1;
  flex: none;
  font-feature-settings: "tnum";
}

.article-body ul { display: grid; gap: var(--s-3); padding-left: 0; }
.article-body ul li { position: relative; padding-left: 1.5rem; }
.article-body ul li::before {
  content: ""; position: absolute; left: 0.25rem; top: 0.68em;
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--orange);
}

.article-body .pullquote { margin-block: var(--s-7); }

.article-body figure { margin-block: var(--s-7); }
.article-body figcaption {
  margin-top: var(--s-3);
  font-size: var(--fs-xs); color: var(--muted);
}

.article-sig {
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 2px solid var(--ink);
  font-size: var(--fs-sm);
}
.article-sig strong { display: block; font-size: var(--fs-body); color: var(--ink); }

/* Reading progress bar. Purely additive — no JS, no bar, no harm. */
.progress {
  position: fixed; top: 0; left: 0; z-index: 150;
  height: 3px; width: 100%;
  transform: scaleX(0); transform-origin: left;
  background: var(--orange);
  will-change: transform;
}

/* --------------------------------------------------------------- legal ---- */

.legal-body { max-width: var(--measure); }
.legal-body > * + * { margin-top: var(--s-5); }
.legal-body h2 {
  font-size: var(--fs-h3); font-weight: 800; letter-spacing: -0.015em;
  color: var(--ink);
  margin-top: var(--s-8); padding-top: var(--s-5);
  border-top: 1px solid var(--line-2);
}
.legal-body h3 {
  font-size: var(--fs-h4); font-weight: 800; color: var(--ink);
  margin-top: var(--s-6);
}
.legal-body ul { display: grid; gap: var(--s-2); }
.legal-body ul li { position: relative; padding-left: 1.5rem; }
.legal-body ul li::before {
  content: ""; position: absolute; left: 0.25rem; top: 0.68em;
  width: 5px; height: 5px; border-radius: 50%; background: var(--orange);
}
.legal-body .updated {
  display: inline-block;
  background: var(--soft); color: var(--orange-d);
  border-radius: var(--r-pill); padding: 0.25rem 0.875rem;
  font-size: var(--fs-xs); font-weight: 800;
}
.legal-toc {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--s-5);
  display: grid; gap: var(--s-2);
}
.legal-toc a { font-size: var(--fs-sm); font-weight: 600; }

/* ---------------------------------------------------------------- footer -- */

.site-footer {
  background: var(--ink);
  color: #cfcbc4;
  padding-block: var(--s-8) var(--s-6);
  font-size: var(--fs-sm);
}
.site-footer a { color: #fff; text-decoration: none; }
.site-footer a:hover { color: var(--orange); text-decoration: underline; }

.footer-grid {
  display: grid; gap: var(--s-7);
  grid-template-columns: 1fr;
}
@media (min-width: 780px) {
  .footer-grid { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 1.2fr); gap: var(--s-8); }
}
.footer-grid .wordmark { color: #fff; }
.footer-grid .wordmark__text { color: #fff; }
.footer-grid .wordmark__sub { color: #8d8880; }

.footer-h {
  font-size: var(--fs-eyebrow); font-weight: 800;
  letter-spacing: var(--tr-wide); text-transform: uppercase;
  color: #8d8880;
  margin-bottom: var(--s-4);
}
.footer-links { display: grid; gap: var(--s-3); }

.footer-newsletter { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.footer-newsletter input {
  flex: 1 1 12rem; min-width: 0;
  padding: 0.75rem 1rem;
  background: #232320; color: #fff;
  border: 1.5px solid #3a3a35; border-radius: var(--r);
  font-size: 1rem;
}
.footer-newsletter input::placeholder { color: #7d7871; }
.footer-newsletter input:focus {
  outline: 0; border-color: var(--orange);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--orange) 22%, transparent);
}

.social-row { display: flex; gap: var(--s-3); }
.social {
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 1.5px solid #3a3a35; border-radius: var(--r-pill);
  color: #fff;
  transition: border-color var(--dur-fast) var(--ease),
              background   var(--dur-fast) var(--ease);
}
.social:hover { background: var(--orange); border-color: var(--orange); }
.social svg { width: 18px; height: 18px; fill: currentColor; }

.footer-bottom {
  margin-top: var(--s-8); padding-top: var(--s-5);
  border-top: 1px solid #2c2c28;
  display: flex; flex-wrap: wrap; gap: var(--s-3) var(--s-5);
  justify-content: space-between; align-items: center;
  font-size: var(--fs-xs); color: #8d8880;
}
.footer-bottom nav { display: flex; flex-wrap: wrap; gap: var(--s-5); }

/* ------------------------------------------------------------ to-top ----- */

.to-top {
  position: fixed; right: clamp(1rem, 2vw, 2rem); bottom: clamp(1rem, 2vw, 2rem);
  z-index: 90;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  background: var(--ink); color: #fff;
  border: 0; border-radius: var(--r-pill);
  box-shadow: var(--shadow-3);
  cursor: pointer;
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              visibility var(--dur) var(--ease),
              background var(--dur-fast) var(--ease);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.to-top:hover { background: var(--orange-d); }
.to-top svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.2; }

/* --------------------------------------------------------- mobile nav ---- */

.nav-toggle { display: none; }

@media (max-width: 860px) {
  .nav-toggle {
    display: grid; place-items: center;
    width: 44px; height: 44px;
    background: transparent; border: 1.5px solid var(--line-2);
    border-radius: var(--r-pill); cursor: pointer;
    color: var(--ink);
  }
  .nav-toggle svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; }
  .nav-toggle .icon-close { display: none; }
  .nav-toggle[aria-expanded="true"] .icon-open  { display: none; }
  .nav-toggle[aria-expanded="true"] .icon-close { display: block; }

  .nav {
    position: fixed;
    inset: var(--header-h) 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--bg);
    border-bottom: 1px solid var(--line-2);
    box-shadow: var(--shadow-3);
    padding: var(--s-3) clamp(1.25rem, 0.6rem + 2.6vw, 2.75rem) var(--s-6);
    /* Closed state. `visibility` (not display:none) so the transition runs and
       so a keyboard user cannot tab into a hidden menu. */
    opacity: 0; visibility: hidden;
    transform: translateY(-8px);
    transition: opacity var(--dur) var(--ease),
                transform var(--dur) var(--ease),
                visibility var(--dur) var(--ease);
  }
  .nav.is-open { opacity: 1; visibility: visible; transform: translateY(0); }
  .nav a {
    font-size: 1.125rem; font-weight: 700;
    padding-block: var(--s-4);
    border-bottom: 1px solid var(--line);
  }
  .nav a::after { display: none; }
  .nav .btn { margin-top: var(--s-5); justify-content: center; }

  /* The header CTA moves into the menu on small screens so the bar stays clean. */
  .header-actions .btn { display: none; }
}

@media (min-width: 861px) {
  .nav .nav__cta { display: none; }   /* menu-only duplicate of the CTA */
}

/* Locks background scroll while the mobile menu is open. */
body.nav-open { overflow: hidden; }

/* ========================================================== MOTION SYSTEM ===
   Rules this follows, so it stays craft and not decoration:

   1. THE STATIC STATE IS THE FINISHED STATE. Every hidden state is applied by
      JS (gated on the .js class) and only ever by code that can also remove it.
      No JS, no motion, nothing missing.
   2. ONCE ONLY. Nothing re-animates on scroll-back. Re-triggering reads as a
      toy; the second viewing should be quiet.
   3. TRANSFORM AND OPACITY ONLY. Both are compositor properties, so none of
      this touches layout or costs a repaint.
   4. REDUCED MOTION IS OFF, NOT SLOW. The block at the end of this section
      disables the lot.
   ========================================================================= */

/* --------------------------------------------------------- reveal motion -- */

.js .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity var(--dur-slow) var(--ease-out),
              transform var(--dur-slow) var(--ease-out);
}
.js .reveal.is-in { opacity: 1; transform: none; }
.js .reveal--d1 { transition-delay: 70ms; }
.js .reveal--d2 { transition-delay: 140ms; }
.js .reveal--d3 { transition-delay: 210ms; }

/* ------------------------------------------------------- headline reveal -- */

/* site.js wraps each word of the hero headline in .word > span. The outer span
   is the mask; the inner one slides up inside it, so the words rise out of an
   invisible baseline rather than fading in place. This is the single most
   "designed" moment on the site, so it gets the longest easing. */
.word {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  padding-bottom: 0.06em;     /* room for descenders inside the mask */
}
.word > span {
  display: inline-block;
  will-change: transform;
}
.js .headline-anim .word > span {
  transform: translateY(105%);
  transition: transform 900ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 42ms);
}
.js .headline-anim.is-in .word > span { transform: translateY(0); }

/* ---------------------------------------------------------- stagger rows -- */

/* Applied to a list or grid: children arrive in sequence rather than as a
   block. --i is set by JS so the delay does not have to be hand-written. */
.js .stagger > * {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 620ms var(--ease-out), transform 620ms var(--ease-out);
  transition-delay: calc(var(--i, 0) * 55ms);
}
.js .stagger.is-in > * { opacity: 1; transform: none; }

/* --------------------------------------------------------- quote entrance - */

/* Pull quotes settle rather than slide: a slight scale-up reads as the line
   being placed down, which suits an aphorism. */
.js .pullquote.reveal {
  transform: translateY(16px) scale(.985);
  transform-origin: left center;
  transition: opacity 760ms var(--ease-out), transform 760ms var(--ease-out);
}
.js .pullquote--center.reveal { transform-origin: center; }
.js .pullquote.reveal.is-in { transform: none; }

/* The accent rule on a left-bordered pull quote draws itself downward. */
.pullquote { position: relative; }
.js .pullquote:not(.pullquote--center)::before {
  content: "";
  position: absolute; left: -3px; top: 0; bottom: 0; width: 3px;
  background: var(--orange);
  transform: scaleY(0); transform-origin: top;
  transition: transform 820ms var(--ease-out) 160ms;
}
.js .pullquote:not(.pullquote--center) { border-left-color: transparent; }
.js .pullquote:not(.pullquote--center).is-in::before { transform: scaleY(1); }

/* -------------------------------------------------------- eyebrow rule ---- */

/* The little orange dash beside every eyebrow draws in from nothing. It is the
   site's recurring ornament, so animating it ties the sections together. */
.js .reveal .eyebrow::before,
.js .eyebrow.reveal::before {
  transform: scaleX(0); transform-origin: left;
  transition: transform 640ms var(--ease-out) 120ms;
}
.js .reveal.is-in .eyebrow::before,
.js .eyebrow.reveal.is-in::before { transform: scaleX(1); }

/* ------------------------------------------------------------- artwork ---- */

.artwork { width: 100%; height: auto; display: block; }

.js .artwork__plane,
.js .artwork__node { opacity: 0; }

.js .artwork.is-in .artwork__plane {
  animation: plane-in 900ms var(--ease-out) forwards;
  animation-delay: calc(var(--i) * 130ms);
}
.js .artwork.is-in .artwork__node {
  animation: node-in 520ms var(--ease-out) forwards;
  animation-delay: calc(760ms + var(--i) * 90ms);
}

/* The planes keep the opacity authored in the SVG — the keyframe animates to
   `inherit`-like values by using a wrapper fade instead of overriding each. */
@keyframes plane-in {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}
@keyframes node-in {
  from { opacity: 0; transform: scale(.2); }
  to   { opacity: 1; transform: none; }
}
.artwork__plane, .artwork__node { transform-box: fill-box; transform-origin: center; }

.js .artwork__glow { opacity: 0; transition: opacity 1200ms var(--ease-out) 400ms; }
.js .artwork.is-in .artwork__glow { opacity: 1; }

.js .artwork__trust {
  opacity: 0; transform: translateY(-22px);
  transition: opacity 1000ms var(--ease-out) 520ms,
              transform 1000ms var(--ease-out) 520ms;
}
.js .artwork.is-in .artwork__trust { opacity: 1; transform: none; }

/* The dashed spine draws itself, then travels upward a few times and stops.
   DELIBERATELY FINITE. `stroke-dashoffset` is not a compositor property — every
   frame is a real repaint — so an infinite loop here would burn CPU and battery
   forever for the sake of decoration, on a page the visitor may leave open. It
   also broke the "once only" rule the rest of this system follows.
   Five passes reads as movement; then the drawing settles. */
.js .artwork__spine {
  stroke-dashoffset: 240;
  transition: stroke-dashoffset 1100ms var(--ease-out) 420ms;
}
.js .artwork.is-in .artwork__spine {
  stroke-dashoffset: 0;
  animation: spine-travel 2.4s linear 1.6s 5;
}
@keyframes spine-travel { to { stroke-dashoffset: -40; } }

/* ------------------------------------------------------- article rail ----- */

/* Sticky section navigation for the long read. Desktop only — on a phone it
   would eat the screen, and the reading-progress bar already answers "how much
   is left". */
/* Below the rail breakpoint the article is one centred column. --article-col is
   the single source for that width, used by both layouts, so the header, the
   artwork and the body can never end up on different left edges. */
:root { --article-col: 40rem; }

.article-layout { max-width: var(--article-col); margin-inline: auto; }
.article-layout .article-body { max-width: none; margin-inline: 0; }

.article-rail { display: none; }

@media (min-width: 1180px) {
  .article-layout {
    display: grid;
    grid-template-columns: minmax(0, 14rem) minmax(0, var(--article-col));
    column-gap: var(--s-8);
    justify-content: center;
    max-width: none;
  }
  /* Everything that is not the rail lives in the second column. */
  .article-layout > *:not(.article-rail) { grid-column: 2; }

  .article-rail {
    display: block;
    grid-column: 1;
    grid-row: 1 / -1;          /* span the whole article so sticky has room */
    align-self: start;
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
    max-height: calc(100vh - var(--header-h) - var(--s-8));
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: var(--s-3);
  }
  .article-rail::-webkit-scrollbar { width: 3px; }
  .article-rail::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 3px; }
}

.article-rail__h {
  font-size: var(--fs-eyebrow); font-weight: 800;
  letter-spacing: var(--tr-wide); text-transform: uppercase;
  color: var(--muted);
  margin-bottom: var(--s-4);
}
.article-rail ol { display: grid; gap: 2px; counter-reset: rail; }
.article-rail a {
  display: block;
  padding: 7px 0 7px var(--s-4);
  border-left: 2px solid var(--line-2);
  font-size: var(--fs-xs); font-weight: 600; line-height: 1.4;
  color: var(--muted);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease),
              padding-left var(--dur) var(--ease);
}
.article-rail a:hover { color: var(--ink); border-left-color: var(--muted); }
.article-rail a[aria-current="true"] {
  color: var(--ink);
  border-left-color: var(--orange);
  padding-left: calc(var(--s-4) + 4px);
}

/* ------------------------------------------------- trust-layer numerals --- */

/* The generated numbers on the nine trust headings scale up as they arrive,
   so the count reads as a sequence rather than static decoration. */
.js .article-body .trust-h::before {
  display: inline-block;
  opacity: 0; transform: translateY(8px) scale(.7);
  transition: opacity 520ms var(--ease-out), transform 520ms var(--ease-out);
}
.js .article-body .trust-h.is-in::before { opacity: 1; transform: none; }

/* ------------------------------------------------------------ hero wash --- */

/* A very slow drift inside the hero. On the cream hero (inner pages) it is a
   faint warm glow; on the orange home hero it becomes light, which gives the
   flat gradient some depth. Either way it is felt rather than seen. */
.hero { position: relative; isolation: isolate; overflow: hidden; }
.hero::before {
  content: "";
  position: absolute; z-index: -1;
  inset: -30% -10% auto -10%;
  height: 130%;
  background:
    radial-gradient(58% 48% at 78% 18%, rgba(249,115,22,.13), transparent 68%),
    radial-gradient(46% 42% at 12% 72%, rgba(249,115,22,.07), transparent 70%);
  animation: hero-drift 26s var(--ease) infinite alternate;
  pointer-events: none;
  /* This one IS allowed to loop forever: it animates `transform` only, which the
     compositor handles without repainting. `will-change` promotes it to its own
     layer so the gradient is rasterised once and merely moved thereafter —
     without it, the scale step can force a re-raster on every keyframe. */
  will-change: transform;
}
@keyframes hero-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-3%, 2%, 0) scale(1.09); }
}

/* ======================================================= HOME HERO: ORANGE ==
   A full orange field behind the home-page hero, with the header floating over
   it — the same move as niftilease.com, so the two sites read as siblings.

   SCOPED TO .page-home ONLY. The article and legal pages keep the cream header,
   because a long read does not want a shout at the top of it.

   HOW THE HEADER FLOATS
     The header stays `position: sticky`, so it still occupies layout space. The
     hero is pulled up underneath it by exactly one header height and pads that
     space back on. The header has a higher z-index, so the orange runs behind
     it with no fixed-positioning and no scroll-jank.

   THE HEADER'S DEFAULT STATE IS TRANSPARENT, ON PURPOSE
     If JavaScript never runs, the header stays transparent for the whole page —
     ink on cream, perfectly readable. The solid state is the enhancement, added
     by site.js once you scroll past the hero. The reverse default would leave a
     cream bar sitting on the orange with no way to remove it.
   ========================================================================== */

/* The hero sits BELOW the header, not behind it. Brett's call, and it is the
   better one: the header reads more clearly on cream, and the orange becomes a
   deliberate block rather than a wash the navigation floats in.

   It also deleted a whole class of bug. When the header overlapped the hero it
   needed a third "veiled" state, a blur, and a scroll threshold computed from
   the hero's height — all of it to stop the headline colliding with the
   wordmark on the way past. None of that exists any more. */
.page-home .hero {
  padding-top: clamp(3rem, 1.5rem + 6vw, 7rem);
  padding-bottom: clamp(3.5rem, 2rem + 6vw, 7rem);
  background: linear-gradient(118deg, var(--hero-1) 0%, var(--hero-2) 44%, var(--hero-3) 100%);
  color: var(--ink);
}

/* Light instead of warm — on orange, a warm glow is invisible. */
.page-home .hero::before {
  background:
    radial-gradient(56% 46% at 76% 14%, rgba(255,255,255,.30), transparent 70%),
    radial-gradient(50% 44% at 8% 86%, rgba(190,50,10,.24), transparent 72%);
}

.page-home .hero .h1 { color: var(--ink); }
.page-home .hero__body p { color: #241209; }  /* deep warm ink, not grey */

/* The header keeps its normal cream treatment on every page — no special case,
   no extra states. A hairline under it separates it cleanly from the orange. */
.page-home .site-header { border-bottom-color: var(--line-2); }

/* The secondary hero link is orange by default, which vanishes on orange. */
.page-home .hero .link-arrow { color: var(--ink); }
.page-home .hero .link-arrow:hover { color: #4a1a06; }

/* Solid ink pill on orange — the same lockup niftilease uses. */
.page-home .hero .btn--primary:hover { background: #241209; }

/* The strip under the hero sits on orange too. */
.page-home .family-strip {
  border-top-color: rgba(21,21,21,.22);
  color: #3d1405;
}

/* The hero supplies its own edge, so the shared hairline would double it up. */
.page-home .hero + .rule { display: none; }

@media (max-width: 860px) {
  /* The open mobile menu is a cream panel; its links must not inherit the
     over-orange ink treatment and lose their hover accent. */
  .page-home .site-header .nav.is-open a:hover { color: var(--orange-d); }
}

/* -------------------------------------------------- reduced motion: off --- */

@media (prefers-reduced-motion: reduce) {
  .js .reveal,
  .js .stagger > *,
  .js .pullquote.reveal,
  .js .artwork__plane,
  .js .artwork__node,
  .js .artwork__glow,
  .js .artwork__trust,
  .js .article-body .trust-h::before {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
    animation: none !important;
  }
  .js .headline-anim .word > span { transform: none; transition: none; }
  .js .pullquote:not(.pullquote--center) { border-left-color: var(--orange); }
  .js .pullquote:not(.pullquote--center)::before { display: none; }
  .js .reveal .eyebrow::before,
  .js .eyebrow.reveal::before { transform: none; transition: none; }
  .js .artwork.is-in .artwork__spine { animation: none; stroke-dashoffset: 0; }
  .hero::before { animation: none; }
}

/* ------------------------------------------------------------------ print - */

@media print {
  .site-header, .site-footer, .to-top, .progress, .nav-toggle, .form, .feature__media { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .article-body, .prose, .legal-body { max-width: none; color: #000; }
  a { color: #000; text-decoration: underline; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; color: #444; }
  .section { padding-block: 0.75rem; }
}
