/* ═══════════════════════════════════════════════════════════════════════════════════════
   custom.css — the bespoke client layer (Growth+ / D39) for COMPLETE LAWN SERVICE.
   Loaded LAST, after client.css. All bespoke classes are prefixed `cls-`.

   ── THE DERIVATION ─────────────────────────────────────────────────────────────────────
   Everything here comes from this client's own mark and their own words. Nothing is
   borrowed from another client's look.

   FROM THE LOGO (decoded from images/logo.png, 2026-08-13):
     · A CRIMSON LEAF sits to the right of the wordmark (centroid 83% across the mark).
     · A CRIMSON RULE runs the FULL WIDTH along the bottom of the whole lockup.
     · Crimson is 29% of the inked pixels — it is not a garnish, it is half the identity.

   FROM THE ONBOARDING CALL (2026-07-15, Fathom 748686552, ~00:16:12 and ~00:20:20):
     Matt: "you have the green and kind of the RED FROM THE LEAF in your logo, correct?"
     Matt: "we got your dark green and we got the crimson."
     Jody: "Those are the two main colors in there?"  → confirmed. TWO main colors.

   FROM WHO JODY IS:
     · He went to night school for a HORTICULTURE DEGREE and sells "Designs & Renderings"
       — so the visual language uses thin keylines and measured, deliberate framing.
     · "Attention to detail" is the differentiator he names himself. The detailing has to
       look considered at close range.
     · Tone is welcoming and down-to-earth, never flashy. Restraint is on-brand.

   ── THE DEVICES ────────────────────────────────────────────────────────────────────────
   1. THE BASELINE RULE  — a crimson band under photos and headings, straight off the logo.
   2. THE LAYERED PLATE  — an offset green plate behind photos, giving real depth/collage.
   Together: green carries structure, crimson carries every edge, rule, and number.

   ── HARD RULES OBSERVED (D39) ──────────────────────────────────────────────────────────
   · Conversion surfaces (forms, quote cards, phone CTAs) are NEVER animated, rotated or
     leaned. Nothing below touches .quote-card, .contact-form-card, or any tel: button.
   · Hero content stays exempt from entrance animation (LCP guard, D26).
   · Decorative text holds >=4.5:1 contrast. Crimson #A30046 measures 8.0:1 on white and
     7.0:1 on the green-100 tint.
   · Interior pages are reskinned with PURE CSS — no interior HTML was rewritten.
   · Truth guardrails are untouched; this layer restyles, it never rewrites facts.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

body.theme-growth {
  --cls-crimson: #A30046;
  --cls-crimson-deep: #7d0035;   /* hover/active ONLY — a darkened #A30046, not a 2nd brand colour */
  --cls-crimson-tint: #fbeaf1;
  --cls-rule: 7px;              /* thickness of the logo's baseline rule */
  --cls-plate: 14px;            /* offset of the layered plate behind photos */
}

/* ───────────────────────────────────────────────────────────────────────────────────────
   1. THE BASELINE RULE — section headings
   The logo underlines itself in crimson. So do our headings. Replaces the thin border
   with a weighted, logo-proportioned bar.
   ─────────────────────────────────────────────────────────────────────────────────────── */
body.theme-growth .with-rule { border-bottom: 0; padding-bottom: 1.35rem; }
body.theme-growth .with-rule::after {
  content: "";
  display: block;
  margin-top: 1.1rem;
  width: 96px;
  height: var(--cls-rule);
  border-radius: 2px;
  background: var(--cls-crimson);
}
/* On dark/photo sections the rule goes WHITE, matching the white heading it sits under.
   Crimson cannot carry enough contrast against the dark green overlay, and lightening it
   invents a pink that is not in this brand — so white it is. Only the two real brand
   hexes (#00703C, #A30046) plus neutrals appear anywhere on this site. */
body.theme-growth .final-cta .with-rule::after,
body.theme-growth .areas-card .with-rule::after { background: #ffffff; }

/* ───────────────────────────────────────────────────────────────────────────────────────
   2. THE PLAN FRAME + LAYERED PLATE — photographs
   Every site photo gets: an inset crimson baseline (the logo device), an offset green
   plate behind it (depth / collage feel), and a hairline. Applied to the template's own
   image classes so INTERIOR PAGES NEED NO HTML CHANGES.

   box-shadow is used rather than pseudo-elements because several of these boxes are
   `overflow: hidden` (which would clip an ::after frame) and because shadows cannot
   affect layout — important on a build that could not be visually QA'd here.
   ─────────────────────────────────────────────────────────────────────────────────────── */
body.theme-growth .service-image,
body.theme-growth .hub-service-image,
body.theme-growth .framed-image,
body.theme-growth .about-content-image,
body.theme-growth .service-area-photo,
body.theme-growth .cls-collage figure {
  position: relative;
  box-shadow:
    inset 0 calc(var(--cls-rule) * -1) 0 0 var(--cls-crimson),   /* the baseline rule */
    var(--cls-plate) var(--cls-plate) 0 -2px rgba(0, 112, 60, .17), /* layered plate */
    0 18px 45px rgba(0, 49, 26, .13);
}

/* Gallery tiles get the baseline rule + plate (they sit in a tight grid,
   and the lightbox button already carries a focus ring). */
body.theme-growth .gallery-item {
  box-shadow:
    inset 0 -5px 0 0 var(--cls-crimson),
    10px 10px 0 -2px rgba(0, 112, 60, .16),
    0 14px 32px rgba(0, 49, 26, .14);
  transition: transform .18s ease, box-shadow .18s ease;
}
body.theme-growth .gallery-item:hover,
body.theme-growth .gallery-item:focus-visible {
  transform: translate(-3px, -3px);
  box-shadow:
    inset 0 -5px 0 0 var(--cls-crimson),
    16px 16px 0 -2px rgba(163, 0, 70, .22),   /* plate flips to crimson on hover */
    0 18px 40px rgba(0, 49, 26, .18);
}
@media (prefers-reduced-motion: reduce) {
  body.theme-growth .gallery-item { transition: none; }
  body.theme-growth .gallery-item:hover { transform: none; }
}

/* ───────────────────────────────────────────────────────────────────────────────────────
   3. CRIMSON CARRIES THE NUMBERS
   The template's numbered chips and markers were green-on-green. Crimson gives them the
   second brand color a real job, and makes "01 / 02 / 03" read as deliberate detailing.
   ─────────────────────────────────────────────────────────────────────────────────────── */
body.theme-growth .service-jump-grid span,
body.theme-growth .area-link-card span,
body.theme-growth .contact-step-card span {
  background: var(--cls-crimson);
  color: #ffffff;
}
body.theme-growth .area-link-card--cta span { background: #ffffff; color: var(--cls-crimson); }

/* Bulleted check-lists: the marker becomes a small crimson leaf-tip wedge, echoing the
   leaf in the mark rather than a generic dot. */
body.theme-growth .check-list li::before { background: var(--cls-crimson); }
/* The city-list dots sit on the DARK green areas card, where crimson would disappear —
   they stay light, matching the white links beside them. */
body.theme-growth .city-list li::before { background: #ffffff; }

/* Article/meta chips pick up the crimson tint so they read as part of the same system. */
body.theme-growth .article-meta span {
  background: var(--cls-crimson-tint);
  color: var(--cls-crimson);
}

/* ───────────────────────────────────────────────────────────────────────────────────────
   4. THE EYEBROW — small crimson leading rule before the kicker text
   ─────────────────────────────────────────────────────────────────────────────────────── */
body.theme-growth .eyebrow { display: inline-flex; align-items: center; gap: .6rem; }
body.theme-growth .eyebrow::before {
  content: "";
  width: 22px; height: 3px;
  border-radius: 2px;
  background: var(--cls-crimson);
  flex: none;
}
/* On dark/photo sections the tick goes WHITE, matching the white eyebrow text beside it
   (see the note on the heading rule above — no invented pink) — EXCEPT the hero (see
   client feedback 2026-08-14: "vary colors in the hero according to branding"). The hero
   eyebrow tick goes crimson; final-cta and other dark sections keep white. This is a small,
   fully OPAQUE decorative shape, never crimson TEXT on the photo — a solid full-strength
   colour patch is legible by hue difference even where the formal luminance-contrast ratio
   against a photo underlay is low (measured ~1.6-1.8:1 there, which would fail for text or
   a thin stroke, but this is neither). Verified by screenshot before shipping, not by the
   ratio alone. */
body.theme-growth .final-cta .eyebrow::before,
body.theme-growth .eyebrow-light::before { background: #ffffff; }

/* The hero also gets a proper crimson rule between the H1 and the italic location line —
   the same "rule under the heading" grammar every other section on the site already uses
   (`.with-rule::after`), which the hero had never carried. Same opaque-shape reasoning as
   the tick above. */
body.theme-growth .hero-title-main::after {
  content: "";
  display: block;
  margin: 1rem 0 0;
  width: 72px;
  height: 5px;
  border-radius: 3px;
  background: var(--cls-crimson);
}

/* ───────────────────────────────────────────────────────────────────────────────────────
   5. HOMEPAGE BESPOKE — the collage and the signed promise
   These classes are used ONLY in the homepage <main> and the footer partial (D39 limits
   bespoke HTML to those two surfaces).
   ─────────────────────────────────────────────────────────────────────────────────────── */

/* A three-photo layered collage: one large plate, two overlapping it. This is the
   "layers / collage" treatment — built with grid so it cannot overflow on mobile. */
body.theme-growth .cls-collage {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: auto auto;
  gap: 1.1rem;
  align-items: stretch;
}
body.theme-growth .cls-collage figure {
  margin: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-green-800);
}
body.theme-growth .cls-collage figure img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
body.theme-growth .cls-collage .cls-collage-lead {
  grid-column: 1 / -1;
  aspect-ratio: 16 / 9;
}
body.theme-growth .cls-collage .cls-collage-sub { aspect-ratio: 4 / 3; }

/* FEATURE + BASE (client pick, 2026-08-17). Two photos share the top row and the third runs
   the full width beneath as a base plate, giving the block a horizon line and a clear reading
   order (across, then down).

   Replaced a tall-left / two-stacked-right arrangement that measured badly: the two right
   photos came out 291px vs 251px wide with all four edges misaligned, because the overlap was
   applied to only one of them while the 3D leans (section 14.1) fanned them in OPPOSITE
   directions (-11deg vs +9deg). The pair read as accidental rather than placed.

   This also gives the outdoor-lighting shot real size instead of shrinking it into a corner —
   lighting is a priority service for Jody (see the content guardrails in AGENTS.md). */
@media (min-width: 981px) {
  body.theme-growth .cls-collage {
    grid-template-columns: 1fr 1fr;   /* equal, not 1.35fr/1fr — see below */
    grid-template-rows: auto auto;
    gap: 1.4rem;
  }
  /* The top pair is now IDENTICAL in every respect: equal columns, one shared aspect ratio,
     no negative margin. The previous version overlapped them by -1.9rem (measured: a real
     -12px overlap, not just a tight gap) and sized them 365x274 vs 305x278, on top of the
     opposing 3D leans removed in 14.1. Client read the result as cramped and mismatched,
     which it was. Two photos sitting side by side have to match or the eye reads the
     difference as a mistake; the visual interest is carried by the wide base plate below
     and by the crimson rule + plate they all now share. */
  body.theme-growth .cls-collage .cls-collage-lead,
  body.theme-growth .cls-collage .cls-collage-sub:nth-of-type(2) {
    grid-row: 1;
    aspect-ratio: 4 / 3;
    min-height: 0;
    margin-left: 0;
  }
  body.theme-growth .cls-collage .cls-collage-lead { grid-column: 1; }
  body.theme-growth .cls-collage .cls-collage-sub:nth-of-type(2) { grid-column: 2; }
  /* The base plate spans both columns and squares the block off along the bottom. */
  body.theme-growth .cls-collage .cls-collage-sub:nth-of-type(3) {
    grid-column: 1 / -1; grid-row: 2;
    aspect-ratio: 20 / 7;
    min-height: 0;
    margin-left: 0;
  }
}

/* The "Since 1997" seal — a small crimson-ruled badge. Nearly 30 years is the single
   most valuable thing this company owns, so it gets a mark of its own. */
body.theme-growth .cls-seal {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  gap: .15rem;
  padding: .85rem 1.15rem;
  border-radius: var(--radius-md);
  background: #ffffff;
  border-bottom: var(--cls-rule) solid var(--cls-crimson);
  box-shadow: 0 14px 34px rgba(0, 49, 26, .16);
}
body.theme-growth .cls-seal strong {
  font-size: 1.6rem;
  line-height: 1;
  color: var(--color-green-700);
  letter-spacing: -.02em;
}
body.theme-growth .cls-seal span {
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--cls-crimson);
}

/* The Owner's Promise, presented as a signed card rather than plain prose. */
body.theme-growth .cls-promise {
  position: relative;
  padding: clamp(1.8rem, 4vw, 2.9rem);
  border-radius: var(--radius-lg);
  background: #ffffff;
  border-bottom: var(--cls-rule) solid var(--cls-crimson);
  box-shadow: var(--cls-plate) var(--cls-plate) 0 -2px rgba(0, 112, 60, .17),
              0 20px 50px rgba(0, 49, 26, .13);
}
body.theme-growth .cls-promise .cls-promise-quote {
  margin: 0 0 1.4rem;
  font-family: var(--font-heading);
  font-size: clamp(1.35rem, 2.6vw, 1.95rem);
  line-height: 1.28;
  color: var(--color-ink);
}
body.theme-growth .cls-promise figcaption { display: flex; align-items: center; gap: .9rem; }
body.theme-growth .cls-promise figcaption span { display: block; }
body.theme-growth .cls-promise .cls-promise-name {
  font-weight: 900;
  color: var(--color-green-700);
}
body.theme-growth .cls-promise .cls-promise-role {
  font-size: .92rem;
  color: var(--color-muted);
}
/* THE REAL LEAF. images/leaf.png is the crimson leaf cut directly out of the client's own
   logo (106x164, extracted 2026-08-13) and used as a mask, so it can be tinted per context.
   This is the one ornament on the site that is unarguably theirs. */
body.theme-growth .cls-leaf {
  width: 30px; height: 46px; flex: none;
  background: var(--cls-crimson);
  -webkit-mask: url('/images/leaf.png') no-repeat center / contain;
          mask: url('/images/leaf.png') no-repeat center / contain;
}

/* ───────────────────────────────────────────────────────────────────────────────────────
   6. THE FOOTER — the logo's full-width crimson rule, reproduced at page scale
   Bespoke footer classes live in partials/footer.html (D39 rule 5).
   ─────────────────────────────────────────────────────────────────────────────────────── */
body.theme-growth .site-footer { border-top: var(--cls-rule) solid var(--cls-crimson); }
body.theme-growth .site-footer h2 { color: #ffffff; }
body.theme-growth .site-footer .footer-cta .btn-primary { background: var(--cls-crimson); color: #ffffff; }
body.theme-growth .site-footer .footer-cta .btn-primary:hover { background: var(--cls-crimson-deep); color: #ffffff; }

/* ───────────────────────────────────────────────────────────────────────────────────────
   7. SECONDARY BUTTONS + FOCUS — crimson as the interaction color
   The primary CTA stays brand green (it is the dominant color and the money button);
   crimson takes the secondary/outline role so both colors do real work.
   ─────────────────────────────────────────────────────────────────────────────────────── */
body.theme-growth .btn-outline {
  border-color: var(--cls-crimson);
  color: var(--cls-crimson);
}
body.theme-growth .btn-outline:hover {
  background: var(--cls-crimson);
  border-color: var(--cls-crimson);
  color: #ffffff;
}
/* Emerson is the one served city whose entry points at /contact/ rather than its own page,
   so on /contact/ itself it is plain text (a link back to the page you are already on is a
   dead control). The template only weights the <a>, which left that one item visibly lighter
   than its neighbours — match it so the list reads as one set. */
body.theme-growth .sidebar-callout--areas li { font-weight: 850; }

/* Secondary button for the DARK cta-panel (city pages: phone beside "Request An Estimate").
   .btn-outline could not be reused here — it is crimson on this build, and crimson on the
   near-black-green panel is far too dark to read. This is the white-ghost counterpart to
   .btn-light: white label, translucent white keyline, so the pair reads primary/secondary
   instead of two identical white pills. Text stays white in every state (same reason the
   in-text CTA phone link is pinned — base.css's `a:hover` would otherwise green it out). */
body.theme-growth .btn-cta-ghost {
  background: transparent;
  border-color: rgba(255, 255, 255, .62);
  color: #ffffff;
  box-shadow: none;
}
body.theme-growth .btn-cta-ghost:hover,
body.theme-growth .btn-cta-ghost:focus-visible,
body.theme-growth .btn-cta-ghost:active {
  background: rgba(255, 255, 255, .14);
  border-color: #ffffff;
  color: #ffffff;
}

body.theme-growth a:focus-visible,
body.theme-growth button:focus-visible {
  outline: 3px solid var(--cls-crimson);
  outline-offset: 3px;
}

/* Text links inside body copy get a crimson underline so the second brand color appears
   in the reading experience, not just in decoration. */
body.theme-growth .services-main p a,
body.theme-growth .city-intro-copy a,
body.theme-growth .about-story-section a,
body.theme-growth .split-copy p a,
body.theme-growth .careers-info-card p a {   /* the careers "How to Reach Out" phone */
  color: var(--cls-crimson);
  text-decoration: underline;
  text-decoration-color: var(--cls-crimson);
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}

/* Phone links inside hero copy sit on the dark photo overlay. `a { color: inherit }` gives
   them white at rest, but base.css's sitewide `a:hover { color: var(--color-green-700) }`
   would repaint them #1d6b3f on a near-black-green ground on hover — the same vanishing-text
   failure already fixed on the review-widget button and the CTA-panel phone link. Held white
   in every state, underlined so it does not rely on colour alone. */
body.theme-growth .hero-copy a {
  color: #ffffff;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 2px;
}
body.theme-growth .hero-copy a:hover,
body.theme-growth .hero-copy a:focus-visible,
body.theme-growth .hero-copy a:active { color: #ffffff; }

/* ───────────────────────────────────────────────────────────────────────────────────────
   8. MOBILE — keep every bespoke device from crowding a 390px screen
   ─────────────────────────────────────────────────────────────────────────────────────── */
@media (max-width: 620px) {
  body.theme-growth {
    --cls-plate: 8px;
    --cls-rule: 5px;
  }
  body.theme-growth .cls-collage { grid-template-columns: minmax(0, 1fr); }
  body.theme-growth .cls-collage .cls-collage-lead { aspect-ratio: 4 / 3; }
  /* Belt-and-braces reset of the desktop overlap. Was `:first-of-type`, which matches nothing
     here (the lead figure is the first <figure>), so this rule had never actually fired. */
  body.theme-growth .cls-collage .cls-collage-sub { margin-left: 0; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   9. "THE DRAWN PLAN" — the typographic + layout system (added 2026-08-13)

   WHY THIS AND NOT SOMETHING ELSE: Jody went to night school for a horticulture degree
   specifically to stop being a mowing company, and he sells "Designs & Renderings" — he
   literally sells drawn plans. He has worked one corner of Northwest Georgia since 1997
   and names "attention to detail" as the reason people pick him. So the site is built to
   look like a DRAWN PLAN SHEET / botanical plate: serif headings, mounted specimen photos, plan labels in letterspaced caps, and a drafting title block.

   This is deliberately NOT the Greenz "Job-Site Journal" (cream paper, taped snapshots,
   stencil numerals). That look belongs to Greenz — a young, scrappy 2022 crew. This one
   belongs to a horticulturist approaching thirty years in business. Same method, opposite
   temperament.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* ── 9.1 TYPE ──────────────────────────────────────────────────────────────────────────
   Retuned 2026-08-18 when the type switched to the system stack used on the live site.
   The -.012em tracking and 700 weight here were set for Bitter, a slab serif that needed
   air. A system sans (SF / Segoe UI / Roboto depending on the OS) is a different problem:
   at heading sizes it wants slightly NEGATIVE tracking to stop looking loose, and it
   carries more apparent weight at the same numeric value, so 700 is enough without
   tipping into heavy. base.css's -.045em is still too tight for these sizes. */
body.theme-growth h1,
body.theme-growth h2,
body.theme-growth h3 {
  letter-spacing: -.021em;
  font-weight: 700;
}
body.theme-growth h1 { line-height: 1.02; }
body.theme-growth h2 { line-height: 1.06; }
body.theme-growth .hero-title { line-height: 1.0; }

/* Body copy. The .002em nudge existed to open up Public Sans; the system stack is already
   comfortably spaced at text sizes, so it goes back to normal rather than reading loose. */
body.theme-growth { font-feature-settings: "kern" 1, "liga" 1; }
body.theme-growth p { letter-spacing: normal; }

/* ── 9.2 THE PLAN LABEL — eyebrows and the hero location line ──────────────────────────
   Started as a large mint-green italic (template default), which competed with the H1, so
   it was cut down to a plain small white caps line with a rule above. That went too far
   the other way — client feedback 2026-08-14: it now blends into the hero copy underneath
   it, since both are white text of a similar size. Given a solid crimson badge instead of
   text-on-photo, which reads as a distinct UI element rather than another line of prose —
   the same fill-badge language already used for the hero corner stamp and the specialty
   badges. A filled block (not a pill) on purpose: this label can run two lines on the
   longer city lists (Service Areas hub, city pages), and a true pill shape looks wrong
   once it wraps. White-on-crimson measures 7.94:1, comfortably clear of AA. */
/* Second attempt (2026-08-14): the badge/fill from the previous pass was itself the
   thing flagged — client wants emphasis from TYPOGRAPHY (size, weight, colour), no
   background shape, pointing at the Greenz hero as the reference for that APPROACH (not
   its pixels — theirs is a bold italic sans in their brand green on a flat cream hero; this
   is a bold italic SERIF in white, because our hero sits on a photo overlay, not a flat
   colour, and our display face is Bitter, not a grotesque). Scaled up to genuinely read as
   a secondary line under the H1 — the template's original mint-green italic had the right
   idea on scale, just the wrong colour and no real relationship to the rest of the type
   system; this keeps that scale in the site's own display face instead. */
body.theme-growth .hero-title-location {
  display: block;
  margin-top: .85rem;
  max-width: 100%;
  font-family: var(--font-heading);
  font-style: italic;
  font-size: clamp(1.25rem, 1.8vw, 1.6rem);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.01em;
  white-space: normal;
  text-wrap: balance;
  overflow-wrap: anywhere;
  text-transform: none;
  color: #ffffff;
}
body.theme-growth .eyebrow {
  font-family: var(--font-body);
  font-weight: 800;
  letter-spacing: .17em;
  font-size: .74rem;
}

/* ── 9.3 (REMOVED) THE SURVEY GRID ─────────────────────────────────────────────────────
   A hairline plan-paper texture used to sit on the light bands here. Removed on client
   feedback 2026-08-13 — it read as noise rather than craft. Do not reinstate it. The
   plan-sheet idea is carried by the mounted photo frames, the schedule numbering and the
   title block instead, which do the job without patterning the whole page. */

/* ── 9.4 THE MOUNTED SPECIMEN — photographs get a mat and a keyline ────────────────────
   A white mat separates the photo from the page the way a mounted botanical specimen is
   separated from its board. border-box keeps the mat INSIDE the existing footprint, so
   nothing reflows. */
body.theme-growth .service-image,
body.theme-growth .hub-service-image,
body.theme-growth .framed-image,
body.theme-growth .about-content-image,
body.theme-growth .service-area-photo,
body.theme-growth .cls-collage figure {
  border: 9px solid #ffffff;
  background-clip: padding-box;
  border-radius: var(--radius-lg);   /* match the site's own soft corners (34px) — a hard
                                         6px mat read as "sharp" against everything else
                                         on the page, client feedback 2026-08-14 */
}
body.theme-growth .gallery-item {
  border: 7px solid #ffffff;
  background-clip: padding-box;
  border-radius: var(--radius-md);   /* was 6px — matches the template's own 22px tiles */
}

/* ── 9.5 THE PLANT SCHEDULE — the homepage service rows, numbered ──────────────────────
   Numbered with a CSS counter, so the homepage HTML stays as generated: a schedule key on
   a planting plan. Toned down 2026-08-18 — the numbering had grown into the loudest thing
   on several pages (client: "the numbers are too distracting"). Measured before the change:
   67.68px on the service pages, 24px here, against 14–17px for every other number on the
   site. This one keeps its role as a quiet marker of sequence, at label size rather than
   heading size. */
body.theme-growth .alternating-services { counter-reset: cls-schedule; }
body.theme-growth .alternating-services .service-card { counter-increment: cls-schedule; }
body.theme-growth .alternating-services .service-card::before {
  content: counter(cls-schedule, decimal-leading-zero);
  display: block;
  margin-bottom: .5rem;
  padding-bottom: .4rem;
  width: 2.4ch;
  border-bottom: 2px solid var(--cls-crimson);
  font-family: var(--font-body);
  font-size: .82rem;
  font-weight: 900;
  letter-spacing: .1em;
  line-height: 1;
  color: var(--color-green-700);
}

/* The sub-service headings on the core service pages USED to carry the same counter
   inline: `01 · Patios & Walkways`. Removed. Because it sat inside the <h2> it inherited
   the full heading size — 67.68px of crimson, as large as the service name itself — so it
   read as the headline and pushed the actual title onto a second line. It also carried no
   information the heading did not already give. The sections are still in a deliberate
   order; they just no longer announce it. */
body.theme-growth .services-main { counter-reset: cls-sub; }

/* ── 9.6 THE TITLE BLOCK — the drafting block on the homepage ──────────────────────────
   Every drawn plan carries a title block: who drew it, where, and when. Bespoke HTML,
   homepage only. */
body.theme-growth .cls-titleblock {
  display: grid;
  /* 4 cells, so the column count must divide into 4 or the last row strands one cell.
     auto-fit with a 150px floor landed on 3 columns at ~1024px and left a gap. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  margin-top: clamp(2rem, 5vw, 3.2rem);
  border: 2px solid var(--color-green-700);
  border-radius: var(--radius-md);   /* was 4px — matches every other card on the site
                                         (quote-card, sidebar-callout), 2026-08-14 */
  overflow: hidden;
  background: #ffffff;
}
body.theme-growth .cls-titleblock div {
  padding: 1rem 1.15rem;
  border-right: 1px solid rgba(0, 49, 26, .16);
}
body.theme-growth .cls-titleblock div:last-child { border-right: 0; }
body.theme-growth .cls-titleblock dt {
  margin: 0 0 .3rem;
  font-size: .68rem;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--cls-crimson);
}
body.theme-growth .cls-titleblock dd {
  margin: 0;
  font-family: var(--font-heading);
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.15;
  color: var(--color-green-700);
}

/* ── 9.7 (REMOVED) SECTION RULE LEAF NOTCH ─────────────────────────────────────────────
   The heading rule used to carry a small leaf-tip wedge at its end (`.with-rule::before`).
   Removed on client feedback 2026-08-14 — unnecessary next to the rule itself. The rule
   (`.with-rule::after`) stays untouched everywhere. Do not reinstate the notch. */

/* ── 9.8 THE SEAL, restyled as a stamped plan mark ─────────────────────────────────────*/
body.theme-growth .cls-seal {
  margin: 1.6rem 0 0;
  border: 2px solid var(--color-green-700);
  border-bottom-width: var(--cls-rule);
  border-bottom-color: var(--cls-crimson);
  border-radius: var(--radius-md);   /* was 4px, same reasoning as the title block */
}
body.theme-growth .cls-seal strong { font-family: var(--font-heading); }

/* ── 9.9 MOBILE ────────────────────────────────────────────────────────────────────────*/
@media (max-width: 620px) {
  body.theme-growth .service-image,
  body.theme-growth .hub-service-image,
  body.theme-growth .framed-image,
  body.theme-growth .about-content-image,
  body.theme-growth .service-area-photo,
  body.theme-growth .cls-collage figure { border-width: 6px; }
  body.theme-growth .gallery-item { border-width: 5px; }
  body.theme-growth .hero-title-location { max-width: 100%; white-space: normal; }
  body.theme-growth .cls-titleblock div { border-right: 0; border-bottom: 1px solid rgba(0, 49, 26, .16); }
  body.theme-growth .cls-titleblock div:last-child { border-bottom: 0; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   10. CRIMSON GETS REAL ESTATE (client feedback 2026-08-13: "use the colour branding,
       not just green all over")

   Until now crimson only appeared as rules, numerals and edges — correct, but thin, on a
   brand where the client confirmed green and crimson are BOTH main colours. So crimson now
   owns a whole band on the homepage, and the leaf lifted out of the logo appears at scale.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

body.theme-growth .cls-band-crimson {
  position: relative;
  overflow: hidden;
  background: var(--cls-crimson);
}
/* The client's own leaf, blown up as a watermark. Masked, so it is a tint of the band
   rather than a pasted graphic. Decorative only — aria-hidden, no text sits on it. */
body.theme-growth .cls-band-crimson::before {
  content: "";
  position: absolute;
  top: -6%;
  right: -3%;
  width: clamp(190px, 26vw, 380px);
  height: 120%;
  background: rgba(255, 255, 255, .11);
  -webkit-mask: url('/images/leaf.png') no-repeat center / contain;
          mask: url('/images/leaf.png') no-repeat center / contain;
  pointer-events: none;
}
body.theme-growth .cls-band-crimson > * { position: relative; }
body.theme-growth .cls-band-crimson .eyebrow { color: #ffffff; }
body.theme-growth .cls-band-crimson .eyebrow::before { background: #ffffff; }

/* The promise card sits on the crimson band as clean white paper. */
body.theme-growth .cls-band-crimson .cls-promise {
  box-shadow: var(--cls-plate) var(--cls-plate) 0 -2px rgba(0, 49, 26, .28),
              0 26px 60px rgba(0, 20, 10, .26);
}

/* NOTE: the check-list marker deliberately keeps the template's CHECKMARK mask and is
   only recoloured crimson (section 3). A leaf was tried here and reverted — the checkmark
   carries the meaning "included", and at .9em square the tall leaf silhouette squashes
   into an unreadable blob. The leaf stays where it can be read: the promise signature and
   the crimson band watermark. */

/* ── The review widget ships low-contrast greys (~2.3:1) fleet-wide. Darken to AA on our
      light card. Same fix carried on the Greenz build. ─────────────────────────────────*/
body.theme-growth .llm-rw-author-meta span,
body.theme-growth .llm-rw-powered { color: #565e6a !important; }

/* "Read all N reviews on Google" is an <a>, so base.css's sitewide `a:hover { color:
   var(--color-green-700) }` was repainting its label the SAME green as its own accent
   background on hover — the text disappeared entirely (measured 1:1). The widget's own
   :hover rule only does transform/shadow, so this was our bleed, not theirs.

   Pinned white across every interactive state. `a.llm-rw-load-more` alone ties `a:hover`
   on specificity (0,1,1) and only wins because custom.css loads later, so the states are
   named explicitly and scoped to body.theme-growth — that holds regardless of load order. */
body.theme-growth a.llm-rw-load-more,
body.theme-growth a.llm-rw-load-more:hover,
body.theme-growth a.llm-rw-load-more:focus-visible,
body.theme-growth a.llm-rw-load-more:active { color: #fff; }

/* The aggregate line above the widget: centred, quiet, crimson link. */
body.theme-growth [data-llm-reviews-agg] {
  margin: 0 0 1.4rem;
  text-align: center;
  color: var(--color-muted);
}
body.theme-growth [data-llm-reviews-agg] a {
  color: var(--cls-crimson);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  font-weight: 700;
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   11. THE MAP (settled 2026-08-13)

   The name is shown by GOOGLE'S OWN PLACE CARD, inside the frame — no bar of ours above it
   and nothing cropped.

   How it got here, so nobody re-litigates it:
     · First attempt used `maps/embed?pb=...place_id:` — that form geocodes nothing and
       rendered the WHOLE WORLD instead of Kingston.
     · Second attempt added a crimson header bar above the frame. That did not replace
       Google's control (which is painted inside the iframe), so both showed at once.
     · Third attempt cropped 54px off the top to hide that control — which sliced the top
       off Google's business card, leaving a stub reading "30145, USA".
     · Settled: the CID form, `maps.google.com/maps?cid=<GBP cid>&output=embed`, which
       renders the full place card — name, address, rating — inside the frame. This is what
       the Greenz build uses. Service-area maps use the city query form and show that
       city's card. Nothing overlaid, nothing cropped, attribution untouched.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

body.theme-growth .cls-map { overflow: hidden; border-radius: var(--radius-md); background: var(--color-green-900); }
body.theme-growth .cls-map .gbp-map-embed {
  margin: 0;
  border-bottom: 0;
  border-radius: 0;
  aspect-ratio: 16 / 9;
  box-shadow: none;
}

/* Inside the dark areas card the map bleeds to the card edges, as the template intends.
   ONLY on the plain .areas-card (the homepage). The `--map` variant is a map-only card whose
   own rule already zeroes the bleed — applying it there pushed the bar and frame ~100px wider
   than the 380px card, and the card is overflow:hidden, so the right edge was CLIPPED
   (measured on /contact/, 2026-08-13). */
body.theme-growth .areas-card:not(.areas-card--map) .cls-map {
  margin: calc(var(--areas-card-pad) * -1) calc(var(--areas-card-pad) * -1) 1.75rem;
  border-radius: 0;
}
body.theme-growth .areas-card--map .cls-map { margin: 0; }

/* The company map needs a visible frame so it reads as a deliberate location card rather
   than a dry iframe dropped onto the page. Crimson leads; the green offset supports it. */
body.theme-growth .service-area-map-section .areas-card--map {
  padding: clamp(.5rem, 1.5vw, .85rem);
  border: 2px solid #a30046;
  background: #ffffff;
  box-shadow: 10px 10px 0 rgba(0,112,60,.14), 0 18px 45px rgba(24,45,34,.12);
}
body.theme-growth .service-area-map-section .areas-card--map .cls-map {
  border: 1px solid rgba(0,112,60,.32);
  border-radius: calc(var(--radius-lg) - .55rem);
}
/* Sidebar maps on the city pages sit a little taller than wide. */
body.theme-growth .cls-map--sidebar .gbp-map-embed { aspect-ratio: 1 / .82; }

/* Area cards are numbered 01-06 rather than initialled (client feedback 2026-08-13 —
   two cities starting with "C" both rendered a "C" badge, which read as a mistake).
   Sized explicitly so two digits sit comfortably in the 42px disc. */
body.theme-growth .area-link-card span {
  font-family: var(--font-heading);
  font-size: .9rem;
  font-weight: 700;
  letter-spacing: -.02em;
}

/* ── CONTRAST FIX (found by the automated audit, 2026-08-13) ────────────────────────────
   The contact page's info card reuses `.footer-list`, whose colours are written for the
   DARK footer — rgba(255,255,255,.72) text and .82 links. On the card's light background
   that rendered white-on-white: the address, hours, phone and email were invisible
   (measured 1.05:1 and 1.06:1 against #f6f8f5). Scope the colours back to readable ink. */
body.theme-growth .contact-info-card .footer-list { color: var(--color-muted); }
body.theme-growth .contact-info-card .footer-list a {
  color: var(--cls-crimson);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  font-weight: 700;
}
body.theme-growth .contact-info-card > h2 {
  margin-bottom: 1rem;
  font-size: clamp(1.2rem, 1.5vw, 1.3rem);
  line-height: 1.15;
  letter-spacing: -.025em;
}

/* ── LAYOUT FIX: the heading rule inside flex/centred headings ──────────────────────────
   Found by visual QA 2026-08-13 (the automated contrast pass could not see it).
   `.split-heading` is `display:flex; justify-content:space-between`, so the container's
   ::after — our crimson rule — became a FLEX ITEM and flew to the far right of the row,
   detached from the heading, with the leaf notch stranded beneath it. Taking both out of
   flow with absolute positioning pins them back under the heading text. */
body.theme-growth .split-heading.with-rule { position: relative; padding-bottom: 1.9rem; }
body.theme-growth .split-heading.with-rule::after {
  position: absolute; left: 0; bottom: 0; margin-top: 0;
}
/* Centred headings (the reviews block): centre the rule. */
body.theme-growth .centered.with-rule::after { margin-left: auto; margin-right: auto; }

/* On narrow screens the full-bleed map overhung its card by ~4px (the card's padding token
   scales with the viewport, the bleed did not) and the card is overflow:hidden, so a sliver
   of map was clipped. Below 620px the map simply sits inside the padding instead. */
@media (max-width: 620px) {
  body.theme-growth .areas-card:not(.areas-card--map) .cls-map {
    margin: 0 0 1.5rem;
    border-radius: var(--radius-md);
  }
}

/* ── The map shows Google's OWN place card, and that is deliberate ──────────────────────
   An earlier pass added a crimson header bar above each frame and cropped 54px off the top
   of the map to hide Google's controls. Both are gone (client feedback 2026-08-13): the
   crop was slicing the top off Google's business card, leaving a stub reading "30145, USA",
   and the bar duplicated a name the map already displays.

   The business maps now use the CID form — `maps.google.com/maps?cid=<GBP cid>&output=embed`
   — which renders the full place card INSIDE the frame: business name, address and rating.
   Same approach as the Greenz build. The service-area maps use the city query form, which
   shows that city's card. Nothing is cropped or overlaid. */

/* ═══════════════════════════════════════════════════════════════════════════════════════
   12. THE ABOUT PAGE — a timeline, not a stack of paragraphs (2026-08-14)

   The about page used to be five identically-shaped `.about-story-section` blocks in a
   row — Jody's actual 29-year arc (start → night school → crew → today) rendered with no
   sense that time was passing. It read exactly like the generic "About Us" wireframe every
   Growth site ships, because structurally it WAS that wireframe.

   This is the one content story on the whole site that is genuinely chronological and
   genuinely unique to this owner, so it gets a shape that reads as chronological: a rail
   down the left with a dot per era and a small crimson date/era label above each heading —
   the same device a hand-drawn plan uses for a phasing diagram.

   `.about-story-section` (the template base class) still carries every article for its
   safe heading scale, paragraph colour/leading, and the mobile overflow-wrap rule (see
   components.css). `.cls-timeline-item` only ADDS the rail treatment — never remove the
   base class when editing this page.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

body.theme-growth .cls-timeline {
  position: relative;
  padding-left: 2.1rem;
}
/* the rail: one continuous line, so it survives the full-width image break cleanly */
body.theme-growth .cls-timeline::before {
  content: "";
  position: absolute;
  top: .5rem;
  bottom: .5rem;
  left: .3rem;
  width: 2px;
  background: var(--color-line);
}
/* The image used to be pulled the FULL -2.1rem, flush to the container edge, which put it
   directly on top of the rail — the line vanished behind every photo and read as a break in
   the timeline rather than one continuous run. Pulled back so it clears the rail with a
   visible gutter (rail ends at ~6.8px, image starts at ~19px) while keeping a slight
   break-out from the text column, so the offset still reads as deliberate.
   Also spaces the image off the era label below it, which was sitting flush at 0px. */
body.theme-growth .cls-timeline .about-content-image {
  margin-left: -.9rem;
  margin-bottom: clamp(1.8rem, 2.8vw, 2.5rem);
}

body.theme-growth .cls-timeline-item {
  position: relative;
  border-bottom: 0;             /* the rail replaces the template's horizontal divider */
  padding-bottom: clamp(1.6rem, 2.6vw, 2.25rem);
}
body.theme-growth .cls-timeline-item::before {
  content: "";
  position: absolute;
  top: .45rem;
  left: -2.1rem;
  width: 11px; height: 11px;
  border-radius: 50%;
  background: var(--cls-crimson);
  border: 2px solid #fffdf6;
  box-shadow: 0 0 0 2px var(--color-line);
}
body.theme-growth .cls-timeline-item--today::before { background: var(--color-green-700); }

body.theme-growth .cls-era {
  margin: 0 0 .35rem;
  font-family: var(--font-body);
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--cls-crimson);
}
body.theme-growth .cls-timeline-item h2 {
  font-size: clamp(1.5rem, 2.3vw, 2.1rem) !important;   /* the base class sizes these as
     page-level headings (up to 3rem) — too heavy repeated six times down one column */
  margin-bottom: .55rem;
}

@media (max-width: 620px) {
  body.theme-growth .cls-timeline { padding-left: 1.5rem; }
  body.theme-growth .cls-timeline-item::before { left: -1.5rem; }
  /* same clearance logic as above, scaled to the tighter mobile gutter */
  body.theme-growth .cls-timeline .about-content-image { margin-left: -.6rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   13. SIGNATURE VS. UTILITY SERVICE PAGES (2026-08-14)

   All five service pages used to share one wireframe with no distinction between them —
   Irrigation read exactly like Hardscaping, structurally, because both came from the same
   template. But Jody does not treat these five services as equals: on the onboarding call
   he named hardscaping his favourite and most profitable work, asked for outdoor lighting
   to be its own standalone section rather than buried as an add-on, and the whole reason he
   earned a horticulture degree was to do landscape design and installation properly. Those
   three are his specialties. Maintenance and irrigation are the steady, practical workhorses
   — no less necessary, just not the thing he leads with.

   So the three specialty pages (hardscaping, landscape-design-install, outdoor-lighting) get
   ONE extra component — a short editorial statement, not a form or a card — that a workhorse
   page does not. Maintenance and irrigation stay exactly as clean and efficient as they were:
   that restraint is deliberate, not an oversight. Not every page needs the same ornament.

   The copy in `.cls-signature` is OUR voice describing the owner, grounded in verified facts
   from the onboarding call — never framed as a direct quotation, so there is no verbatim-vs-
   audio risk the way the homepage Owner's Promise carries.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

body.theme-growth .cls-signature {
  position: relative;
  margin: .3rem 0 2.4rem;
  padding: 1.9rem clamp(1.5rem, 4vw, 2.6rem) 1.9rem 2.3rem;
  border-left: 4px solid var(--cls-crimson);
  background: var(--color-bg);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
body.theme-growth .cls-signature-label {
  margin: 0 0 .5rem;
  font-family: var(--font-body);
  font-size: .72rem;
  font-weight: 800;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--cls-crimson);
}
body.theme-growth .cls-signature h3 {
  margin: 0 0 .6rem;
  font-family: var(--font-heading);
  font-size: clamp(1.4rem, 2.4vw, 1.9rem);
  line-height: 1.15;
  color: var(--color-green-700);
}
body.theme-growth .cls-signature p:last-child {
  margin: 0;
  max-width: 62ch;
  color: var(--color-ink);
  font-size: 1.06rem;
  line-height: 1.55;
}
@media (max-width: 620px) {
  body.theme-growth .cls-signature { padding: 1.4rem 1.25rem 1.4rem 1.4rem; border-radius: 0 var(--radius-md) var(--radius-md) 0; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   14. REAL DEPTH — CSS 3D, homepage only (2026-08-14)

   Not WebGL, not a JS library: pure CSS `perspective`/`rotateX`/`rotateY` on three already-
   decorative elements. That keeps it free (no new dependency, no render-blocking script, no
   risk to load time on a marketing site) and keeps it OFF anything load-bearing — nothing
   here touches the hero (LCP-critical, D26), a form, a quote card, or a phone CTA (D39).

   Static tilts only (no continuous motion). Where a hover transition is added, it is guarded
   by `(hover: hover) and (pointer: fine)` so touch devices never get a stuck hover state, and
   by `prefers-reduced-motion` throughout.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* 14.1 — the collage USED TO lean each photo a different way ("scattered, placed prints").
   Removed 2026-08-17 on client review: side by side, opposing leans do not read as casual,
   they read as two different components. Measured, the top pair had opposite rotateY (+3deg
   vs -8deg), different sizes (365x274 vs 305x278), tops 4px out of line — and the lean rules
   carried their OWN box-shadow, which REPLACED the shared photo treatment from section 2.
   So the right-hand photo had a plain drop shadow while the left had the offset green plate.
   That is the mismatch the client saw: it was not the same treatment.

   The collage now sits flat and uniform and inherits section 2 like every other photo.
   The 3D language is not gone from the build — the crimson band's leaf watermark (14.2)
   still carries it, where there is no neighbour for it to disagree with.

   NOTE for whoever touches this next: section 2's `inset 0 -7px crimson` baseline rule does
   NOT render on these three. Collage figures hold a child <img>, and an inset shadow paints
   behind element content, so the photo covers it. It works on .hub-service-image and friends
   only because those carry their photo as a background-image on the div itself. Verified by
   sampling pixels on both the current and the previously deployed build — zero crimson on
   either, so this is long-standing, not a regression from this change. Left alone
   deliberately: adding the rule back is a design call, not a bug fix, and the brief here was
   to make the group calmer. */
@media (min-width: 981px) and (hover: hover) and (pointer: fine) {
  body.theme-growth .cls-collage figure { transition: transform .3s ease, box-shadow .3s ease; }
  body.theme-growth .cls-collage figure:hover { transform: translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  body.theme-growth .cls-collage figure { transition: none; }
}

/* 14.2 — the crimson band's leaf watermark tilts in 3D like a die-stamped plate rather than
   a flat pasted sticker — the same "official plan" language as the title block and seal. */
body.theme-growth .cls-band-crimson { perspective: 900px; }
body.theme-growth .cls-band-crimson::before { transform: rotateY(-16deg) rotateX(6deg); }

/* 14.3 — the five core-service photos lift and tilt slightly toward the reader on hover,
   as if they are set on the page rather than printed flat on it. Desktop pointer only; the
   photo is decorative (the "View Service" link lives in the card beside it), so this never
   changes what is tappable. */
@media (min-width: 981px) and (hover: hover) and (pointer: fine) {
  body.theme-growth .alternating-services .service-image {
    transform-style: preserve-3d;
    transition: transform .3s ease, box-shadow .3s ease;
  }
  body.theme-growth .alternating-services .service-row .service-image:hover {
    transform: perspective(900px) rotateX(2deg) rotateY(-2deg) translateY(-4px);
    box-shadow: 0 26px 46px rgba(0, 49, 26, .24);
  }
  body.theme-growth .alternating-services .service-row--reverse .service-image:hover {
    transform: perspective(900px) rotateX(2deg) rotateY(2deg) translateY(-4px);
  }
}
@media (prefers-reduced-motion: reduce) {
  body.theme-growth .alternating-services .service-image { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   15. SERVICE AREAS ON THE HOMEPAGE — chips, not a bullet list (2026-08-14)

   Client referenced the Greenz build's homepage areas section, where each city is its own
   clickable "stamp" chip rather than a plain list — the section carries far more visual
   weight because six individual tags read as "look how much ground we cover" in a way a
   five-line bulleted list does not.

   Per D39, the METHOD transfers, the PIXELS do not: Greenz's device is a dashed-border
   rubber-stamp tilted a degree or two (their "Job-Site Journal" language). Ours reuses what
   is already established on THIS site — the leaf cut from the client's own logo as the chip's
   icon, and the crimson/white pairing already used for every other interactive chip on the
   build (nav, badges, map header).

   Scoped to `.areas-section` only, which exists ONLY on the homepage — the shared
   `.city-list` class is used in sidebars on about/contact/city pages too, and those stay the
   plain compact list they already are (a sidebar widget earns less visual weight than a
   homepage section, on purpose). No HTML changed — same <ul><li><a> markup, restyled.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

body.theme-growth .areas-section .city-list {
  display: flex;
  flex-wrap: wrap;
  gap: .65rem;
  border-top: 0;
  padding-top: 0;
}
body.theme-growth .areas-section .city-list li {
  display: contents;   /* the <a> becomes the visual chip, not the <li> */
}
body.theme-growth .areas-section .city-list li::before { content: none; }  /* drop the bullet dot */

body.theme-growth .areas-section .city-list a {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  padding: .6rem 1.05rem;
  border: 1.5px solid rgba(255, 255, 255, .38);
  border-radius: var(--radius-pill);
  font-weight: 800;
  font-size: .96rem;
  color: #ffffff;
  transition: background .2s ease, border-color .2s ease, transform .2s ease;
}
body.theme-growth .areas-section .city-list a::before {
  content: "";
  width: 13px; height: 20px;
  flex: none;
  background: var(--cls-crimson);
  -webkit-mask: url('/images/leaf.png') no-repeat center / contain;
          mask: url('/images/leaf.png') no-repeat center / contain;
}
body.theme-growth .areas-section .city-list a:hover,
body.theme-growth .areas-section .city-list a:focus-visible {
  background: var(--cls-crimson);
  border-color: var(--cls-crimson);
}
body.theme-growth .areas-section .city-list a:hover::before,
body.theme-growth .areas-section .city-list a:focus-visible::before {
  background: #ffffff;
}

/* "View All Service Areas" reads as the standout chip — solid-filled from the start, since
   it is the section's actual call to action, not just another city. */
body.theme-growth .areas-section .city-list-more a {
  background: var(--cls-crimson);
  border-color: var(--cls-crimson);
  color: #ffffff;
}
body.theme-growth .areas-section .city-list-more a::before { display: none; }
body.theme-growth .areas-section .city-list-more a .link-arrow { margin-left: .15rem; }
body.theme-growth .areas-section .city-list-more a:hover,
body.theme-growth .areas-section .city-list-more a:focus-visible {
  background: var(--cls-crimson-deep);
  border-color: var(--cls-crimson-deep);
}

@media (prefers-reduced-motion: reduce) {
  body.theme-growth .areas-section .city-list a { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   16. THE FULL COMMIT — hero, services, final CTA, footer as one bound plan document
   (2026-08-14)

   Everything before this section layered strong, individually-considered components onto
   the master template's existing section order. This section is the difference: the whole
   homepage — and, via the shared footer partial, every OTHER page too — now commits to one
   idea from open to close, the way a real drawn plan set does: a cover sheet (hero) with a
   corner stamp, a legend before the detail (services), and a closing seal that repeats on
   every sheet in the set (the final-cta corner ticks and the footer's title-block labels
   appear on all 23 pages, not just home).

   Nothing here is Greenz's device. Greenz built a cream-paper "Job-Site Journal" — taped
   snapshots, a scrolling ticker, a stencil-numbered ledger, a banana-yellow CTA. This is a
   drafted plan set — registration ticks, a legend, a title-block stamp, one crimson rule —
   because that is what THIS owner's degree and his own words ("Designs & Renderings") are
   actually about. Same ambition, deliberately different execution.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* 16.1 — (REMOVED 2026-08-14) the hero's corner stamp — "Est. 1997 · Kingston, GA" in the
   bottom-right of the homepage hero. Client feedback: remove it. The facts it carried are
   still visible elsewhere (hero copy, the title block further down the page), so nothing is
   lost. That bottom-right hero corner is open again — see AGENTS.md D39-3 for what was
   considered as a replacement and why nothing has been built there yet. Do not reintroduce
   this exact stamp without a reason; if the corner gets used again, it should be a new idea,
   not this one restored. */

/* 16.2 — the services legend: a plan's key, read before the detail rows. Real in-page jump
   links (not decorative), reusing the crimson-chip language already established for the
   homepage service areas — but as an OUTLINE treatment here, since this sits on a light
   section rather than the dark areas-card. */
body.theme-growth .cls-service-legend {
  display: flex;
  flex-wrap: wrap;
  gap: .55rem;
  margin: 1.6rem 0 2.6rem;
}
body.theme-growth .cls-service-legend a {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .95rem;
  border: 1.5px solid var(--color-line);
  border-radius: var(--radius-pill);
  font-size: .88rem;
  font-weight: 700;
  color: var(--color-green-700);
  transition: background .2s ease, border-color .2s ease, color .2s ease;
}
body.theme-growth .cls-legend-leaf {
  width: 10px; height: 15px;
  flex: none;
  background: var(--cls-crimson);
  -webkit-mask: url('/images/leaf.png') no-repeat center / contain;
          mask: url('/images/leaf.png') no-repeat center / contain;
}
body.theme-growth .cls-service-legend a:hover,
body.theme-growth .cls-service-legend a:focus-visible {
  background: var(--cls-crimson);
  border-color: var(--cls-crimson);
  color: #ffffff;
}
body.theme-growth .cls-service-legend a:hover .cls-legend-leaf,
body.theme-growth .cls-service-legend a:focus-visible .cls-legend-leaf { background: #ffffff; }
@media (prefers-reduced-motion: reduce) { body.theme-growth .cls-service-legend a { transition: none; } }

/* 16.3 — final-CTA registration ticks removed sitewide at Honey's direction, 2026-08-21.
   Do not add white corner marks to image frames, CTA bands, heroes, or other photo surfaces. */

/* 16.4 — the footer as the set's back cover, SITE-WIDE (it is a shared partial). Column
   headers become drafting labels rather than plain white h2s; a small leaf mark closes the
   attribution line the way a drafter initials the corner of a finished sheet. */
body.theme-growth .site-footer h2 {
  font-family: var(--font-body);
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #ffffff;   /* NOT a lightened crimson — the client already flagged an invented
     pink (#FF5C9B) once this build. #A30046 measures only 2.27:1 on the footer's dark
     background (fails AA), and lightening it again to pass would repeat the exact mistake:
     inventing an off-brand third colour. White is the resolved pattern from that fix —
     decorative/label marks on dark backgrounds go white, matching the surrounding text. */
}
body.theme-growth .cls-leaf-mark {
  display: inline-block;
  width: 10px; height: 15px;
  margin-right: .5rem;
  vertical-align: -2px;
  background: #ffffff;
  -webkit-mask: url('/images/leaf.png') no-repeat center / contain;
          mask: url('/images/leaf.png') no-repeat center / contain;
}

/* ── Contact form subtitle width fix (client feedback 2026-08-14) ───────────────────────
   `.section-subtitle` caps at 670px sitewide, which is right in a two-column context but
   left a wide blank strip on the right of THIS card — .contact-form-card runs the full
   width of the single-column .contact-main, well over 800px, so the paragraph and the
   crimson rule beneath it were hugging the left ~70% of the card while the right side sat
   empty. That imbalance, not the wording, was the real cause. Widened here only. */
body.theme-growth .contact-form-card .section-subtitle { max-width: 100%; }

/* ── Section-to-section rhythm fix (client feedback 2026-08-14) ─────────────────────────
   "Why Choose Us" and the Reviews section sat back to back with almost identical
   backgrounds — .about-section falls back to the plain white body background, and
   .testimonials-section used --color-bg (#f6f8f5), just 6.7% darker in luminance. At a
   glance the two folds read as one continuous white block with no seam.
   Given the Reviews section its own soft green wash — the same --color-green-100 tint
   already used for chip backgrounds sitewide, not a new colour — so scrolling past it
   registers as a distinct beat before landing on the crimson Owner's Promise band. */
body.theme-growth .testimonials-section { background: var(--color-green-100); }

/* 17 — Gallery category cards (D43 categorized gallery, 2026-08-18). /gallery/ hub links
   out to one page per service category (Landscape Design & Install / Hardscaping / Outdoor
   Lighting); each card is the full link (bigger target, no nested interactive elements),
   photo cropped to a portrait card, dark gradient at the bottom, white title, and a crimson
   "View Our Work" link — crimson already owns markers/links sitewide (see section 14), so
   the link reuses --color-accent rather than inventing a new tint. Background photo comes
   from the page's own <style> block (.cls-gallery-cat--<slug>); this component only owns
   the card shape, overlay, and text placement, same split as the existing service cards. */
body.theme-growth .cls-gallery-cats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2.4vw, 1.75rem);
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
}
/* 4 categories (Landscape Maintenance added 2026-08-20) want 2x2 on desktop, not a stranded
   4th card alone on a second row — same fix already applied to .service-jump-grid. Scoped to
   min-width:901px: below that, the single-column tablet/mobile rule further down (raised from
   560px to 900px the same day, client feedback: "not responsive... make it 1 card per line")
   must win outright — this rule originally had no width limit at all, so its higher selector
   specificity (:has() + a class) was beating that mobile rule even on small phones. Cards keep
   their aspect-ratio fixed regardless of column count, so going from 3 columns to 2 also made
   each card noticeably TALLER at the original 4:5 portrait ratio (client feedback: "too big");
   shortened to 4:3 for this 2-up case only. */
@media (min-width: 901px) {
  body.theme-growth .cls-gallery-cats:has(> a:nth-child(4):last-child) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  body.theme-growth .cls-gallery-cats:has(> a:nth-child(4):last-child) .cls-gallery-card {
    aspect-ratio: 4 / 3;
  }
}
body.theme-growth .cls-gallery-card {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: 22px;
  aspect-ratio: 4 / 5;
  background-color: var(--color-green-800);
  background-size: cover;
  background-position: center;
  box-shadow: var(--shadow-card);
  transition: transform .2s ease, box-shadow .2s ease;
}
body.theme-growth .cls-gallery-card:hover,
body.theme-growth .cls-gallery-card:focus-visible {
  transform: translateY(-4px);
  box-shadow: 0 24px 52px rgba(0, 40, 20, .28);
}
body.theme-growth .cls-gallery-card:focus-visible { outline: 3px solid var(--cls-crimson); outline-offset: 4px; }
body.theme-growth .cls-gallery-card::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 62%;
  background: linear-gradient(0deg, rgba(0, 40, 20, .92) 0%, rgba(0, 40, 20, .5) 55%, transparent 100%);
  pointer-events: none;
}
body.theme-growth .cls-gallery-card__content {
  position: absolute;
  inset: auto 1.35rem 1.25rem 1.35rem;
  z-index: 1;
}
body.theme-growth .cls-gallery-card__title {
  display: block;
  font-family: var(--font-heading);
  font-weight: 800;
  font-size: clamp(1.2rem, 2.2vw, 1.5rem);
  color: #fff;
  line-height: 1.15;
}
body.theme-growth .cls-gallery-card__link {
  display: inline-block;
  margin-top: .4rem;
  font-size: .9rem;
  font-weight: 700;
  color: #fff;
  border-bottom: 2px solid var(--cls-crimson);
  padding-bottom: 1px;
}
body.theme-growth .cls-gallery-card:hover .cls-gallery-card__link,
body.theme-growth .cls-gallery-card:focus-visible .cls-gallery-card__link { border-bottom-width: 3px; }

/* Tablet/mobile (client feedback 2026-08-20: "not responsive... make it 1 card per line"),
   raised from a 560px single-column cutoff with an 860px 2-up tier above it — that tier put
   an 856px-wide tablet test into 2 columns, still cramped. One column all the way up through
   900px now; the min-width:901px rule above is what re-introduces 2-up for the 4-card case
   on desktop. */
@media (max-width: 900px) {
  body.theme-growth .cls-gallery-cats { grid-template-columns: minmax(0, 1fr); }
  body.theme-growth .cls-gallery-card { aspect-ratio: 16 / 11; }
}

/* ── "What We Stand For" on /about/ (2026-08-18) ───────────────────────────────────────
   .careers-card-grid is a 3-up. There are four values here, and this grid sits in the
   narrower main column beside the estimate sidebar — so 3-up left one orphan on a second
   row and squeezed each card hard enough that "Experience that solves problems" wrapped
   across four lines. Four items want 2x2. Scoped to this block so /careers/ keeps its 3-up. */
body.theme-growth .about-main .careers-card-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.1rem;
  margin-top: 1.4rem;
}
body.theme-growth .about-main > .about-story-section {
  padding-top: clamp(.65rem, 1.5vw, 1rem);
}
body.theme-growth .about-main > .section-heading { margin-bottom: .85rem; }
body.theme-growth .about-main > .about-content-image {
  margin-block: clamp(1.4rem, 2.5vw, 2rem);
}

body.theme-growth .cls-about-values > h2 { margin-bottom: .2rem; }
body.theme-growth .cls-about-values .careers-info-card { height: 100%; }
body.theme-growth .careers-main .careers-card-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
body.theme-growth .careers-interest-note {
  margin-top: .35rem;
  padding: 1rem 1.15rem;
  border-left: 4px solid var(--cls-crimson);
  border-radius: 0 16px 16px 0;
  background: var(--color-bg);
  line-height: 1.55;
}
@media (max-width: 700px) {
  body.theme-growth .about-main .careers-card-grid { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  body.theme-growth .careers-main .careers-card-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════
   18. EVEN ROWS — no stranded grid items (client feedback 2026-08-19)

   Audited every CSS grid on all 27 pages at 1440 / 1024 / 390 and flagged any whose last
   row was only partly filled. Eleven cases across three components. A partly-filled row is
   not neutral: on /gallery/landscape-design-install/ it left ~939px of empty white beside a
   single photo.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* 18.1 — Title block: 2x2 rather than a stranded 4th cell once it drops below 4 across.
   The cell dividers are right-borders, so at 2 columns the 2nd and 4th cells must lose
   theirs or a rule hangs off the middle of the block. */
@media (max-width: 1100px) {
  body.theme-growth .cls-titleblock { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body.theme-growth .cls-titleblock div:nth-child(2n) { border-right: 0; }
}
@media (max-width: 430px) {
  body.theme-growth .cls-titleblock { grid-template-columns: minmax(0, 1fr); }
  body.theme-growth .cls-titleblock div { border-right: 0; }
}

/* 18.2 — Service jump nav: a fixed 2-up stranded the 5th link on /services/ with ~500px
   empty beside it, and the 3-link version on /services/irrigation/ stranded its third.
   The link count differs per page, so no fixed column count is right. Flex lets the last
   row's links grow to fill the width instead. */
body.theme-growth .service-jump-grid {
  /* Aligned columns, not a ragged wrap (team direction 2026-08-19: "01 02 03 vertically
     aligned, then 04 05 06"). Content-sized chips read tidily on their own but the numbers
     land in different places on every row, which is what made the sequence hard to scan.
     Equal columns line the numbers up down the page.

     This deliberately accepts a partly-filled last row on the counts that do not divide by
     three (4, 5, 8) — alignment was chosen over a full final row. What must NOT come back is
     a lone chip STRETCHED across the whole row; grid keeps every cell one column wide, so
     the trailing chip stays chip-sized. */
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: .85rem;
  align-items: stretch;
}
body.theme-growth .service-jump-grid a {
  min-height: 56px;
}
/* Four services go 2x2, not 3+1 (team direction 2026-08-19). Written as a count test rather
   than pinned to the one page that currently has four, so it keeps working if Ground Control
   adds or removes a service: `:has(> a:nth-child(4):last-child)` matches only when the 4th
   link is also the last. Browsers without :has() fall back to the 3-column rule above, which
   is the previous behaviour rather than a broken one. */
body.theme-growth .service-jump-grid:has(> a:nth-child(4):last-child) {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

@media (max-width: 1100px) {
  body.theme-growth .service-jump-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  body.theme-growth .service-jump-grid { grid-template-columns: minmax(0, 1fr); }
}

/* 18.3 — Photo galleries: the item count is data-driven (currently 4, 5 and 8 across the
   three category pages) so a fixed 3-up will strand photos at some count no matter what we
   pick. Flex + grow gives a justified row: the last row's photos widen to fill. Swapping
   aspect-ratio for a fixed row height keeps every photo in a row the same height, which is
   what stops a "justified" gallery looking ragged. object-fit on the img already handles
   the crop. */
body.theme-growth .gallery-grid {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(.9rem, 2vw, 1.25rem);
}
body.theme-growth .gallery-grid {
  /* Centre the rows. Full rows fill and are unaffected; it only changes where a partial last
     row sits, which then reads as deliberate rather than left-stranded. */
  justify-content: center;
}
body.theme-growth .gallery-grid .gallery-item {
  flex: 1 1 300px;
  /* Cap the growth. Without this a lone photo on the last row grew to the FULL row width —
     measured 992px against 317px siblings at 1024px on the design-and-install gallery. Same
     fault as the stretched jump chip. Half a row is the widest a single photo should ever be. */
  max-width: calc(50% - .65rem);
  aspect-ratio: auto;
  min-height: 0;
  height: clamp(240px, 26vw, 330px);
}
/* Same 900px cutoff as .cls-gallery-cats above (client feedback 2026-08-20: "same with the
   services gallery page" — the per-category photo grids had the identical 560px-only
   single-column cutoff, so an 856px tablet test still saw 2 photos per row). */
@media (max-width: 900px) {
  body.theme-growth .gallery-grid .gallery-item { flex-basis: 100%; max-width: 100%; height: 260px; }
}
/* ── Gallery lightbox: show the whole photo, not a cropped cover (2026-08-19) ───────────
   The shared .gallery-lightbox__image (components.css) uses background-size: cover, which
   fills the fixed lightbox box and crops whatever doesn't fit — most of our client's real
   project photos are portrait phone shots, so cover was cutting off the tops/bottoms of
   patios and walls in the enlarged view. Overridden here (not in components.css, which is
   shared across every Growth client) to contain instead: the full photo now fits inside the
   box, letterboxed on the box's own dark background rather than cropped.
   no-repeat is required alongside it: neither this rule nor the base component set it, so
   the browser's default background-repeat: repeat tiled the photo across the letterboxed
   space contain now leaves uncovered (client feedback 2026-08-20).

   Second pass, same day: contain fit the whole photo but the element still forced the full
   960px grid track width, so portrait photos (most of this client's real project photos)
   left big flat-color bars down both sides — "the container doesn't look visually good."
   Real fix: the lightbox image is now an actual <img> (assets/js/gallery-category.js sets
   .src/.alt instead of a background-image), sized here to its own intrinsic aspect ratio
   via object-fit rather than forced to fill a fixed box. A portrait photo now renders as a
   narrower, taller frame instead of a wide box with empty color on either side. */
body.theme-growth .gallery-lightbox__image {
  width: auto;
  height: auto;
  min-width: 0;
  min-height: 0;
  max-width: 100%;
  max-height: min(68vh, 620px);
  object-fit: contain;
  justify-self: center;
}
@media (max-width: 560px) {
  body.theme-growth .gallery-lightbox__image { aspect-ratio: auto; max-height: 68vh; }
}

/* ── 18.4 Buttons that wrap when they should not (client feedback 2026-08-19) ───────────
   Audited every .btn on all 27 pages at 1440 / 1024 / 390 for labels breaking onto a second
   line. Three real causes (the "Learn More about X" hits were false positives — that trailing
   text is sr-only, so those buttons are single-line as rendered).

   a) .split-heading is `display:flex; justify-content:space-between`, so its button is a flex
      item and gets SQUEEZED by the heading beside it — "View Our Services" broke onto two
      lines at 1440 with the row nowhere near full. It should keep its natural width. */
body.theme-growth .split-heading > .btn {
  flex: 0 0 auto;
  white-space: nowrap;
}

/* b) The footer CTA column is the narrowest of the four at ~1024px, so "Request An Estimate"
      wrapped there on all 27 pages while the identical button is single-line everywhere else.
      Give that column a little more of the row before it squeezes the button. */
@media (min-width: 981px) and (max-width: 1180px) {
  body.theme-growth .footer-grid { grid-template-columns: 1fr 1fr 1fr 1.55fr; }
}
body.theme-growth .cta-panel .button-row .btn { margin-top: 0; padding-inline: .9rem; }
body.theme-growth .footer-cta .button-row { gap: .65rem; margin-top: 1rem; }
body.theme-growth .footer-cta .button-row .btn { margin-top: 0; white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════════════════
   19. TEXT DISTRIBUTION — no stranded words, no lopsided measure (client feedback 2026-08-19)

   Measured every heading and paragraph on all 27 pages at 1440 and 1024. Two faults, both
   sitewide rather than section-specific:

   a) 28 headings and 85 paragraphs ended on a stranded word. Worst case: the outdoor-lighting
      H3 put "Add-On" alone on a second line at 5% of the width of the line above it, which is
      what opens a band of dead space under a heading.
   b) Body text was using as little as 54-55% of the column it sat in — .section-subtitle caps
      at 670px but sits in a 1193px column on the homepage, so the copy hugged the left and
      left a void on the right.

   Fixed with line-breaking rather than by shrinking type, so nothing gets smaller:
   `balance` evens the line lengths of short blocks (headings), `pretty` only protects the
   last line (paragraphs) and is cheaper on long text. Both degrade to normal wrapping in
   browsers that lack them — nothing breaks, it just looks like it did before.
   ═══════════════════════════════════════════════════════════════════════════════════════ */
body.theme-growth h1,
body.theme-growth h2,
body.theme-growth h3,
body.theme-growth .hero-title,
body.theme-growth .cls-promise-quote {
  text-wrap: balance;
}
body.theme-growth p,
body.theme-growth li,
body.theme-growth dd {
  text-wrap: pretty;
}

/* `pretty` only guards the final line and left 79 short blocks still ending on a stub. The
   remainder were 3-4 line paragraphs in cards, heroes and intros — short enough for the
   browser to balance properly. Chromium ignores `balance` past its own line-count limit, so
   long body copy is unaffected by this and keeps `pretty` above.

   Removed later: .hub-service-body p (its container is ~860px on a service page, wide
   enough that balancing stranded the text at 54%) and the spanning "Nearby Area?" card,
   which is full-row width for the same reason. Balance is only right where the container
   is genuinely narrow. */
/* NOT .hero-copy or .section-subtitle: balancing those pulled them in to 40-43% of their
   column, which is the lopsided-left problem this section exists to fix. Wide intro copy
   keeps `pretty` above and fills its measure; only blocks in already-narrow containers get
   balanced, where a shorter line costs nothing. */
body.theme-growth .service-card p,
body.theme-growth .careers-info-card p,
body.theme-growth .contact-step-card p,
body.theme-growth .area-link-card:not(.area-link-card--fallback) p,
body.theme-growth .city-core-service p,
body.theme-growth .quote-card p {
  text-wrap: balance;
}

/* Wider measure where the column is wide. 670px in a 1193px column reads as an accident;
   ~74ch is still a comfortable line length but fills the space it is given. Capped with
   min() so narrow/two-column contexts (sidebars, cards) are untouched. */
body.theme-growth .section-subtitle { max-width: min(74ch, 100%); }
body.theme-growth .hero-copy { max-width: min(68ch, 100%); }
body.theme-growth .home-hero-copy--mobile { display: none; }

/* Legal pages keep section headings compact so policy content remains easy to scan. */
body.theme-growth .legal-content h2 {
  font-size: clamp(1.5rem, 2.2vw, 2rem);
  line-height: 1.16;
}
/* Sidebars and cards keep the tight measure — they are already narrow. */
body.theme-growth .services-sidebar .section-subtitle,
body.theme-growth .about-sidebar .section-subtitle,
body.theme-growth .careers-sidebar .section-subtitle { max-width: 100%; }

body.theme-growth .primary-nav .dropdown a[aria-current="page"] {
  color: var(--color-green-800);
  background: var(--color-green-100);
  font-weight: 950;
}
@media (min-width: 981px) {
  body.theme-growth .primary-nav > ul > li.is-current-section > a::after { transform: scaleX(1); }
}

/* ── Sandi mobile conversion pass (2026-08-19) ───────────────────────────────
   Keep the first screen focused on the company and next step. The embedded
   forms themselves are unchanged; only their mobile position is improved. */
@media (max-width: 980px) {
  body.theme-growth .hero-grid { padding-block: 2.6rem; }
  body.theme-growth .hero-title-main { font-size: clamp(2.15rem, 10vw, 3.1rem); line-height: .98; }
  body.theme-growth .hero-title-location {
    margin-top: .6rem;
    font-size: clamp(1rem, 4.4vw, 1.25rem);
    line-height: 1.25;
    font-style: normal;
    letter-spacing: -.015em;
  }
  body.theme-growth .hero-copy { margin-top: .9rem; font-size: 1rem; line-height: 1.48; }
  body.theme-growth .hero .button-row { margin-top: 1.25rem; }
  body.theme-growth .cls-service-legend,
  body.theme-growth .services-hub:not(.service-page) .service-jump-grid { display: none; }

  body.theme-growth .services-layout,
  body.theme-growth .city-service-area-layout,
  body.theme-growth .about-layout {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }
  body.theme-growth .services-layout > .services-sidebar,
  body.theme-growth .city-service-area-layout > .city-service-sidebar,
  body.theme-growth .about-layout > .about-sidebar { display: contents; }
  /* Honey's mobile sidebar contract (2026-08-19): when the sidebar is flattened
     into the page flow, every promoted card fills the same content column.
     Without this, align-items:start shrink-wraps each card to its text and creates
     several visibly different card widths across otherwise identical templates. */
  body.theme-growth .services-layout > .services-sidebar > *,
  body.theme-growth .city-service-area-layout > .city-service-sidebar > *,
  body.theme-growth .about-layout > .about-sidebar > * {
    width: 100%;
    min-width: 0;
    max-width: none;
    align-self: stretch;
    box-sizing: border-box;
  }
  body.theme-growth .contact-phone-card { border-radius: 22px; }
  body.theme-growth .services-layout > .services-sidebar > .quote-card,
  body.theme-growth .city-service-area-layout > .city-service-sidebar > .quote-card,
  body.theme-growth .about-layout > .about-sidebar > .quote-card { order: 1; }
  body.theme-growth .services-layout > .services-main,
  body.theme-growth .city-service-area-layout > .city-service-main,
  body.theme-growth .about-layout > .about-main { order: 2; }
  body.theme-growth .services-layout > .services-sidebar > :not(.quote-card),
  body.theme-growth .city-service-area-layout > .city-service-sidebar > :not(.quote-card),
  body.theme-growth .about-layout > .about-sidebar > :not(.quote-card) { order: 3; }
}

/* ── Sandi media room mobile pass (2026-08-19) ────────────────────────────── */
.media-room-embed { min-width: 0; overflow: hidden; }
.media-room-embed > * { max-width: 100%; min-width: 0; }
.media-room-embed .wa-intcode-signals-app,
.media-room-embed .wa-intcode-signals-app .v-application__wrap,
.media-room-embed .wa-intcode-signals-app .v-main {
  min-height: 0 !important;
  height: auto !important;
}
.media-room-empty-note { margin-bottom: 1.25rem; color: var(--color-muted); }
.media-room-embed.is-empty .wa-intcode-signals-app .v-col-md-8 { display: none !important; }
.media-room-embed.is-empty .wa-intcode-signals-app .v-col-md-4 {
  width: 100% !important;
  max-width: 100% !important;
  flex: 0 0 100% !important;
}
.service-area-fit--text-only .split-section {
  grid-template-columns: minmax(0, 900px);
  justify-content: center;
}
body.theme-growth .city-service-area-content .impact-phone-cta > p {
  max-width: 620px;
  margin: 0;
  color: rgba(255, 255, 255, .92);
  font-size: 1rem;
  line-height: 1.45;
  text-wrap: balance;
}
/* Moved below .city-service-grid (2026-08-20, client-directed) so the phone CTA reads as a
   close after the five service cards rather than a detour before them. It picked up its
   spacing for free in the old position (city-service-grid's own margin-top followed it);
   now it needs that same margin itself, matching the grid's own card gap. */
body.theme-growth .city-service-area-content .impact-phone-cta {
  margin-top: clamp(1.5rem, 3vw, 2.2rem);
}
@media (max-width: 620px) {
  body.theme-growth .home-hero-copy--desktop { display: none; }
  body.theme-growth .home-hero-copy--mobile { display: inline; }
  body.theme-growth .city-service-area-content .impact-phone-cta > a {
    width: 100%;
    max-width: 100%;
    padding-inline: .7rem;
    font-size: 1rem;
    line-height: 1;
    white-space: nowrap;
  }
}

/* City pages: full-width vertical service cards (approved reference, 2026-08-19). */
.city-service-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1.5rem, 3vw, 2.2rem);
  margin-top: 1.5rem;
}
body.theme-growth .city-service-grid .city-core-service {
  display: block;
  overflow: hidden;
  min-height: 0;
  padding: clamp(1.15rem, 3vw, 1.75rem);
  margin-top: 0;
  border: 1px solid rgba(29, 107, 63, .18);
  border-bottom: 1px solid rgba(29, 107, 63, .18);
  border-radius: 26px;
  background: #fffdf8;
  box-shadow: 0 18px 42px rgba(16, 61, 36, .10);
}
body.theme-growth .city-service-grid .hub-service-body {
  display: block;
  max-width: none;
  min-width: 0;
  padding: 0;
}
body.theme-growth .city-service-grid h2 {
  margin: 0 0 .75rem;
  font-size: clamp(1.8rem, 4vw, 2.45rem);
  line-height: 1.05;
  text-wrap: balance;
}
body.theme-growth .city-service-grid p {
  margin: 0;
  font-size: clamp(1rem, 1.4vw, 1.1rem);
  line-height: 1.5;
  text-wrap: pretty;
}
body.theme-growth .city-service-grid .hub-service-image {
  position: relative;
  width: 100%;
  height: auto;
  min-height: 0;
  margin: 1rem 0;
  aspect-ratio: 2 / 1;
  border: 6px solid #fff;
  border-radius: 9px;
  background-position: center;
  box-shadow: 0 8px 20px rgba(16, 61, 36, .14);
}
body.theme-growth .city-service-grid .city-service-detail {
  margin-top: .85rem;
}
body.theme-growth .city-service-grid .city-service-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .7rem;
  margin-top: 1.1rem;
}
body.theme-growth .city-service-grid .btn {
  min-height: 44px;
  padding: .65rem 1rem;
}
.service-area-map-section + .service-area-directory {
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
}
body.theme-growth .service-area-directory .coverage-directory-panel { margin-top: 0; }
body.theme-growth .service-area-directory .coverage-panel-heading h2 {
  color: #ffffff;
  font-size: clamp(1.75rem, 3vw, 2.65rem);
}
body.theme-growth .service-area-directory .coverage-pill-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(.75rem, 1.6vw, 1rem);
}
body.theme-growth .service-area-directory .coverage-pill-grid a {
  justify-content: center;
  text-align: center;
}
@media (max-width: 620px) {
  body.theme-growth .service-area-directory .coverage-pill-grid { gap: .75rem; }
  body.theme-growth .service-area-directory .coverage-pill-grid a {
    min-height: 52px;
    padding: .65rem .55rem;
    font-size: clamp(.82rem, 3.8vw, .95rem);
  }
}
.city-service-area-content .hub-service { padding-block: .8rem 1.6rem; }
.city-service-area-content .hub-service-body { max-width: 100%; }
@media (max-width: 760px) {
  body.theme-growth .city-service-grid .city-core-service {
    padding: 1rem;
    border-radius: 22px;
  }
  body.theme-growth .city-service-grid h2 {
    font-size: clamp(1.55rem, 8vw, 2rem);
  }
  body.theme-growth .city-service-grid .hub-service-image {
    margin-block: .9rem;
    border-width: 4px;
  }
  body.theme-growth .city-service-grid .city-service-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  body.theme-growth .city-service-grid .btn {
    width: 100%;
    padding-inline: .7rem;
    font-size: .9rem;
  }
  .media-room-embed .wa-intcode-signals-app .v-container { width: 100% !important; padding-inline: 0 !important; }
  .media-room-embed .wa-intcode-signals-app .v-row { display: grid !important; grid-template-columns: minmax(0, 1fr) !important; margin: 0 !important; }
  .media-room-embed .wa-intcode-signals-app .v-col-12,
  .media-room-embed .wa-intcode-signals-app .v-col-sm-12,
  .media-room-embed .wa-intcode-signals-app .v-col-md-4,
  .media-room-embed .wa-intcode-signals-app .v-col-md-8 {
    width: 100% !important;
    max-width: 100% !important;
    min-width: 0 !important;
    flex: 0 0 100% !important;
    padding-inline: 0 !important;
  }
  .media-room-embed .wa-intcode-signals-app .v-card-title,
  .media-room-embed .wa-intcode-signals-app .v-card-text { white-space: normal !important; overflow-wrap: anywhere; }
  .media-room-embed.is-empty .wa-intcode-signals-app .v-col-md-8 { display: none !important; }
}

/* ── 19.1 "Nearby Area?" fallback card (service-areas-hub.md item 5) ────────────────────
   The spec closes the city grid with a fallback card routing to contact. It is not one of
   the numbered cities, so it does not take a number in the crimson chip sequence — a "+"
   instead — and it is outlined rather than solid so it reads as the catch-all at the end of
   the set rather than a seventh city. */
body.theme-growth .area-link-card--fallback {
  /* Spans the row. Six cities + this card is seven items in a 3-up, which strands the last
     one (the audit flagged ~939px empty when it was first added). It is the catch-all at the
     end of the set rather than a seventh city, so closing the grid full-width is both the
     honest hierarchy and the even layout. */
  grid-column: 1 / -1;
  background: transparent;
  border: 2px dashed var(--color-line);
  box-shadow: none;
}
body.theme-growth .area-link-card--fallback span[aria-hidden] {
  background: var(--color-green-700);
}
body.theme-growth .area-link-card--fallback:hover {
  border-color: var(--color-green-700);
  border-style: solid;
}

/* Complete Lawn Service Homepage supplied-content system (2026-08-20) */
body.theme-growth .cls-services-catalog-heading {
  display: grid;
  grid-template-columns: minmax(0, 820px) max-content;
  grid-template-areas:
    "eyebrow button"
    "title button";
  align-items: end;
  justify-content: space-between;
  column-gap: clamp(2rem, 7vw, 7rem);
  width: 100%;
  max-width: none;
  margin: clamp(2.5rem, 6vw, 4.5rem) 0 1.4rem;
}
body.theme-growth .cls-services-catalog-heading .eyebrow { grid-area: eyebrow; }
body.theme-growth .cls-services-catalog-heading h2 { grid-area: title; margin-bottom: 0; }
body.theme-growth .cls-services-catalog-heading .btn {
  grid-area: button;
  justify-self: end;
  align-self: end;
}
@media (max-width: 700px) {
  body.theme-growth .cls-services-catalog-heading {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "eyebrow" "title" "button";
    row-gap: 0;
  }
  body.theme-growth .cls-services-catalog-heading .btn {
    justify-self: stretch;
    margin-top: 1rem;
  }
}

/* Exactly three honest slots until real articles are published. */
body.theme-growth .cls-home-blog {
  background: linear-gradient(180deg, #f7faf6 0%, #eef5f0 100%);
}
body.theme-growth .cls-home-blog .section-heading {
  align-items: end;
  margin-bottom: clamp(1.8rem, 4vw, 3rem);
}
body.theme-growth .cls-home-blog .section-heading > div { max-width: 800px; }
body.theme-growth .cls-home-blog__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.35rem);
}
body.theme-growth .cls-home-blog__card {
  min-width: 0;
  overflow: hidden;
  border: 1px solid rgba(0, 112, 60, .14);
  border-radius: 24px;
  background: #fff;
  box-shadow: 0 18px 42px rgba(0, 63, 42, .09);
}
body.theme-growth .cls-home-blog__media {
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background: var(--color-green-800);
}
body.theme-growth .cls-home-blog__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
body.theme-growth .cls-home-blog__body { padding: clamp(1.25rem, 2.5vw, 1.75rem); }
body.theme-growth .cls-home-blog__topic {
  margin: 0 0 .65rem;
  color: var(--color-green-700);
  font-size: .76rem;
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
}
body.theme-growth .cls-home-blog__card h3 {
  margin: 0 0 .75rem;
  font-size: clamp(1.35rem, 2.2vw, 1.7rem);
  line-height: 1.05;
}
body.theme-growth .cls-home-blog__card .cls-home-blog__body > p:last-child { margin: 0; }
body.theme-growth .cls-decision-heading { margin-top: clamp(3rem, 7vw, 5.5rem); }
body.theme-growth .cls-decision-heading .section-heading { max-width: 860px; margin-inline: auto; }
/* .section-subtitle's own max-width (min(74ch,100%)) is narrower than this 860px heading
   box, and the paragraph had no auto margins — so the block sat flush left even though its
   own text-align:center (inherited from .centered) centered the lines within that
   left-anchored box. Centering the block itself fixes the visual left-bias. */
body.theme-growth .cls-decision-heading .section-subtitle { margin-inline: auto; }
body.theme-growth .cls-decision-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.15rem;
  margin-top: 2rem;
}
body.theme-growth .cls-decision-card {
  min-width: 0;
  padding: clamp(1.25rem, 2.5vw, 1.75rem);
  border: 1px solid rgba(0, 112, 60, .14);
  border-top: 5px solid var(--cls-crimson);
  border-radius: 0 0 22px 22px;
  background: #fff;
  box-shadow: 0 16px 36px rgba(0, 63, 42, .09);
}
body.theme-growth .cls-decision-card > span {
  display: inline-grid;
  width: auto;
  min-width: 52px;
  height: 42px;
  padding-inline: .8rem;
  margin-bottom: 1rem;
  place-items: center;
  border-radius: 999px;
  color: #fff;
  background: var(--cls-crimson);
  font-size: .8rem;
  font-weight: 950;
  letter-spacing: .08em;
  text-transform: uppercase;
}
body.theme-growth .cls-decision-card h3 {
  margin-bottom: .7rem;
  font-size: clamp(1.25rem, 2.2vw, 1.6rem);
  line-height: 1.1;
}
body.theme-growth .cls-decision-card p { margin: 0; }

@media (max-width: 900px) {

  body.theme-growth .cls-home-blog__grid { grid-template-columns: minmax(0, 1fr); }
  body.theme-growth .cls-home-blog__card {
    display: grid;
    grid-template-columns: 190px minmax(0, 1fr);
  }
  body.theme-growth .cls-home-blog__media { aspect-ratio: auto; }
  body.theme-growth .cls-decision-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  body.theme-growth .cls-home-blog__card { grid-template-columns: minmax(0, 1fr); }
  body.theme-growth .cls-home-blog__media { aspect-ratio: 16 / 9; }
}

/* Blog index (2026-08-20, client feedback):
   1. .breadcrumb-nav's near-white fill (components.css) reads as its own floating card on
      .blog-index-section, which is already plain white — dropped to transparent so it just
      shows the section's own background instead of a redundant near-match panel.
   2. .service-jump-grid only carries margin-bottom (components.css) — on every other page it
      follows a .section-heading, whose own margin-bottom supplies the gap above it. Blog
      instead has two bare <p> tags in between with no such spacing, so the grid needs its own
      margin-top here specifically. */
body.theme-growth .blog-index-section .breadcrumb-nav { background: transparent; }
body.theme-growth .blog-index-section .service-jump-grid { margin-top: clamp(1.5rem, 3vw, 2.2rem); }

/* Gallery category pages: the "Explore <Service>" link now sits after the photo grid
   (client feedback 2026-08-20) rather than between the heading and the grid, where it read
   as floating, left-aligned text ahead of the photos. Centered to match the centered
   section-heading above it. */
body.theme-growth .gallery-service-link {
  margin: clamp(1.5rem, 3vw, 2.2rem) 0 0;
  text-align: center;
}

/* Sitewide heading scale (2026-08-20, Honey): keep long homeowner-facing phrases readable
   without allowing section headings to dominate the copy or break into oversized fragments. */
body.theme-growth h1 { font-size: clamp(2.35rem, 3.8vw, 4.05rem); }
body.theme-growth h2 { font-size: clamp(1.85rem, 3.25vw, 3.25rem); }
body.theme-growth h3 { font-size: clamp(1.25rem, 1.9vw, 1.75rem); }

/* Component headings are intentionally compact. Keep this after the sitewide heading scale so
   cards and sidebars do not inherit section-title sizing. */
body.theme-growth .quote-card h2,
body.theme-growth .sidebar-callout h2,
body.theme-growth .career-form-card h2 {
  font-size: 1.35rem;
  line-height: 1.12;
}
body.theme-growth .city-service-sidebar .quote-card h2,
body.theme-growth .about-sidebar .quote-card h2 { font-size: 1.25rem; }
body.theme-growth .contact-form-card h2 {
  font-size: clamp(1.5rem, 2.2vw, 2.1rem);
  line-height: 1.1;
}

/* Blog balance and contrast (Honey, 2026-08-21). The index intro stacks as one thought,
   article images keep their native proportions, and compact sidebar headings/buttons stay
   readable after the sitewide heading and crimson-outline rules above. */
body.theme-growth .blog-index-section .section-heading.split-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: .7rem;
  align-items: start;
}
body.theme-growth .blog-index-section .section-heading .section-subtitle {
  max-width: 760px;
  margin: 0;
  color: #3f493f;
  line-height: 1.5;
}
body.theme-growth .blog-index-section .featured-article-card {
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
  align-items: stretch;
}
body.theme-growth .blog-index-section .featured-article-image {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
  max-height: 360px;
  object-fit: cover;
  object-position: center;
}
body.theme-growth .blog-index-section .featured-article-body {
  padding: clamp(1.45rem, 3vw, 2.25rem);
}
body.theme-growth .blog-index-section .featured-article-body h3 {
  font-size: clamp(1.55rem, 2.25vw, 2.1rem);
  line-height: 1.08;
}
body.theme-growth .blog-index-section .blog-card-grid {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
body.theme-growth .blog-card {
  display: flex;
  flex-direction: column;
  min-width: 0;
  height: 100%;
}
body.theme-growth .blog-card .article-image {
  display: block;
  width: 100%;
  height: auto;
  min-height: 0;
  aspect-ratio: 1200 / 628;
  object-fit: cover;
  object-position: center;
}
body.theme-growth .blog-card .article-body {
  flex: 1;
  height: auto;
  background: #ffffff;
  color: var(--color-ink);
}

body.theme-growth .final-cta .btn-outline-light {
  background: transparent;
  border-color: rgba(255,255,255,.72);
  color: #ffffff;
  box-shadow: none;
}
body.theme-growth .final-cta .btn-outline-light:hover,
body.theme-growth .final-cta .btn-outline-light:focus-visible,
body.theme-growth .final-cta .btn-outline-light:active {
  background: rgba(255,255,255,.14);
  border-color: #ffffff;
  color: #ffffff;
}
body.theme-growth .blog-article-cta > span { color: rgba(255,255,255,.84); }
body.theme-growth .blog-article-cta h2 {
  margin-top: .35rem;
  color: #ffffff;
  font-size: clamp(1.3rem, 1.7vw, 1.55rem);
  line-height: 1.12;
}
body.theme-growth .blog-article-cta .btn.btn-light {
  display: flex;
  width: 100%;
  margin-top: 1rem;
  color: var(--color-green-900);
  font-size: .95rem;
  line-height: 1.2;
  letter-spacing: 0;
}
body.theme-growth .blog-article-cta .btn.btn-light:hover,
body.theme-growth .blog-article-cta .btn.btn-light:focus-visible {
  color: var(--color-green-900);
}
body.theme-growth .blog-article-cta .text-link-light {
  color: #ffffff !important;
  font-size: 1.05rem;
  line-height: 1.25;
  letter-spacing: 0;
}
body.theme-growth .sidebar-service-list-card h2 {
  margin-bottom: 1rem;
  font-size: clamp(1.35rem, 1.8vw, 1.6rem);
  line-height: 1.1;
}

@media (max-width: 980px) {
  body.theme-growth .blog-index-section .featured-article-card,
  body.theme-growth .blog-index-section .blog-card-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  body.theme-growth .blog-index-section .featured-article-image {
    height: auto;
    max-height: none;
    aspect-ratio: 1200 / 628;
  }
}

/* Service Areas company map: the map leads on desktop and the explanation sits to its right.
   The source order stays text-first so the narrow-screen reading flow remains natural. */
body.theme-growth .service-area-map-section .areas-grid {
  grid-template-columns: minmax(0, 1.18fr) minmax(0, .82fr);
}
body.theme-growth .service-area-map-section .areas-card--map {
  grid-column: 1;
  grid-row: 1;
}
body.theme-growth .service-area-map-section .areas-copy {
  grid-column: 2;
  grid-row: 1;
}
@media (max-width: 980px) {
  body.theme-growth .service-area-map-section .areas-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  body.theme-growth .service-area-map-section .areas-copy {
    grid-column: 1;
    grid-row: 1;
  }
  body.theme-growth .service-area-map-section .areas-card--map {
    grid-column: 1;
    grid-row: 2;
  }
}