/* ==========================================================================
   Treeline Automation — foundation
   Values are BASE values for a 1280px design width. See design-tokens.md.
   1rem = 10px at 1280px viewport.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. PROPORTIONAL SCALING
   Wix designs at 1280px and scales the whole page linearly above it
   (x1.125 at 1440px). Driving root font-size off vw reproduces that exactly.
   Clamped so it stops shrinking below 1280 and stops growing past 1920.
   -------------------------------------------------------------------------- */
html {
  font-size: 0.78125vw;            /* = 10px at 1280px */
  -webkit-text-size-adjust: 100%;
}
@media (max-width: 1280px) { html { font-size: 10px; } }
/* 14px, not 15px. At 15 the page scaled 1.5x on a 1920 monitor while the screen
   is no taller than a laptop's, which pushed the audit form and each case study
   just past the bottom of a maximized window. 14 still scales the design up 40%
   and buys back roughly 65px of height. */
@media (min-width: 1920px) { html { font-size: 14px; } }

/* --------------------------------------------------------------------------
   2. TOKENS
   -------------------------------------------------------------------------- */
:root {
  --cream:       #FBFFE7;
  --brown-dark:  #472F13;
  --brown:       #784F24;
  --sage:        #C9D29E;
  --rule:        #C5C1A7;   /* thin vertical rules (About) */
  --card-border: #86785D;   /* "What we build with" card borders */
  --tan:         #AE875D;   /* card headings (About) */
  --gold:        #E0AC4A;   /* review stars — added for the reviews band */
  --overlay:     rgba(0, 0, 0, 0.456);
  --header-bg:   rgba(251, 255, 231, 0.95);

  --font: "Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;

  --page-w:      128rem;   /* 1280px design width */
  --header-h:    6.933rem; /* 69.33px */
}

/* --------------------------------------------------------------------------
   3. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
body, h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { list-style: none; margin: 0; padding: 0; }
/* height:auto lets width/height attributes on <img> reserve layout space (CLS)
   without locking the rendered height when max-width scales the image down. */
img, picture, video { max-width: 100%; height: auto; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
button { padding: 0; background: none; border: none; }   /* UA padding breaks measured widths */
a { color: inherit; text-decoration: none; }

/* The cream lives on <html> as well as <body> so the page fade below has cream
   underneath it rather than the browser's white canvas. */
html { background: var(--cream); }

body {
  font-family: var(--font);
  font-weight: 400;
  font-size: 1.3rem;
  line-height: 2.34rem;          /* 23.4px — 1.8 ratio */
  color: var(--brown-dark);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
}

/* --------------------------------------------------------------------------
   PAGE FADE
   Every page fades in on load, so moving between pages reads as one site
   rather than a series of hard cuts. Opacity only: no transform, which would
   otherwise make <body> a containing block and unpin the fixed header.

   This is deliberately CSS on load rather than JS that fades out on click.
   A fade-out has to guess how long the next page takes to arrive, and it
   leaves the old page dimmed if the visitor cancels or the network stalls.

   It is short (0.28s) on purpose. Anything slower and every click feels like
   waiting. Scroll reveals still run on top of it for content further down.

   Gated on `.js` for the same reason the scroll reveals are: the page starts
   at opacity 0, so anything that stops the animation from running would leave
   it blank. No JS, no fade, page renders visible.
   -------------------------------------------------------------------------- */
@keyframes page-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.js body { animation: page-in 0.28s ease-out both; }

@media (prefers-reduced-motion: reduce) {
  .js body { animation: none; }
}

/* --------------------------------------------------------------------------
   4. TYPE SCALE  (base values, see design-tokens.md)
   -------------------------------------------------------------------------- */
.t-hero    { font-size: 6.0rem; line-height: 10.8rem;  letter-spacing: 0.96rem;  }
.t-display { font-size: 5.6rem; line-height: 7.84rem;  letter-spacing: normal;   }
.t-h2      { font-size: 4.8rem; line-height: 7.2rem;   letter-spacing: 0.24rem;  }
.t-stat    { font-size: 4.2rem; line-height: 6.3rem;   letter-spacing: 0.336rem; }
.t-h3      { font-size: 3.6rem; line-height: 6.48rem;  letter-spacing: 0.288rem; }
.t-h4      { font-size: 2.8rem; line-height: 4.2rem;   letter-spacing: 0.224rem; }
.t-h5      { font-size: 2.4rem; line-height: 3.6rem;   letter-spacing: 0.192rem; }
.t-lead    { font-size: 2.0rem; line-height: 2.8rem;   letter-spacing: normal;   }
.t-eyebrow { font-size: 1.8rem; line-height: 3.24rem;  letter-spacing: 0.288rem; }
.t-body    { font-size: 1.3rem; line-height: 2.34rem;  letter-spacing: normal;   }

/* --------------------------------------------------------------------------
   5. LAYOUT HELPERS
   -------------------------------------------------------------------------- */
.page {
  width: 100%;
  max-width: var(--page-w);
  margin-inline: auto;
}

/* ==========================================================================
   HEADER
   Measured: header 69.33px tall, 95% opaque cream, pinned.
   Logo box x=263 w=277; nav right-aligned; Subscribe right edge at x=1182.
   ========================================================================== */
/* Wix pins the header as a fixed overlay — it does NOT take flow space, so the
   hero starts at y=0 and its top 78px (@1440) sit behind the 95%-opaque bar.
   Using sticky here would push the page 78px taller than the original. */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  width: 100%;
  height: var(--header-h);
  background: var(--header-bg);
}

.site-header__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  height: 100%;
  display: flex;
  align-items: flex-start;  /* content sits above centre — matched to measurements */
  padding-left: 26.3rem;   /* logo box starts at x=263 */
  padding-right: 9.8rem;   /* button right edge at x=1182 */
}

/* --- logo ---------------------------------------------------------------- */
.site-header__logo {
  flex: 0 0 auto;
  width: auto;
  height: 3.47rem;
  margin-top: 1.333rem;    /* measured y=15 @1440 */
  display: flex;
  align-items: center;
  gap: 1rem;
}
/* Banner's mark plus a wordmark. The mark alone is near-square (429x481); the
   logo slot is 277x35, so a mark on its own would sit in a lot of empty space
   and the company name would never appear. Mark + wordmark fills it properly.
   The supplied logo.png had a checkerboard baked into the pixels rather than
   real transparency — assets/img/logo.png is the extracted version. */
.site-logo__mark {
  /* explicit height, not 100% — a percentage height did not resolve inside the
     header's flex row and the mark rendered 355px wide instead of ~31px */
  height: 3.2rem;
  width: auto;
  max-width: none;
  flex: 0 0 auto;
}
.site-logo__word {
  font-size: 1.9rem;
  font-weight: 700;
  letter-spacing: 0.18rem;
  color: var(--brown-dark);
  white-space: nowrap;
  text-transform: uppercase;
}

/* --- nav ----------------------------------------------------------------- */
.site-nav {
  margin-left: auto;
  margin-top: 1.867rem;    /* measured y=21 @1440 */
  display: flex;
  align-items: center;
  gap: 0.8rem;             /* measured 9px @1440 between item boxes */
}
.site-nav__link {
  font-size: 1.3rem;
  font-weight: 700;
  line-height: 2.4rem;
  color: var(--brown-dark);
  padding: 0.22rem 0.4rem;
  border-radius: 0.4rem;
  transition: color 0.18s ease;
}
.site-nav__link:hover { color: var(--brown); }
.site-nav__link[aria-current="page"] { text-decoration: underline; }

/* --- focus ring ----------------------------------------------------------
   Two-tone on purpose: the cream outline reads against the dark panels and
   the footer, the dark ring around it reads against cream and sage. One rule
   that stays visible everywhere on the site. Keyboard only — :focus-visible
   does not fire on mouse clicks. */
:focus-visible {
  outline: 2px solid var(--cream);
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--brown-dark);
  border-radius: 2px;
}

/* --- mobile-only chrome: hidden on desktop ------------------------------- */
.nav-toggle { display: none; background: none; border: none; }
/* doubled class on purpose — .btn-call sets display later in this file
   and would otherwise win on source order and show this on desktop */
.btn-call.btn-call--mobile { display: none; }

/* --- call/text button (was Subscribe) ---------------------------------------------------- */
.btn-call {
  margin-left: 3.2rem;     /* measured 36px @1440 gap after nav */
  margin-top: 1.689rem;    /* measured y=19 @1440 */
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 12rem;
  height: 3.1rem;
  background: var(--brown);
  color: var(--cream);
  border-radius: 0.8rem;
  font-size: 1.3rem;
  font-weight: 400;
  transition: filter 0.18s ease;
}
.btn-call:hover { filter: brightness(1.12); }

/* ==========================================================================
   HERO  (home §1)
   Measured @1440: section 1440x834, overlay card 922x234 at x=260 y=141,
   radius 18px, fill rgba(0,0,0,0.456), H1 54/81/2.7 cream centred.
   Card geometry uses Wix's own percentages (width 64%, margin-left 18.0695%)
   so it tracks the container at every width.
   ========================================================================== */
.hero {
  position: relative;
  width: 100%;
  height: 74.133rem;        /* 834px @1440 */
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
  isolation: isolate;       /* keeps the darken blend off the headline */
}
.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* No gradient. The video used to melt into the brown, which read as muddy.
   It now runs to a clean edge and the proof strip starts hard against it. */

/* The Wix white→black blend band was removed. It darkened the foot of the
   video toward black while .hero__gradient was already fading it to #472F13,
   so the video hit black and then the brown strip started — a visible seam.
   The gradient alone now dissolves the video straight into the proof strip. */

.hero__content {
  position: relative;
  max-width: var(--page-w);
  margin-inline: auto;
  height: 100%;
}

.hero__card {
  width: 64%;
  margin-left: 18.0695%;
  margin-top: 12.53rem;     /* 141px @1440 from section top */
  padding: 3.2rem;
  background: var(--overlay);
  border-radius: 1.6rem;
}

.hero__title {
  font-size: 4.8rem;
  line-height: 7.2rem;
  letter-spacing: 0.24rem;
  font-weight: 400;
  color: var(--cream);
  text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .hero__video { display: none; }
  .hero__media { background: url("../assets/video/hero-poster.jpg") center/cover; }
}

/* ==========================================================================
   MISSION + THE PROOF  (home §2)
   Measured @1440: section 1440x1038. Two columns — mission copy left,
   "The Proof" + a 2x2 stat grid right. All text left-aligned.
   Positions are absolute in rem so they scale with the rest of the page.
   NOTE: Wix's per-element percentage margins leave the stat columns a few px
   out of alignment (left edges 876/877/882 and 1161/1165/1170 @1440).
   Reproduced exactly — see BUILD-PLAN "known cosmetic flaws".
   ========================================================================== */
.proof {
  position: relative;
  width: 100%;
  /* was 92.267rem, copied from Wix. Content bottoms out at 632 base, so that
     left 291 of dead space before SERVICES. 69.6 keeps 64 of breathing room. */
  height: 69.6rem;
  background: var(--cream);
}
.proof__inner {
  position: relative;
  max-width: var(--page-w);
  margin-inline: auto;
  height: 100%;
}

/* --- left column --------------------------------------------------------- */
.proof__headline {
  position: absolute;
  left: 3.644rem; top: 10.044rem;
  width: 61.956rem;
  font-size: 3.6rem;
  line-height: 5.4rem;
  letter-spacing: normal;
  font-weight: 400;
  color: var(--brown-dark);
}
.proof__copy {
  position: absolute;
  left: 4rem; top: 30.756rem;
  width: 59.022rem;
  font-size: 1.8rem;
  line-height: 3.24rem;
  color: var(--brown-dark);
}
.proof__copy p + p { margin-top: 3.24rem; }   /* one blank line */

/* --- right column -------------------------------------------------------- */
.proof__title {
  position: absolute;
  left: 77.333rem; top: 16.178rem;
  width: 30.667rem;
  font-size: 3.6rem;
  line-height: 6.48rem;
  letter-spacing: 0.288rem;
  font-weight: 400;
  color: var(--brown-dark);
}

.stat { position: absolute; color: var(--brown-dark); font-weight: 400; }
.stat__num   { display: block; font-size: 2.8rem; line-height: 4.2rem; letter-spacing: 0.224rem; }
.stat__label { display: block; font-size: 1.8rem; line-height: 3.24rem; letter-spacing: 0.288rem; width: 17.067rem; }

/* the ∞ is set larger than the numerals — Wix bumped it so it reads at size */
.stat__num--inf { font-size: 4.2rem; line-height: 6.3rem; letter-spacing: 0.336rem; }

/* exact measured positions, converted from @1440 ÷ 1.125 */
.stat--n1 { left: 78.400rem; top: 28.889rem; }
.stat--l1 { left: 77.867rem; top: 33.600rem; }
.stat--n2 { left: 104.000rem; top: 27.822rem; }
.stat--l2 { left: 103.556rem; top: 33.689rem; }
.stat--n3 { left: 77.956rem; top: 48.889rem; }
.stat--l3 { left: 77.511rem; top: 52.978rem; }
.stat--n4 { left: 103.822rem; top: 48.889rem; }
.stat--l4 { left: 103.200rem; top: 52.978rem; }

/* container widths — invisible (text is left-aligned) but matched to Wix */
.stat--n1 .stat__num { width: 16.711rem; }
.stat--n2 .stat__num { width: 16.622rem; }
.stat--n3 .stat__num { width: 16.533rem; }
.stat--n4 .stat__num { width: 16.533rem; }

/* ==========================================================================
   PROOF BLOCK  (home) — dark stats strip + light reviews band
   Pattern lifted from treelineautomation.com and re-coloured to this site's
   palette. Dark strip over a light band of dark cards gives the page a
   contrast rhythm it otherwise has nowhere.
   ========================================================================== */

/* --- stats strip --------------------------------------------------------- */
.proof-strip {
  width: 100%;
  background: var(--brown-dark);
  padding-block: 1.1rem;
}
.proof-strip__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  /* 6.4rem, not 11.2rem. The wider gutter squeezed each column narrow enough
     that "Average # of New Clients Per Month" wrapped to two lines, which set
     the height of the whole strip. Widening the columns un-wraps the labels. */
  padding-inline: 6.4rem;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 2rem 3.2rem;
}
.proof-stat__num {
  display: block;
  font-size: 4.2rem;
  /* line-height under 1 — these are numerals, so there are no descenders to
     clip and the extra leading was pure dead space */
  line-height: 4rem;
  letter-spacing: 0.168rem;
  color: var(--cream);
  margin-bottom: 0.2rem;
  /* fixed-width digits: without them the count-up jitters sideways on every
     frame as 8 gives way to 11 */
  font-variant-numeric: tabular-nums;
}
/* Live dot on the Bozeman count. It marks the number as current, which is what
   a visitor wants to know; it is not wired to anything that changes on its own,
   and the number itself never moves after its first count-up. */
.proof-stat__live {
  display: inline-block;
  width: 0.8rem;
  height: 0.8rem;
  margin-left: 1.2rem;
  vertical-align: 0.9rem;        /* sits at the numerals' mid height */
  border-radius: 50%;
  background: var(--sage);
  animation: proof-pulse 2.4s ease-out infinite;
}
@keyframes proof-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(201, 210, 158, 0.55); }
  70%  { box-shadow: 0 0 0 0.9rem rgba(201, 210, 158, 0); }
  100% { box-shadow: 0 0 0 0 rgba(201, 210, 158, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .proof-stat__live { animation: none; }
}
/* the infinity glyph reads small at the same size as the numerals */
.proof-stat__num--inf { font-size: 5.4rem; line-height: 4rem; }
.proof-stat__label {
  display: block;
  font-size: 1.2rem;
  line-height: 1.8rem;
  letter-spacing: 0.208rem;
  text-transform: uppercase;
  color: var(--tan);
}

/* --- reviews band -------------------------------------------------------- */
.reviews {
  width: 100%;
  background: var(--cream);
  padding: 4rem 0 3.6rem;
}
.reviews__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.8rem 2.4rem;
  margin-bottom: 2rem;
}

.reviews__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 1.6rem;
  margin-bottom: 0;
}
.reviews__eyebrow::before,
.reviews__eyebrow::after {
  content: "";
  width: 4.4rem;
  height: 2px;
  background: var(--brown);
}
.reviews__eyebrow span {
  font-size: 1.5rem;
  line-height: 2.2rem;
  letter-spacing: 0.324rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--brown-dark);
}

.reviews__rating { display: flex; align-items: baseline; justify-content: center; gap: 0.8rem; }
.reviews__stars { color: var(--gold); font-size: 1.5rem; letter-spacing: 0.25rem; }
.reviews__score { font-size: 1.4rem; font-weight: 700; color: var(--brown-dark); }
.reviews__count { font-size: 1.2rem; color: var(--brown); }

/* horizontally scrollable. A fade on each edge signals there is more —
   on desktop a scroll region is otherwise invisible. The left one is only
   painted once the track has actually been scrolled (js/reviews.js adds the
   class); at rest there is nothing hidden on that side to hint at, and the
   gradient would just dull the first card. */
.reviews__carousel { position: relative; }
.reviews__carousel::before,
.reviews__carousel::after {
  content: "";
  position: absolute;
  top: 0; bottom: 1.2rem;
  width: 8rem;
  pointer-events: none;
}
.reviews__carousel::after {
  right: 0;
  background: linear-gradient(to right, rgba(251,255,231,0), var(--cream));
}
.reviews__carousel::before {
  left: 0;
  z-index: 1;
  opacity: 0;
  transition: opacity 0.18s ease;
  background: linear-gradient(to left, rgba(251,255,231,0), var(--cream));
}
.reviews__carousel.is-scrolled::before { opacity: 1; }
.reviews__track {
  display: flex;
  gap: 2rem;
  /* 3.2rem inset, not 4rem — enough that the first card is not flush to the
     window edge, without pulling the row off the page's left margin. */
  padding: 0.3rem 3.2rem 0.4rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  /* Without this the snap points ignore the padding: the browser snapped the
     first card flush to x=0 the moment the track settled, so the inset above
     never actually showed. */
  scroll-padding-inline: 3.2rem;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
}
.reviews__track::-webkit-scrollbar { height: 6px; }
.reviews__track::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 3px; }

.review-card {
  /* Width is fixed at 24rem so four sit in view at desktop; height is not.
     The square these used to be ran 240px tall while the longest quote only
     filled ~153px, so every card carried 50-67px of empty brown under the
     text. Height now follows the tallest quote and the flex row levels the
     rest, which takes ~45px off the whole band. */
  flex: 0 0 24rem;
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1.2rem 1.4rem 1.1rem;
  background: var(--brown-dark);
  border: 1px solid var(--card-border);
  border-radius: 0.4rem;
  color: var(--cream);
}
.review-card__stars { color: var(--gold); font-size: 1.3rem; letter-spacing: 0.18rem; }
.review-card blockquote {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.85rem;
  color: var(--cream);
}
.review-card__meta { margin-top: auto; display: flex; align-items: center; gap: 0.9rem; }
.review-card__avatar {
  width: 2.6rem; height: 2.6rem;
  display: grid; place-items: center;
  border-radius: 0.4rem;
  background: rgba(174, 135, 93, 0.18);
  color: var(--tan);
  font-size: 1.2rem; font-weight: 700; letter-spacing: 0.048rem;
}
.review-card__name { font-size: 1.3rem; font-weight: 500; color: var(--cream); }

/* --------------------------------------------------------------------------
   SECTION DIVIDER
   Same 1px --rule hairline used on About (.stack-row) and the FAQ list, so it
   reads as part of the existing vocabulary rather than a new device.
   Inset to 3.644rem, which lines it up with the mission headline's left edge.
   -------------------------------------------------------------------------- */
.section-divider {
  background: var(--cream);
  padding-top: 4.8rem;
  padding-bottom: 2.4rem;
}
.section-divider__line {
  max-width: var(--page-w);
  margin-inline: auto;
  padding-inline: 3.644rem;
}
.section-divider__line::before {
  content: "";
  display: block;
  height: 1px;
  background: var(--rule);
}

/* ==========================================================================
   SERVICES  (home §3)
   Measured @1440: section 1440x1393. A "SERVICES" title, then 4 full-bleed
   rows that alternate image/text. Each row is two 720px halves.
   Row heights differ (273/250/311/333) — that's how Wix built it.
   ⚠️ All four images are Wix stock, not Banner's. See FINDINGS.md.
   ========================================================================== */
.services {
  position: relative;
  width: 100%;
  /* Was 123.822rem (1393px @1440), which left ~60px of empty cream under the
     last photo before the FAQ began. 2.4rem of clearance is enough. */
  height: 120.200rem;
  background: var(--cream);
}
/* Above 1920 the section background stays full-bleed but the content is
   capped and centred — matching Wix's own .max-width-container. Without this
   the content clings to the left edge on an ultrawide display. */
.services__inner {
  position: relative;
  max-width: var(--page-w);
  margin-inline: auto;
  height: 100%;
}

.services__title {
  position: absolute;
  /* Was a fixed-left box with left-aligned text, which put the word ~90px left
     of the page centre. Full-width box + centred text instead. The padding
     cancels the trailing letter-space, which otherwise pulls the glyphs left
     by half of it. */
  /* Optically centred between the hairline above and the top edge of the row 1
     photo below. line-height is 1 so the box hugs the glyphs: at 10.8rem the
     box carried 24px of leading on each side and no `top` value could sit the
     word where it looked centred without going negative. */
  left: 0; top: 2.766rem;
  width: 100%;
  text-align: center;
  padding-left: 0.96rem;
  font-size: 6rem;
  line-height: 6rem;
  letter-spacing: 0.96rem;
  font-weight: 400;
  color: var(--brown-dark);
}

/* --- rows ---------------------------------------------------------------- */
.svc-row { position: absolute; left: 0; width: 100%; }
.svc-row--1 { top: 14.133rem; height: 24.267rem; }
.svc-row--2 { top: 38.311rem; height: 22.222rem; }
.svc-row--3 { top: 60.533rem; height: 27.644rem; }
.svc-row--4 { top: 88.267rem; height: 29.600rem; }

.svc-row__img {
  position: absolute;
  top: 0; height: 100%;
  width: 50%;
  overflow: hidden;
}
.svc-row__img--right { right: 0; }
.svc-row__img--left  { left: 0; }
.svc-row__img img { width: 100%; height: 100%; object-fit: cover; }

/* Wix focal points, read from each image's data-image-info on the live site.
   Banner repositioned rows 1 and 2 in the Wix editor — these are the current
   published values. Rows 3 and 4 are still centred (50/50). */
.svc-row--1 .svc-row__img img { object-position: 37.6% 29.7%; }
.svc-row--2 .svc-row__img img { object-position: 78.9% 29.6%; }

/* --- card text ----------------------------------------------------------- */
.svc-card { position: absolute; }
.svc-card__title {
  font-size: 2.8rem;
  line-height: 4.2rem;
  letter-spacing: 0.224rem;
  font-weight: 400;
  color: var(--brown-dark);
}
.svc-card__body {
  width: 31.378rem;
  font-size: 1.3rem;
  line-height: 2.34rem;
  letter-spacing: 0.065rem;
  color: var(--brown-dark);
}

/* per-card positions, measured @1440 ÷ 1.125, y relative to section top */
.svc-title--1 { left: 7.289rem;  top: 16.711rem; width: 42.578rem; }
.svc-body--1  { left: 7.289rem;  top: 22.489rem; }
.svc-title--2 { left: 70.400rem; top: 40.622rem; width: 36.000rem; }
.svc-body--2  { left: 70.400rem; top: 45.600rem; }
/* Rows 3 and 4 were each measured on their own and drifted off the row above
   them in the same column: row 3 sat 4px right of row 1, row 4 sat 73px right
   of row 2. Both now share their column's left edge and its title->body gap.
   The titles are also wide enough to hold one line, which is what crowded the
   paragraph underneath them. */
.svc-title--3 { left: 7.289rem;  top: 63.644rem; width: 43.000rem; }
.svc-body--3  { left: 7.289rem;  top: 69.422rem; width: 29.000rem; }
.svc-title--4 { left: 70.400rem; top: 91.467rem; width: 40.000rem; }
.svc-body--4  { left: 70.400rem; top: 96.445rem; }

/* --- Read More button ---------------------------------------------------- */
.btn-read {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* width follows the label now that these say "Lead Capture Case Study"
     rather than "Read More" */
  width: auto;
  white-space: nowrap;
  padding-inline: 1.8rem;
  height: 3.644rem;
  background: var(--cream);
  border: 1px solid var(--brown);
  border-radius: 0.8rem;
  color: var(--brown);
  font-size: 1.3rem;
  font-weight: 400;
  transition: background 0.18s ease, color 0.18s ease;
}
.btn-read:hover { background: var(--brown); color: var(--cream); }

.btn-read--1 { left: 41.600rem;  top: 32.889rem; }
.btn-read--2 { left: 106.311rem; top: 53.867rem; }
/* "Communication Case Study" is the longest label, so the measured left edge
   pushed it past the halfway line and under row 3's photo. Anchored by its
   right edge instead: it now ends 2.267rem clear of the image, lining up with
   btn-read--1, and stays clear however long the label gets. */
/* bottom edge level with the last line of the paragraph, as in row 1 */
.btn-read--3 { right: calc(50% + 2.267rem); top: 79.821rem; }
/* same offsets from its title as row 2's button has from its own */
.btn-read--4 { left: 106.311rem; top: 104.712rem; }

/* ==========================================================================
   FAQ + CATCH-ALL CTA  (home §4)
   Structure C: FAQ in the primary left column, a compact dark CTA card on the
   right. Replaces the old fixed-height panel + "Best Tools in the Biz" logo
   wall, which was deleted. Height is content-driven — an accordion changes
   height as items open, so a fixed section height is not possible here.
   ========================================================================== */
.forget {
  position: relative;
  width: 100%;
  background: var(--cream);
  /* less on top: services and this section are both cream, so the old 8rem
     read as one long empty stretch between the last service and the FAQ */
  padding: 5.6rem 0 8rem;
}
.forget__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  padding-inline: 11.2rem;      /* matches the old dark panel's left edge */
  display: grid;
  grid-template-columns: 1fr 36rem;
  gap: 6.4rem;
  align-items: start;
}

/* --- FAQ column ---------------------------------------------------------- */
.faq__eyebrow {
  font-size: 1.3rem;
  line-height: 2.34rem;
  letter-spacing: 0.208rem;
  color: var(--brown);
  margin-bottom: 1.2rem;
}
.faq__title {
  font-size: 2.8rem;
  line-height: 4.2rem;
  letter-spacing: 0.224rem;
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 3.2rem;
}

.faq-item { border-top: 1px solid var(--rule); }
.faq-item:last-child { border-bottom: 1px solid var(--rule); }

.faq-item__q {
  width: 100%;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 2.4rem;
  padding: 1.8rem 0;
  text-align: left;
  cursor: pointer;
  font-size: 1.6rem;
  line-height: 2.6rem;
  color: var(--brown-dark);
}
.faq-item__q:hover { color: var(--brown); }

/* the Q:/A: prefixes — the whole point is that this reads as a Q&A */
.faq-item__tag {
  display: inline-block;
  width: 2.6rem;
  color: var(--tan);
  font-weight: 700;
}

.faq-item__chev {
  flex: 0 0 auto;
  width: 1.4rem;
  height: 0.8rem;
  margin-top: 0.9rem;
  fill: none;
  stroke: var(--brown);
  stroke-width: 1.6;
  transition: transform 0.22s ease;
}
.faq-item.is-open .faq-item__chev { transform: rotate(180deg); }

/* Collapse/expand via grid-template-rows 0fr -> 1fr.
   The obvious approach — transitioning max-height to a JS-measured
   scrollHeight — got stuck at its start value and rendered every panel at 0
   height. This needs no measurement, so there is nothing to get stuck, and it
   animates to the content's true height whatever that turns out to be. */
/* Open/close is display:none <-> block. Deliberately NOT an animated height.
   Both the usual tricks — transitioning max-height to a measured value, and
   grid-template-rows 0fr->1fr — left the panel frozen at its start value and
   rendering at 0 height. `transform` and `opacity` transitions do work, so the
   polish comes from a short fade-in on open instead. This cannot get stuck. */
.faq-item__a { display: none; }
.faq-item.is-open .faq-item__a {
  display: block;
  animation: faq-open 0.22s ease both;
}
@keyframes faq-open {
  from { opacity: 0; transform: translateY(-0.4rem); }
  to   { opacity: 1; transform: none; }
}

.faq-item__a > p {
  padding: 0 4rem 2rem 0;
  font-size: 1.3rem;
  line-height: 2.34rem;
  color: var(--brown-dark);
}
/* no-JS fallback: without the script every answer is simply visible */
html:not(.js) .faq-item__a { display: block; }

/* --- link through to the full FAQ page ----------------------------------- */
.btn-more {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-top: 3.2rem;
  height: 4.4rem;
  padding-inline: 2.4rem;
  border: 1px solid var(--brown);
  border-radius: 0.8rem;
  color: var(--brown);
  font-size: 1.3rem;
  transition: background 0.18s ease, color 0.18s ease;
}
.btn-more:hover { background: var(--brown); color: var(--cream); }

/* ==========================================================================
   CASE STUDIES  (case-studies.html)
   One section per service, deep-linked from the home page "Read More" buttons.
   The anchor ids must stay: #lead-capture #booking #communication #back-office
   ========================================================================== */
.cases {
  width: 100%;
  background: var(--cream);
  padding-bottom: 9.6rem;
}
.cases__inner {
  /* widened from 82rem to make room for the results rail. The story column
     does NOT get wider as a result — see .case__story. */
  max-width: 96rem;
  margin-inline: auto;
  padding-inline: 2.4rem;
}

.case {
  /* Each case is bracketed by a hairline: its own rule on top, the next case's
     rule underneath. The last one carries a bottom rule so the set closes.

     The two paddings are doing different jobs. padding-top is the air under
     the rule, and it is also the buffer that keeps the NEXT case's eyebrow
     below the fold when you land here from a home page button — the whole ask
     is to see one case start and finish, not the top of the one after it.
     padding-bottom is just the air above the closing rule, so it stays small.

     scroll-margin-top lands the top rule below the fixed header rather than
     under it. Every rem of it is a rem the case itself does not get. */
  scroll-margin-top: 7.6rem;
  padding-top: 3rem;
  padding-bottom: 1.2rem;
  border-top: 1px solid var(--rule);
}
.case:last-of-type { border-bottom: 1px solid var(--rule); }

/* The case you arrived at from a home page button fills what is left of the
   screen. A fixed gap cannot do this job: how much of the next case shows
   below the closing rule depends entirely on the window height, so on a tall
   window its eyebrow always crept into view. Sized so the closing rule lands
   ~2.4rem above the fold — visible, with the next case's text pushed past it.
   :target means only the case being linked to stretches; scrolling the page
   normally leaves them stacked at their natural height. */
.case:target { min-height: calc(100vh - 10rem); }

/* Story left, results right. align-items:start is what lets the rail be
   sticky — a stretched grid item is already as tall as the row and has
   nowhere to travel. */
.case__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 26rem;
  gap: 4.8rem;
  align-items: start;
}
.case__story {
  /* Caps the line length at roughly 75 characters. At the old full-width
     82rem the paragraphs ran 91-103 characters per line, which is well past
     the point where the eye starts losing its place on the carriage return. */
  max-width: 61rem;
}
.case__story > :first-child { margin-top: 0; }

.case__results { position: sticky; top: 11rem; }
.case__results-label {
  font-size: 1.2rem;
  line-height: 2rem;
  letter-spacing: 0.208rem;
  text-transform: uppercase;
  color: var(--tan);
  margin-bottom: 1.2rem;
  padding-bottom: 0.8rem;
  border-bottom: 1px solid var(--rule);
}

.case__eyebrow {
  font-size: 1.3rem;
  line-height: 2.34rem;
  letter-spacing: 0.208rem;
  text-transform: uppercase;
  color: var(--tan);
  margin-bottom: 0.4rem;
}
.case__title {
  font-size: 2.8rem;
  line-height: 3.2rem;
  letter-spacing: 0.112rem;
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 1.1rem;
  /* the title spans the grid, but a 2.8rem headline still should not run the
     full width of the page. 88rem is set so the longest of the four titles
     lands on one line like the other three — a lone two-line headline read as
     an inconsistency, and it cost 38px. */
  max-width: 88rem;
}
.case__h3 {
  margin-top: 1.2rem;
  margin-bottom: 0.5rem;
  font-size: 1.8rem;
  line-height: 2.4rem;
  letter-spacing: 0.144rem;
  font-weight: 400;
  color: var(--brown);
}
.case p {
  font-size: 1.4rem;
  /* 2.6rem on 1.4rem text is a 1.86 ratio, which is loose enough to read as
     airy rather than comfortable. 2.3rem lands at 1.64 — still inside the
     comfortable band, and it takes real height out of a page this text-heavy. */
  line-height: 2.3rem;
  color: var(--brown-dark);
}
.case__list {
  margin-top: 0.8rem;
  padding-left: 0;
  list-style: none;
}
.case__list li {
  position: relative;
  padding-left: 2.4rem;
  margin-top: 0.8rem;
  font-size: 1.4rem;
  line-height: 2.3rem;
  color: var(--brown-dark);
}
.case__list li::before {
  content: "";
  position: absolute;
  /* tuned to the first line box — follows .case__list li's line-height down */
  left: 0; top: 1rem;
  width: 0.8rem; height: 0.8rem;
  border-radius: 50%;
  background: var(--tan);
}
.case__list strong { font-weight: 700; }

/* pulls the numbers out of the paragraph so the result scans at a glance.
   In the rail they stack; the media query below puts them back in a row when
   the rail collapses. */
.case__stats {
  display: flex;
  flex-direction: column;
  gap: 1.2rem;
}
.case-stat {
  padding: 1.4rem 1.6rem;
  border: 1px solid var(--card-border);
  border-radius: 1.2rem;
}
.case-stat__num {
  display: block;
  font-size: 2.2rem;
  line-height: 3rem;
  color: var(--tan);
  margin-bottom: 0.4rem;
}
.case-stat__label {
  display: block;
  font-size: 1.2rem;
  line-height: 2rem;
  color: var(--brown-dark);
}

/* sections still awaiting a write-up */
.case--pending .case__title { color: var(--card-border); }
.case__pending {
  padding: 2rem 2.4rem;
  border: 1px dashed var(--card-border);
  border-radius: 1.2rem;
  color: var(--brown-dark);
}

/* Its own breakpoint rather than the site-wide 1279px one: the rail needs
   ~26rem plus a story column wide enough to still read. Above 900px both fit
   and the two-column layout is worth keeping; below it the story would be
   squeezed under 50 characters a line, which is worse than stacking. */
@media (max-width: 900px) {
  .case__body { grid-template-columns: 1fr; gap: 2.4rem; }
  /* .case__story keeps its max-width on purpose — the rail is gone, so
     without the cap the story would spread back out to 90+ characters a line
     on a tablet, which is the problem this whole change was fixing. */
  .case__results { position: static; }
  .case__stats { flex-direction: row; flex-wrap: wrap; }
  .case-stat { flex: 1 1 18rem; }
}

/* ==========================================================================
   AUDIT FORM  (audit.html)
   The site's single conversion point. The phone / contact-method / consent
   fields mirror what privacy.html and terms.html describe.
   ========================================================================== */
.audit { width: 100%; background: var(--cream); padding: 8.8rem 0 5.6rem; }
.audit__inner {
  max-width: 104rem;
  margin-inline: auto;
  padding-inline: 2.4rem;
  display: grid;
  grid-template-columns: minmax(0, 34rem) minmax(0, 56rem);
  grid-template-rows: auto 1fr;
  justify-content: center;
  gap: 3.2rem 6.4rem;
  align-items: start;
}
.audit__pitch  { grid-column: 1; grid-row: 1; }
.audit__assure { grid-column: 1; grid-row: 2; }
/* js/audit-form.js hides the form and unhides a status panel in its place, so
   the panel has to claim the same cell or it lands in a row of its own */
.audit-form,
.audit__inner > .form-status { grid-column: 2; grid-row: 1 / span 2; }
.audit__title {
  font-size: 4rem;
  line-height: 5rem;
  font-weight: 400;
  color: var(--brown-dark);
  margin-bottom: 1.6rem;
}
.audit__copy {
  font-size: 1.5rem;
  line-height: 2.6rem;
  color: var(--brown-dark);
  margin-bottom: 2.4rem;
}
.audit__assure .audit-form__guarantee { margin-top: 0; text-align: left; }
.audit__assure .audit-form__alt { margin-top: 1.6rem; text-align: left; }

/* two short fields to a row: four stacked rows was 204px of the reason this
   page could not be seen in one screen */
.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2rem;
}

.field { margin-bottom: 1.2rem; border: 0; padding: 0; }
.field__label {
  display: block;
  margin-bottom: 0.6rem;
  font-size: 1.3rem;
  line-height: 2.2rem;
  letter-spacing: 0.065rem;
  color: var(--brown-dark);
}
.field__opt { color: var(--card-border); }
.field__input {
  width: 100%;
  height: 4.2rem;
  padding: 0 1.4rem;
  background: transparent;
  border: 1px solid var(--card-border);
  border-radius: 0.8rem;
  font-size: 1.4rem;
  color: var(--brown-dark);
  transition: border-color 0.18s ease;
}
.field__input--area { height: auto; padding: 1rem 1.4rem; line-height: 2.2rem; resize: vertical; }
.field__input::placeholder { color: var(--card-border); }
.field__input:focus { border-color: var(--brown); outline: none; }
.field__input:focus-visible { border-color: var(--brown); }

.field--choice { display: flex; flex-wrap: wrap; align-items: center; gap: 2rem; }
/* the label is a <legend>, which the browser renders as the fieldset's caption
   outside the flex flow — it cannot be pulled onto the radios' line */
.field--choice .field__label { flex: 0 0 100%; margin-bottom: 0; }
.choice { display: inline-flex; align-items: center; gap: 0.8rem; font-size: 1.4rem; cursor: pointer; }
.choice input { width: 1.6rem; height: 1.6rem; accent-color: var(--brown); }

.consent {
  display: flex;
  gap: 1.2rem;
  align-items: flex-start;
  margin-bottom: 0.8rem;
  font-size: 1.3rem;
  line-height: 2.2rem;
  cursor: pointer;
}
.consent input { margin-top: 0.3rem; width: 1.6rem; height: 1.6rem; flex: 0 0 auto; accent-color: var(--brown); }

.audit-form__disclosure {
  margin-bottom: 1.2rem;
  font-size: 1.15rem;
  line-height: 1.9rem;
  color: var(--brown);
}
.audit-form__disclosure a { text-decoration: underline; }

.btn-audit {
  width: 100%;
  height: 4.8rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--brown);
  border: none;
  border-radius: 0.8rem;
  color: var(--cream);
  font-size: 1.4rem;
  cursor: pointer;
  transition: filter 0.18s ease;
}
.btn-audit:hover { filter: brightness(1.12); }

/* Sits between the submit button and the "would rather just talk" line. A
   hairline box rather than plain text, so it reads as a term of the offer
   instead of another footnote. */
.audit-form__guarantee {
  margin-top: 1.6rem;
  padding: 1.2rem 1.6rem;
  border: 1px solid var(--card-border);
  border-radius: 0.8rem;
  text-align: center;
  font-size: 1.3rem;
  line-height: 2.2rem;
  color: var(--brown-dark);
}
.audit-form__guarantee strong { font-weight: 700; }

.audit-form__alt {
  margin-top: 1.6rem;
  text-align: center;
  font-size: 1.3rem;
  color: var(--brown-dark);
}
.audit-form__alt a { color: var(--brown); text-decoration: underline; }

/* phone link that only appears in the mobile menu, under the Free Audit button */
.site-nav__tel { display: none; }

/* honeypot — off-screen rather than display:none, which more bots skip */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* success / failure states, swapped in by js/audit-form.js */
.form-status {
  padding: 3.2rem 2.8rem;
  border-radius: 1.2rem;
  font-size: 1.4rem;
  line-height: 2.6rem;
}
.form-status[hidden] { display: none; }
.form-status__title {
  margin-bottom: 1.2rem;
  font-size: 2.2rem;
  line-height: 3rem;
  letter-spacing: 0.176rem;
  font-weight: 400;
}
.form-status--ok {
  background: var(--brown-dark);
  color: var(--cream);
}
.form-status--ok .form-status__title { color: var(--cream); }
.form-status--ok a { color: var(--cream); text-decoration: underline; }

/* failure is deliberately loud — this is the state where a lead is at risk */
.form-status--fail {
  background: transparent;
  border: 2px solid var(--brown);
  color: var(--brown-dark);
}
.form-status--fail .form-status__title { color: var(--brown); }
.form-status--fail a { color: var(--brown); text-decoration: underline; }

/* ==========================================================================
   LEGAL PAGES  (privacy.html, terms.html)
   Same interior-page shell as the FAQ page: centred res-intro header, then a
   single readable column. Narrow measure on purpose — legal text is only
   scannable at roughly 70-80 characters a line.
   ========================================================================== */
.legal {
  width: 100%;
  background: var(--cream);
  padding-bottom: 9.6rem;
}
.legal__inner {
  max-width: 76rem;
  margin-inline: auto;
  padding-inline: 2.4rem;
  font-size: 1.4rem;
  line-height: 2.6rem;
  color: var(--brown-dark);
}
.legal__dates {
  padding-bottom: 2.4rem;
  margin-bottom: 3.2rem;
  border-bottom: 1px solid var(--rule);
  font-size: 1.3rem;
  color: var(--brown);
}
.legal__h2 {
  margin-top: 4rem;
  margin-bottom: 1.2rem;
  font-size: 2rem;
  line-height: 3rem;
  letter-spacing: 0.16rem;
  font-weight: 400;
  color: var(--tan);
}
.legal__inner p + p { margin-top: 1.6rem; }
.legal__inner a { color: var(--brown); text-decoration: underline; }
.legal__inner a:hover { color: var(--brown-dark); }

/* ==========================================================================
   FAQ PAGE  (faq.html)
   Reuses the homepage accordion component. The homepage shows five and links
   here for the rest. Narrower column than the homepage because there is no
   second column competing for width — long answers read better at ~86rem.
   ========================================================================== */
.faq-page {
  width: 100%;
  background: var(--cream);
  padding-bottom: 9.6rem;
}
.faq-page__inner {
  max-width: 86rem;
  margin-inline: auto;
  padding-inline: 2.4rem;
}
/* Same card as the home page: left aligned copy, full width button. It was
   centred with a 28rem button, which read as a different component sitting on
   a different page rather than the one the visitor already saw. */
.faq-page__cta {
  position: static;
  margin-top: 6.4rem;
}
/* The card spans this page's wider column. A full-width button would run 91rem
   and the old 30.4rem cap read as an oversized empty box around a small label,
   so here the button sizes to its own text with real padding around it. */
.faq-page__cta .btn-touch {
  width: auto;
  max-width: 100%;
  height: 5.2rem;
  padding-inline: 3.2rem;
  font-size: 1.5rem;
}

/* --- compact CTA card ---------------------------------------------------- */
.forget__card {
  background: var(--brown-dark);
  border-radius: 1.2rem;
  padding: 3.2rem 2.8rem;
  position: sticky;
  top: 12rem;                   /* clears the fixed header while scrolling */
}
.forget__q {
  font-size: 2.2rem;
  line-height: 3.2rem;
  letter-spacing: 0.176rem;
  font-weight: 400;
  color: var(--cream);
  margin-bottom: 1.6rem;
}
.forget__a {
  font-size: 1.4rem;
  line-height: 2.4rem;
  color: var(--cream);
  margin-bottom: 2.8rem;
}
.btn-touch {
  width: 100%;
  height: 4.8rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--brown);
  border: none;
  border-radius: 0.8rem;
  color: var(--cream);
  font-size: 1.3rem;
  font-weight: 400;
  cursor: pointer;
  transition: filter 0.18s ease;
}
.btn-touch:hover { filter: brightness(1.12); }


/* ==========================================================================
   FREE WORKFLOWS CTA  (home §5)
   Measured @1440: section 1440x758 on sage #C9D29E — the only place the sage
   token is used on this page. A cream card sits inside it, everything centred.
   ========================================================================== */
/* The Wix original was 758px tall around 513px of card holding four elements
   that added up to ~380px of text, so most of it was gaps: 110px between the
   headline and the paragraph alone. Same composition, gaps cut to a single
   rhythm (4rem card inset, 2.4rem title->copy, 3.2rem copy->button,
   1.6rem button->note) and the headline down from 5.6rem to 4.4rem. Section
   673px -> 488px, then -> 550px when the guarantee line went in under the
   button. */
.cta {
  position: relative;
  width: 100%;
  height: 55rem;
  background: var(--sage);
}
.cta__inner {
  position: relative;
  max-width: var(--page-w);
  margin-inline: auto;
  height: 100%;
}
.cta__card {
  position: absolute;
  left: 19.2rem; top: 6.4rem;
  width: 89.6rem; height: 42.2rem;
  background: var(--cream);
}
.cta__title {
  position: absolute;
  left: 24rem; top: 10.4rem;
  width: 80rem;
  font-size: 4.4rem; line-height: 6rem; letter-spacing: normal;
  font-weight: 400; color: var(--brown-dark); text-align: center;
}
.cta__copy {
  position: absolute;
  left: 30.4rem; top: 18.8rem;
  width: 67.2rem;
  font-size: 2rem; line-height: 2.8rem;
  color: var(--brown-dark); text-align: center;
}
.btn-cta {
  position: absolute;
  /* centred on the 128rem page; the old left was Wix's, half a rem off */
  left: 53.111rem; top: 30.4rem;
  width: 21.778rem; height: 4rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brown);
  border: none; border-radius: 0.8rem;
  cursor: pointer;
  transition: filter 0.18s ease;
}
.btn-cta:hover { filter: brightness(1.12); }
.btn-cta__label {
  /* source text is "Get My Free Workflows" — the caps come from CSS */
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--cream);
  font-size: 1.3rem; font-weight: 400; letter-spacing: 0.13rem;
  line-height: 2.34rem;
}
.cta__guarantee {
  position: absolute;
  left: 24rem; top: 36.4rem;
  width: 80rem;
  font-size: 1.4rem; line-height: 2.2rem;
  color: var(--brown-dark); text-align: center;
}
.cta__guarantee strong { font-weight: 700; }

.cta__note {
  position: absolute;
  left: 24rem; top: 42.2rem;
  width: 80rem;
  font-size: 1.3rem; line-height: 2.34rem;
  color: var(--brown-dark); text-align: center;
}

/* ==========================================================================
   ABOUT PAGE
   Measured @1440. Three sections: mission (804), what-we-build-with (1018),
   news (574). Header is a fixed overlay as on the home page.
   ⚠️ Copy in §1 headline and all of §3 is Wix template text — Banner is
   rewriting it (BUILD-PLAN decision C). Structure is exact; words are not his.
   ========================================================================== */

/* --- shared bits --------------------------------------------------------- */
.vrule { position: absolute; width: 0.089rem; background: var(--rule); }
.eyebrow {
  position: absolute;
  font-size: 1.3rem; line-height: 2.34rem; letter-spacing: 0.208rem;
  font-weight: 400;
}
.about-h2 {
  position: absolute;
  font-size: 1.8rem; line-height: 2.7rem; letter-spacing: 0.144rem;
  font-weight: 400;
}

/* --- §1 mission ----------------------------------------------------------
   Flow layout. This was absolutely positioned inside a fixed 71.467rem box,
   which held two paragraphs. It now carries four, so height is
   content-driven. The vertical rule became a border on the text column so it
   grows with the copy instead of being a fixed-height element. */
.mission {
  position: relative;
  width: 100%;
  background: var(--cream);
  padding-block: 9.6rem;
}
.mission__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  padding-inline: 14.933rem;
  display: grid;
  grid-template-columns: minmax(0, 46rem) 34.133rem;
  justify-content: space-between;
  gap: 6.4rem;
  align-items: start;
}
.mission__text {
  border-left: 1px solid var(--rule);
  padding-left: 4.267rem;
}
.mission__title {
  /* .about-h2 is absolutely positioned for the News block; this one is in flow
     now, so it must opt out or it lands on top of the lead-in below it */
  position: static;
  width: auto;
  /* was 1.6rem when a lead-in paragraph sat between this and the copy */
  margin-bottom: 2.4rem;
  font-size: 2.8rem;
  line-height: 4rem;
  letter-spacing: 0.168rem;
  color: var(--brown-dark);
}

.mission__copy {
  font-size: 1.3rem;
  line-height: 2.34rem;
  letter-spacing: 0.065rem;
  color: var(--brown-dark);
}
.mission__copy p + p { margin-top: 2.34rem; }
.mission__signoff { margin-top: 3.2rem; }

.mission__photo {
  width: 100%;
  aspect-ratio: 384 / 554;
  border-radius: 1.6rem;
  overflow: hidden;
}
.mission__photo img { width: 100%; height: 100%; object-fit: cover; }

/* --- §2 what we build with --------------------------------------------
   Rebuilt as "layout B": one row per category, label on the left and a
   wrapping strip of logo tiles on the right. The Wix carousel was removed —
   it hid two of the three categories behind an arrow, which works against
   the whole point of showing recognisable tools.
   Section height is content-driven now, not the fixed 1018px.

   Chips carry a Simple Icons mark plus the brand name, the same treatment
   treelineautomation.com uses. A brand with no mark available renders as the
   identical chip without the icon. */
.build {
  position: relative;
  width: 100%;
  background: var(--cream);
  padding-bottom: 5.6rem;
}
.build__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  /* left edge stays aligned with the mission copy; the right is only a bound
     on the wrapping strip, and it takes this much for Integrations to hold a
     single line */
  padding-left: 19.2rem;
  padding-right: 6.4rem;
}
.build__title {
  position: static;
  width: auto;
  margin-bottom: 3.2rem;
  color: var(--brown-dark);
}

.stack-row {
  display: flex;
  align-items: baseline;
  gap: 2.4rem;
  padding: 1.4rem 0;
  border-top: 1px solid var(--rule);
}
.stack-row:last-of-type { border-bottom: 1px solid var(--rule); }

.stack-row__label {
  /* wide enough for "Communication", which used to overflow its column and
     push that one row's chips 36px right of the other three */
  flex: 0 0 17rem;
  font-size: 1.8rem;
  line-height: 3.2rem;
  letter-spacing: 0.144rem;
  font-weight: 400;
  color: var(--tan);
}
.stack-row__logos {
  flex: 1 1 auto;
  display: flex;
  flex-wrap: wrap;
  gap: 0.8rem;
}

/* One chip per tool: brand mark plus name. Was a 4.4rem tile/pill split — the
   tiles were 16:9 crops of logo images, which is what made the row so tall. */
.tool {
  height: 3.2rem;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  padding-inline: 0.95rem;
  border: 1px solid var(--card-border);
  border-radius: 0.4rem;
  font-size: 1.25rem;
  letter-spacing: 0.04rem;
  color: var(--brown-dark);
  white-space: nowrap;
}
.tool__icon {
  flex: 0 0 auto;
  width: 1.5rem;
  height: 1.5rem;
  display: block;
}

.build__note {
  margin-top: 2rem;
  max-width: 72rem;
  font-size: 1.3rem;
  line-height: 2.34rem;
  color: var(--brown);
}

/* A case has to fit between the header and the fold, and on a short window it
   does not, no matter how the spacing is tuned: the story is simply taller than
   the screen. So on short windows the case sets its own type a step smaller.
   Keyed off viewport HEIGHT, not width, because height is the constraint. Tall
   windows are untouched. */
@media (max-height: 800px) {
  .case__title { font-size: 2.4rem; line-height: 2.8rem; margin-bottom: 0.9rem; }
  .case__h3 { font-size: 1.6rem; line-height: 2.2rem; margin-top: 1rem; }
  .case p,
  .case__list li { font-size: 1.3rem; line-height: 2.1rem; }
  .case__list li { margin-top: 0.6rem; }
  .case__eyebrow { line-height: 2rem; }
  .case { padding-top: 2.4rem; }
}

/* --- §3 where we work ----------------------------------------------------
   Replaces the template's press band, which was 51rem tall to hold five logos
   on a 1440 canvas. This is a single flow row: label left, towns and one line
   of copy right. Content driven, and it comes out around 18rem.
   ------------------------------------------------------------------------- */
.area {
  width: 100%;
  background: var(--brown-dark);
  padding-block: 5.6rem;
}
.area__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  padding-left: 19.2rem;
  padding-right: 6.4rem;
  display: flex;
  align-items: baseline;
  gap: 2.4rem;
}
/* same 17rem measure the stack rows use, so the two sections line up */
.area__label {
  flex: 0 0 17rem;
  font-size: 1.8rem;
  line-height: 3.2rem;
  letter-spacing: 0.144rem;
  color: var(--tan);
}
.area__body { flex: 1 1 auto; }
.area__towns {
  font-size: 2.2rem;
  line-height: 3.2rem;
  letter-spacing: 0.11rem;
  color: var(--cream);
}
.area__towns span { color: var(--tan); padding-inline: 0.4rem; }

/* ==========================================================================
   FOOTER
   Measured: 241px tall. Three columns at x=86 / x=479 / x=671.
   Social icons right-aligned, 20.4px, 48px apart, baseline y=145.
   ⚠️ CONTENT IS WIX PLACEHOLDER — kept verbatim by Banner's decision
   (BUILD-PLAN decision D). All swappable values are in ONE block in the HTML,
   marked PLACEHOLDER-BLOCK. Changing them is a copy-paste job.
   ========================================================================== */
.site-footer {
  width: 100%;
  background: var(--cream);
  color: var(--brown-dark);
}
/* Two rows, not three columns. The old layout stacked the four nav links
   vertically, which made a 151px column that set the height of the whole
   footer while the brand column sat 647px wide holding two links. Now the
   brand, nav and contact share one baseline row, and a hairline separates the
   copyright and legal line under it. 255px -> ~160px. */
.site-footer__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  padding: 4rem 8.6rem 3.2rem;
  font-size: 1.3rem;
  line-height: 2.34rem;
}

.site-footer__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 3.2rem 4.8rem;
  flex-wrap: wrap;
  padding-bottom: 2.4rem;
  border-bottom: 1px solid var(--rule);
}

.site-footer__brand { display: inline-block; }
.site-footer__brand .site-header__logo { width: auto; height: 3.2rem; margin-top: 0; }

.site-footer__nav { display: flex; flex-wrap: wrap; gap: 2.8rem; }
.site-footer__nav a:hover { color: var(--brown); }

/* the two links sit inline here, so they need a separator's worth of space
   rather than the stacked paragraphs this used to be */
.site-footer__contact { display: flex; flex-wrap: wrap; gap: 2.4rem; }
.site-footer__contact a:hover { color: var(--brown); text-decoration: underline; }

.site-footer__bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.2rem 3.2rem;
  flex-wrap: wrap;
  padding-top: 1.6rem;
  font-size: 1.2rem;
  color: var(--brown);
}
.site-footer__legal { display: flex; gap: 2.4rem; }
.site-footer__legal a:hover { text-decoration: underline; }
.site-footer__copy a:hover { text-decoration: underline; }

/* ==========================================================================
   BLOG & RESOURCES PAGE
   Measured @1440: intro 351, resource grid 2143, footer 270.
   ⚠️ Every word and image on this page is untouched Wix template copy —
   "Resource Title 01", placeholder body text, six stock photos, and Download
   buttons with no link. See FINDINGS.md #25.

   NOTE: on this page Wix leaves the header `position: relative` so it scrolls
   away, unlike Home and About where it is pinned. Reproduced via
   .site-header--static. That inconsistency is Banner's, not ours.
   ========================================================================== */
.site-header--static { position: relative; }

/* --- intro --------------------------------------------------------------- */
.res-intro {
  position: relative;
  width: 100%;
  height: 31.2rem;            /* 351px @1440 */
  background: var(--cream);
}
.res-intro__inner {
  position: relative;
  max-width: var(--page-w);
  margin-inline: auto;
  height: 100%;
}
.res-intro__title {
  position: absolute;
  left: 0; top: 9.956rem;
  width: 100%;
  font-size: 4.8rem; line-height: 7.2rem; letter-spacing: normal;
  font-weight: 400; color: var(--brown-dark); text-align: center;
}
/* Resources page: heading only, no standfirst under it. The measure is capped
   so the line breaks near the middle instead of leaving "reading" alone on a
   second line, and the block loses the height the missing paragraph held. */
.res-intro--title-only { height: 28rem; }
.res-intro--title-only .res-intro__title {
  left: 0; right: 0;
  width: auto;
  max-width: 70rem;
  margin-inline: auto;
}

.res-intro__copy {
  position: absolute;
  left: 34.667rem; top: 19.2rem;
  width: 58.578rem;
  font-size: 1.3rem; line-height: 2.34rem;
  color: var(--brown-dark); text-align: center;
}

/* --- resource grid ------------------------------------------------------- */
/* The cards were absolutely positioned to match Wix exactly while they held
   placeholder text ("Resource Title 01") that always fit on one line. Banner's
   real titles run 2-3 lines and collided with the body copy below, so the grid
   is now flow-based. Every gap here is still the measured Wix spacing; the
   cards simply grow to fit their content. Section height is content-driven. */
.resources {
  position: relative;
  width: 100%;
  background: var(--cream);
  padding-bottom: 6.311rem;
}
.resources__inner {
  max-width: var(--page-w);
  margin-inline: auto;
  padding-inline: 7.111rem;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: 5.956rem;       /* 67px @1440 */
  row-gap: 6.311rem;          /* 71px @1440 */
  align-items: stretch;
}

.res-card { display: flex; flex-direction: column; align-items: flex-start; }
.res-card__img {
  width: 100%;
  aspect-ratio: 607 / 354;    /* the measured Wix image box */
  overflow: hidden;
}
.res-card__img img { width: 100%; height: 100%; object-fit: cover; }
.res-card__title {
  /* Wix used 340px here, sized for the placeholder "Resource Title 01".
     Banner's real titles wrapped after ~30 characters and left the card
     lopsided, so this now matches the body width. */
  max-width: 45.689rem;
  margin-top: 1.956rem;       /* 22px @1440 */
  font-size: 1.8rem; line-height: 2.52rem;
  font-weight: 400; color: var(--brown-dark);
}
.res-card__body {
  max-width: 45.689rem;
  margin-top: 2.044rem;       /* 23px @1440 */
  font-size: 1.3rem; line-height: 2.34rem;
  color: var(--brown-dark);
  flex: 1 0 auto;             /* pushes the button to the card foot so buttons
                                 line up across a row of uneven titles */
}
.btn-download {
  margin-top: 1.689rem;       /* 19px @1440 */
  width: 12.533rem; height: 4.8rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--brown);
  border: none; border-radius: 0.8rem;
  color: var(--cream);
  font-size: 1.3rem; font-weight: 400;
  cursor: pointer;
  transition: filter 0.18s ease;
}
.btn-download:hover { filter: brightness(1.12); }

/* ==========================================================================
   SCROLL REVEAL
   Copied from Wix's own motion keyframes. Three variants, all 1.2s:
     fade  — opacity only.              ease cubic-bezier(.445,.05,.55,.95)
     glide — snaps to opaque, then slides in from an offset.
                                        ease cubic-bezier(.645,.045,.355,1)
     float — fades AND slides together. ease cubic-bezier(.445,.05,.55,.95)
   Offsets come from --rx / --ry, delay from --rd, both set per element.

   Elements only start hidden when JS is running (the `js` class is set by an
   inline script in <head>). Without JS everything renders visible.
   ========================================================================== */
@keyframes reveal-fade {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}
@keyframes reveal-glide {
  0%      { opacity: 0; animation-timing-function: step-end; }
  0.0001% { opacity: 1; transform: translate(var(--rx, 0), var(--ry, 0)); }
  100%    { opacity: 1; transform: translate(0, 0); }
}
@keyframes reveal-float {
  0%   { opacity: 0; transform: translate(var(--rx, 0), var(--ry, 0)); }
  100% { opacity: 1; transform: translate(0, 0); }
}

.js [data-reveal] { opacity: 0; }
.js [data-reveal].is-in {
  animation-duration: 1.2s;
  animation-delay: var(--rd, 0s);
  animation-fill-mode: both;
}
.js [data-reveal="fade"].is-in  { animation-name: reveal-fade;  animation-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95); }
.js [data-reveal="glide"].is-in { animation-name: reveal-glide; animation-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1); }
.js [data-reveal="float"].is-in { animation-name: reveal-float; animation-timing-function: cubic-bezier(0.445, 0.05, 0.55, 0.95); }

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; }
  .js [data-reveal].is-in { animation: none; }
}

/* ==========================================================================
   MOBILE / TABLET  —  below 1280px
   ==========================================================================
   The desktop layout is absolutely positioned on a 1280px canvas, so it
   cannot survive a narrower viewport — it would simply scroll sideways.
   Below 1280 every section leaves absolute positioning and enters normal
   flow, stacking vertically.

   This is NOT a copy of Wix's mobile layout. Per Banner's decision we match
   it in spirit and build it properly. Deliberate improvements over the Wix
   mobile view are marked IMPROVED.
   ========================================================================== */
@media (max-width: 1279px) {

  /* ---- global reset out of absolute positioning ---- */
  .hero__content, .hero__card,
  .proof__inner, .proof__headline, .proof__copy, .proof__title,
  .stat, .stat__num, .stat__label,
  .services__title, .svc-card, .btn-read,
  .forget__q, .forget__a, .btn-touch,
  .cta__title, .cta__copy, .btn-cta, .cta__guarantee, .cta__note,
  .mission__title, .mission__copy,
  .build__title, .build__carousel, .build-card, .build-name, .build-underline, .build-list,
  .site-footer__brand, .site-footer__legal, .site-footer__copy,
  .site-footer__nav, .site-footer__contact, .site-footer__top, .site-footer__bottom {
    position: static;
    left: auto; right: auto; top: auto;
    width: auto;              /* desktop widths are canvas-sized and overflow */
  }
  .svc-card__title { width: auto; }

  .hero, .proof, .services, .forget, .cta,
  .mission, .build, .area,
  .res-intro, .resources,
  .site-footer__inner {
    height: auto;
  }

  :root { --pad: 2.4rem; }
  html { font-size: 10px; }

  /* ---- header: logo + hamburger ---- */
  .site-header { height: 5.6rem; }
  .site-header__inner { padding: 0 var(--pad); align-items: center; }
  .site-header__logo { margin-top: 0; width: auto; height: 2.8rem; gap: 0.8rem; }
  .site-logo__mark { height: 2.6rem; }
  .site-logo__word { font-size: 1.5rem; letter-spacing: 0.1rem; }

  .nav-toggle {
    display: inline-flex; flex-direction: column; justify-content: center; gap: 0.5rem;
    margin-left: auto; width: 4rem; height: 4rem; padding: 0.8rem; cursor: pointer;
  }
  .nav-toggle span { display: block; height: 2px; background: var(--brown-dark); border-radius: 2px; }

  .site-nav {
    position: absolute; top: 5.6rem; left: 0; right: 0;
    margin: 0; flex-direction: column; align-items: stretch; gap: 0;
    background: var(--cream);
    border-top: 1px solid rgba(71, 47, 19, 0.12);
    max-height: 0; overflow: hidden;
    transition: max-height 0.28s ease;
  }
  .site-nav.is-open { max-height: 32rem; }
  .site-nav__link { padding: 1.6rem var(--pad); font-size: 1.5rem; border-radius: 0; }

  .btn-call.btn-call--desktop { display: none; }
  .site-nav__tel {
    display: block;
    padding: 0 var(--pad) 2rem;
    font-size: 1.4rem;
    color: var(--brown);
    text-decoration: underline;
  }
  .btn-call.btn-call--mobile {
    display: flex; margin: 0.8rem var(--pad) 0.8rem;
    width: auto; height: 4.4rem; font-size: 1.5rem; border-radius: 0.8rem;
  }

  /* ---- hero ---- */
  .hero { min-height: 72vh; display: flex; align-items: center; }
  .hero__content { width: 100%; padding: 0 var(--pad); }
  .hero__card { width: 100%; margin: 0; padding: 2.8rem 2.4rem; border-radius: 1.2rem; }
  .hero__title { font-size: 3.2rem; line-height: 4.2rem; letter-spacing: 0.2rem; }

  /* ---- proof ---- */
  .proof { padding: 6.4rem var(--pad); }
  .proof__headline { width: auto; font-size: 2.8rem; line-height: 3.8rem; margin-bottom: 2.8rem; }
  .proof__copy { width: auto; font-size: 1.5rem; line-height: 2.6rem; }  /* IMPROVED: 13px→15px */
  .proof__title { width: auto; font-size: 2.8rem; line-height: 4rem; margin: 5.6rem 0 3.2rem; }

  .proof__stats { display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem 2.4rem; }
  .stat__num   { font-size: 2.6rem; line-height: 3.6rem; }
  .stat__num--inf { font-size: 3.4rem; line-height: 3.6rem; }
  .stat__label { width: auto; font-size: 1.4rem; line-height: 2.2rem; }
  .stat--n1 { grid-area: 1 / 1; } .stat--l1 { grid-area: 2 / 1; margin-bottom: 3.2rem; }
  .stat--n2 { grid-area: 1 / 2; } .stat--l2 { grid-area: 2 / 2; margin-bottom: 3.2rem; }
  .stat--n3 { grid-area: 3 / 1; } .stat--l3 { grid-area: 4 / 1; }
  .stat--n4 { grid-area: 3 / 2; } .stat--l4 { grid-area: 4 / 2; }

  .proof-strip { padding-block: 1.4rem; }
  .proof-strip__inner {
    grid-template-columns: 1fr 1fr;
    padding-inline: var(--pad);
    gap: 1.8rem 2.4rem;
  }
  .proof-stat__num { font-size: 3rem; line-height: 3.6rem; }
  .proof-stat__num--inf { font-size: 3.8rem; line-height: 3.6rem; }
  /* Half the desktop tracking. In a 159px phone column the wide letter-spacing
     pushed every label to three lines, which set the height of the whole band. */
  .proof-stat__label { letter-spacing: 0.104rem; }
  .proof-stat__live { width: 0.7rem; height: 0.7rem; margin-left: 0.9rem; vertical-align: 0.6rem; }

  .reviews { padding: 3.2rem 0 3.2rem; }
  .reviews__eyebrow span { font-size: 1.5rem; letter-spacing: 0.24rem; }
  .reviews__eyebrow::before, .reviews__eyebrow::after { width: 2.8rem; }
  .reviews__track { padding-inline: var(--pad); scroll-padding-inline: var(--pad); }
  .review-card { flex-basis: 25rem; }
  .reviews__carousel::after { width: 4rem; }

  .section-divider { padding-top: 3.2rem; padding-bottom: 2.4rem; }
  .section-divider__line { padding-inline: var(--pad); }

  /* ---- services: flex + order interleaves images with their text ---- */
  .services__inner, .forget__inner, .cta__inner { max-width: none; height: auto; }
  .services__inner { display: flex; flex-direction: column; padding-bottom: 6.4rem; }
  .services__title {
    width: auto; order: 0;
    font-size: 3.6rem; line-height: 5rem; letter-spacing: 0.5rem;
    padding: 6.4rem var(--pad) 3.2rem; text-align: center;
  }
  /* top:auto is essential — the desktop `top` would still offset these
     relatively positioned rows down over the text that follows them */
  .svc-row { position: relative; top: auto; left: auto; width: 100%; height: 22rem; }
  .svc-row__img { position: absolute; inset: 0; width: 100%; }
  .svc-card__title { font-size: 2.2rem; line-height: 3rem; padding: 3.2rem var(--pad) 0; }
  .svc-card__body  { width: auto; font-size: 1.5rem; line-height: 2.6rem; padding: 1.6rem var(--pad) 0; }
  /* width follows the label — a fixed 17rem clipped "Communication Case Study" */
  .btn-read { margin: 2.4rem var(--pad) 4.8rem; width: auto; align-self: flex-start;
              height: 4.4rem; font-size: 1.4rem; padding-inline: 1.6rem; }

  .svc-row--1 { order: 1; } .svc-title--1 { order: 2; } .svc-body--1 { order: 3; } .btn-read--1 { order: 4; }
  .svc-row--2 { order: 5; } .svc-title--2 { order: 6; } .svc-body--2 { order: 7; } .btn-read--2 { order: 8; }
  .svc-row--3 { order: 9; } .svc-title--3 { order: 10; } .svc-body--3 { order: 11; } .btn-read--3 { order: 12; }
  .svc-row--4 { order: 13; } .svc-title--4 { order: 14; } .svc-body--4 { order: 15; } .btn-read--4 { order: 16; }

  /* ---- FAQ + CTA card ----
     Single column: FAQ first, CTA card underneath. The card drops its sticky
     positioning — sticky in a one-column stack just pins it awkwardly. */
  .forget { padding-block: 5.6rem; }
  .forget__inner {
    grid-template-columns: 1fr;
    gap: 4.8rem;
    padding-inline: var(--pad);
  }
  .faq__title { font-size: 2.4rem; line-height: 3.4rem; margin-bottom: 2.4rem; }
  .faq-item__q { font-size: 1.5rem; line-height: 2.5rem; padding: 1.6rem 0; }
  .faq-item__a p { font-size: 1.4rem; line-height: 2.5rem; padding-right: 0; }

  .forget__card { position: static; padding: 3.2rem 2.4rem; }
  .forget__q { font-size: 2.2rem; line-height: 3.2rem; }
  .forget__a { font-size: 1.5rem; line-height: 2.6rem; }
  .btn-touch { height: 5.2rem; font-size: 1.5rem; }

  /* ---- cta ---- */
  .cta__inner { position: relative; padding: 6.4rem var(--pad); }
  .cta__card { position: absolute; inset: 2.4rem; width: auto; height: auto; }
  .cta__title, .cta__copy, .btn-cta, .cta__guarantee, .cta__note { position: relative; z-index: 1; width: auto; }
  .cta__title { font-size: 3rem; line-height: 4rem; padding: 2.4rem 1.6rem 0; }
  .cta__copy  { font-size: 1.5rem; line-height: 2.6rem; padding: 2.4rem 1.6rem 0; }
  .btn-cta    { display: flex; width: calc(100% - 3.2rem); height: 4.8rem; margin: 3.2rem auto 0; }
  .cta__guarantee { font-size: 1.4rem; padding: 2.4rem 1.6rem 0; }
  .cta__note  { font-size: 1.3rem; padding: 1.6rem 1.6rem 2.4rem; }

  /* ---- about: mission ---- */
  .mission { padding-block: 5.6rem; }
  .mission__inner {
    grid-template-columns: 1fr;
    padding-inline: var(--pad);
    gap: 3.2rem;
  }
  .mission__text { border-left: 0; padding-left: 0; }
  .mission__title { font-size: 2.6rem; line-height: 3.6rem; margin-bottom: 2rem; }
  .mission__copy { font-size: 1.5rem; line-height: 2.6rem; }
  .mission__photo { order: -1; width: 100%; }   /* photo first on a phone */

  /* ---- about: what we build with ----
     Rows stack: label above its own logo strip, since a 200px label column
     plus wrapping tiles does not fit a phone. */
  .build { padding: 0 0 6.4rem; }
  .build__inner { padding-inline: var(--pad); }
  .build__title { width: auto; font-size: 2.4rem; line-height: 3.4rem; margin-bottom: 3.2rem; }
  .stack-row { flex-direction: column; gap: 1.2rem; padding: 2rem 0; }
  .stack-row__label { flex: 0 0 auto; font-size: 2rem; line-height: 2.8rem; }
  .stack-row__logos { gap: 0.8rem; }
  .tool { height: 3.6rem; font-size: 1.35rem; padding-inline: 1.2rem; }

  /* ---- about: where we work ---- */
  .area { padding-block: 4.8rem; }
  .area__inner { flex-direction: column; gap: 1.2rem; padding-inline: var(--pad); }
  .area__label { flex: 0 0 auto; font-size: 2rem; line-height: 2.8rem; }
  .area__towns { font-size: 1.9rem; line-height: 3rem; }

  /* ---- free audit ----
     One column. DOM order puts the form ahead of the guarantee block here, so
     a phone gets the fields first rather than scrolling past the pitch. */
  .audit { padding: 3.2rem 0 4.8rem; }
  .audit__inner {
    display: block;
    max-width: none;
    padding-inline: var(--pad);
  }
  .audit__title { font-size: 3rem; line-height: 4rem; margin-bottom: 1.2rem; }
  .audit__copy { font-size: 1.5rem; line-height: 2.6rem; margin-bottom: 2.4rem; }
  .field-row { grid-template-columns: 1fr; gap: 0; }
  .field { margin-bottom: 1.6rem; }
  .field__label { margin-bottom: 0.6rem; }
  .field__input { height: 4.6rem; }
  .audit__assure { margin-top: 2.4rem; }

  /* ---- blog & resources ---- */
  .res-intro__title, .res-intro__copy {
    position: static; left: auto; top: auto; width: auto;
  }
  .res-intro { padding: 5.6rem var(--pad) 0; }
  .res-intro__inner { max-width: none; height: auto; }
  .res-intro__title { font-size: 3.6rem; line-height: 4.8rem; margin-bottom: 2.4rem; }
  .res-intro__copy  { font-size: 1.5rem; line-height: 2.6rem; }

  /* one column on phones */
  .resources { padding-bottom: 0; }
  .resources__inner {
    max-width: none;
    grid-template-columns: 1fr;
    padding: 4.8rem var(--pad) 6.4rem;
    row-gap: 4.8rem;
  }
  .res-card__img { border-radius: 0.8rem; }
  .res-card__title { max-width: none; font-size: 2rem; line-height: 2.8rem; margin-top: 2rem; }
  .res-card__body  { max-width: none; font-size: 1.5rem; line-height: 2.6rem; margin-top: 1.2rem; flex: 0 0 auto; }
  .btn-download    { width: 14rem; height: 4.8rem; font-size: 1.4rem; margin-top: 2rem; }

  /* ---- footer ----
     The single row becomes a stack, but the nav stays a wrapping row rather
     than a column of four: four short links fit two to a line on a phone. */
  .site-footer__inner { padding: 4rem var(--pad) 3.2rem; font-size: 1.4rem; }
  .site-footer__top {
    flex-direction: column;
    align-items: flex-start;
    gap: 2.4rem;
    padding-bottom: 2.4rem;
  }
  .site-footer__brand { display: block; }
  .site-footer__brand .site-header__logo { width: auto; height: 2.8rem; }
  .site-footer__nav { flex-direction: row; gap: 1.6rem 2.4rem; }
  .site-footer__contact { flex-direction: column; gap: 1.2rem; }
  .site-footer__bottom { flex-direction: column; align-items: flex-start; gap: 1.2rem; font-size: 1.3rem; }
  .site-footer__legal { gap: 2.4rem; flex-wrap: wrap; }
}

/* Reveal on small screens: the desktop offsets are up to 400px horizontally,
   which would throw content off a phone. IMPROVED: everything becomes a short
   fade-and-rise instead. */
@media (max-width: 1279px) {
  /* !important because the offsets are inline on each element, and inline
     wins otherwise — the rule looked applied but never was. A 140px sideways
     glide on a 393px screen is what this is guarding against. */
  .js [data-reveal] { --rx: 0px !important; --ry: 24px !important; }
  .js [data-reveal="glide"].is-in { animation-name: reveal-float; }
}

/* Narrow phones */
@media (max-width: 400px) {
  .proof__stats { gap: 0.8rem 1.6rem; }
  .tools__grid { grid-template-columns: repeat(2, 1fr); }
  .hero__title { font-size: 2.8rem; line-height: 3.8rem; }
}

/* ============================================================
   TEXT US — floating CTA
   Replaces the Cloudflare Zaraz "Custom HTML" injection that shipped with the
   previous design. In the codebase it uses the real tokens, is versioned, and
   cannot break from the escaping bug the injected version had.
   Shown only at <=1279px, the same breakpoint where the nav collapses behind
   the hamburger and the phone number stops being reachable in one tap.
   sms: links are also unreliable on desktop, so a desktop button would be a
   dead end on most machines.
   ============================================================ */
.text-us {
  position: fixed;
  z-index: 900;                       /* under the nav drawer, over content */
  right: max(1.6rem, env(safe-area-inset-right));
  bottom: max(1.6rem, env(safe-area-inset-bottom));
  display: none;                      /* enabled in the media query below */
  align-items: center;
  gap: 0.7rem;
  padding: 1rem 1.5rem;
  background: var(--brown-dark);
  border: 1px solid var(--gold);
  border-radius: 0.8rem;
  box-shadow: 0 3px 14px rgba(0, 0, 0, 0.32);
  color: var(--gold);
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  transition: transform 0.18s ease, background-color 0.18s ease;
}
.text-us__icon { width: 1.5rem; height: 1.5rem; flex: none; }
.text-us:hover,
.text-us:focus-visible { background: var(--brown); transform: translateY(-2px); }
.text-us:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }
.text-us:active { transform: translateY(0); }

@media (max-width: 1279px) {
  .text-us { display: inline-flex; }
}

/* The drawer overlays the page; a floating button on top of it reads as a bug.
   nav.js puts .is-open on .site-nav itself, which is inside <header>, so :has()
   is what reaches back up to hide a button that lives after the footer. If a
   browser lacks :has() the button simply stays visible — no layout breakage. */
body:has(.site-nav.is-open) .text-us { display: none; }

@media (prefers-reduced-motion: reduce) {
  .text-us { transition: none; }
  .text-us:hover, .text-us:focus-visible { transform: none; }
}
