/* ==========================================================================
   Nulectrics — Module Styles
   Styles for all 14 ACF Flexible Content modules
   ========================================================================== */

/* First section padding is controlled by the ACF padding_top value.
   The body padding-top offset accounts for the fixed header, so no override
   is needed here — sections respect their selected padding cleanly. */

/* --------------------------------------------------------------------------
   1. Hero (V5)
   -------------------------------------------------------------------------- */

/* Inner container — NO padding by default (flush with container) */
.nu-hero__inner {
  position: relative;
}

/* Has-gallery: exact 50/50 with a single 66px gap between content and
 * gallery. (No extra padding-right on the content column — the grid gap
 * is the only separator.) */
.nu-hero--has-gallery .nu-hero__inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 66px;
  align-items: center;
}

/* The text + gallery split holds down to 900px (tablet landscape keeps the
 * two-column hero instead of a 1,400px stack); it collapses below that. */
@media (max-width: 900px) {
  .nu-hero--has-gallery .nu-hero__inner {
    grid-template-columns: 1fr;
    gap: var(--nu-gap);
  }
}

/* Box shadow ON = boxed style with padding, border, surface bg */
.nu-hero--box-shadow .nu-hero__inner {
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  transition: box-shadow var(--nu-transition);
}

/* On a gradient section the inner panel is a solid dark card, so the gradient
   reads in the section around it rather than washing behind the content. */
.nu-hero.nu-style--gradient .nu-hero__inner {
  background: var(--nu-theme-bg);
  /* It is a visible card, so the text, contact details and trust logos need
   * the same inset as the boxed hero (was 0, content sat on the card edge). */
  padding: var(--nu-gap);
}

.nu-hero--box-shadow .nu-hero__inner:hover {
  box-shadow: var(--nu-glow-hover);
}

/* Gradient left border — inner pages (green gradient) */
.nu-hero--gradient-border .nu-hero__inner::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  width: 6px;
  height: 100%;
  background: linear-gradient(180deg, var(--nu-gradient-green-end), var(--nu-gradient-green-start));
}

/* Gradient left border — homepage (green -> blue) */
.nu-hero--gradient-border-home .nu-hero__inner::before {
  background: linear-gradient(180deg, var(--nu-green), var(--nu-blue));
}

/* Content column */
.nu-hero__content {
  max-width: none;
}

.nu-hero__heading {
  margin-bottom: var(--nu-gap-sm);
  overflow-wrap: break-word;
  word-break: break-word;
  color: var(--nu-theme-heading);
}

.nu-hero__subheading {
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-regular);
  color: var(--nu-theme-muted);
  margin-bottom: var(--nu-gap);
}

.nu-hero__body {
  margin-bottom: var(--nu-gap-lg);
  color: var(--nu-theme-text);
}

/* ── Bottom row: CTAs left, trust right ─────────────────────────── */
.nu-hero__bottom-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--nu-gap);
}

.nu-hero__ctas {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 16px;
}

/* The text-link CTA keeps its underline but gets a 44px tap target via an
 * invisible hit area, so the underline does not move away from the text. */
.nu-hero__ctas .nu-cta-link,
.nu-cta-banner__ctas .nu-cta-link {
  position: relative;
}

.nu-hero__ctas .nu-cta-link::after,
.nu-cta-banner__ctas .nu-cta-link::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -11px;
  bottom: -11px;
}

/* ── Trust row: cert logos + Google badge sit adjacent, right-aligned ──
 * Lives inline with the CTAs on the bottom row (parent uses
 * justify-content: space-between → CTAs left, trust right). Removing
 * width: 100% lets it take max-content width so the parent flex layout
 * actually keeps it on the same row. */
.nu-hero__trust-row {
  display: flex;
  align-items: center;
  gap: var(--nu-gap);
  flex-wrap: wrap;
}

/* Cert logos row — fixed bounding-box height for uniform rendering */
.nu-hero__cert-logos {
  display: flex;
  align-items: center;
  gap: 20px;
  height: 50px;
}

/* Each img sized by its natural aspect ratio inside the 50px band */
.nu-hero__cert-logo {
  height: 50px;
  width: auto;
  max-width: 100%;
  object-fit: contain;
  display: block;
}

/* Cert logos stay at the standard 50px band whether the hero has a gallery
 * or not. The earlier "doubled on no-gallery" rule was dropped 2026-04-18. */

/* Separator removed — space-between layout makes it unnecessary */
.nu-hero__trust-sep {
  display: none;
}

/* ── Google review badge ─────────────────────────────────────────────
   Stars on top row.
   Below: 'XXX reviews' snapped to LEFT of stars row,
          Google G snapped to RIGHT of stars row.
   Badge width = exact width of the stars row (max-content). */
.nu-hero__google-badge {
  display: inline-flex;
  flex-direction: column;
  gap: 6px;
  width: max-content;
}

.nu-hero__stars {
  color: #f5c518;
  font-size: 1.4rem;
  letter-spacing: 4px;
  line-height: 1;
  display: block;
}

/* Bottom row matches stars width via flex space-between */
.nu-hero__google-badge-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  gap: 8px;
}

.nu-hero__review-text {
  color: var(--nu-theme-muted);
  font-size: var(--nu-fs-small);
  white-space: nowrap;
}

.nu-hero__google-g {
  flex-shrink: 0;
  width: 18px;
  height: 18px;
}

/* Review badge renders at the SAME size whether the hero has a gallery
 * or not — the earlier no-gallery 33%-shrink rule was dropped 2026-04-18
 * after visual review. */

/* ── Gallery grid (2 square top + 1 wide bottom) ────────────────── */
.nu-hero__gallery-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 12px;
}

.nu-hero__gallery-item {
  margin: 0;
  overflow: hidden;
  border-radius: 0;
}

.nu-hero__gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  aspect-ratio: 1 / 1;
  display: block;
}

.nu-hero__gallery-item--wide {
  grid-column: 1 / -1;
}

.nu-hero__gallery-item--wide img {
  aspect-ratio: 2 / 1;
}

/* ── Mobile ──────────────────────────────────────────────────────── */
@media (max-width: 767px) {
  .nu-hero--has-gallery .nu-hero__inner {
    grid-template-columns: 1fr;
  }

  /* Internal padding ONLY when the hero is a boxed card (visible
   * background tint / shadow). For non-boxed heroes the section's
   * container gutter handles spacing — extra internal padding makes
   * content read inset from where the user expects. */
  .nu-hero--box-shadow .nu-hero__inner,
  .nu-hero--gradient-border .nu-hero__inner,
  .nu-hero.nu-style--gradient .nu-hero__inner {
    padding: 24px 20px;
  }

  .nu-hero__bottom-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }

  .nu-hero__trust-row {
    gap: 12px;
  }

  .nu-hero__cert-logo {
    max-height: 24px;
  }
}

/* --------------------------------------------------------------------------
   2. Content Block (50/50 split with lightbox gallery)
   -------------------------------------------------------------------------- */

.nu-content-block__heading {
  margin-bottom: var(--nu-gap);
  color: var(--nu-theme-heading);
}

.nu-content-block__content {
  color: var(--nu-theme-text);
}

.nu-content-block__content p:last-child {
  margin-bottom: 0;
}

/* Max-width variants (text-only, no gallery) */
.nu-content-block--narrow .nu-content-block__content,
.nu-content-block--narrow .nu-content-block__heading {
  max-width: 600px;
}

.nu-content-block--medium .nu-content-block__content,
.nu-content-block--medium .nu-content-block__heading {
  max-width: 800px;
}

/* ── Content block CTAs — match hero exactly (flex + 16px gap) ──── */
.nu-content-block__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: var(--nu-gap);
}

/* ── 50/50 Split layout (same pattern as hero — single 66px gap) ────
 * Both columns are vertically centred relative to each other — whichever
 * column is shorter, its content sits in the middle of the tallest. This
 * matches the hero's behaviour and gives a balanced read regardless of
 * how many images are in the gallery (1 / 2 / 3 / 4+). */
.nu-content-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 66px;
  align-items: center;
}

/* media_position = "left" → media goes in column 1, text in column 2 */
.nu-content-split--reversed .nu-content-split__text {
  order: 2;
}

@media (max-width: 1024px) {
  .nu-content-split {
    grid-template-columns: 1fr;
    gap: var(--nu-gap);
  }
  .nu-content-split--reversed .nu-content-split__text {
    order: 0;
  }
}

/* ── Split gallery ───────────────────────────────────────────────── */
.nu-content-split__gallery {
  display: grid;
  gap: 9px;
}

.nu-content-split__gallery-item {
  display: block;
  margin: 0;
  overflow: hidden;
  border-radius: 0;
  cursor: pointer;
}

.nu-content-split__gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--nu-transition-slow);
}

/* .nu-content-split gallery image scale on hover removed 2026-06-06 — no-motion hover rule. */

/* 1 image: single full-width of the column, 1:1 aspect so it balances the
 * text column vertically (without spilling out of the 50% column width). */
.nu-content-split__gallery--single {
  grid-template-columns: 1fr;
}

.nu-content-split__gallery--single img {
  aspect-ratio: 1 / 1;
}

/* 2 images: stacked vertically */
.nu-content-split__gallery--two {
  grid-template-columns: 1fr;
}

.nu-content-split__gallery--two img {
  aspect-ratio: 16 / 9;
}

/* 3 images: 2 squares top + 1 wide bottom */
.nu-content-split__gallery--three {
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto auto;
}

.nu-content-split__gallery--three img {
  aspect-ratio: 1 / 1;
}

.nu-content-split__gallery--three .nu-content-split__gallery-item--wide {
  grid-column: 1 / -1;
}

.nu-content-split__gallery--three .nu-content-split__gallery-item--wide img {
  aspect-ratio: 2 / 1;
}

/* 4+ images: 2x2 grid */
.nu-content-split__gallery--grid {
  grid-template-columns: 1fr 1fr;
}

.nu-content-split__gallery--grid img {
  aspect-ratio: 1 / 1;
}

/* ── Mobile: stack split layout ──────────────────────────────────── */
@media (max-width: 767px) {
  .nu-content-split {
    grid-template-columns: 1fr;
  }

  .nu-content-split__gallery--three,
  .nu-content-split__gallery--grid {
    grid-template-columns: 1fr 1fr;
  }

  .nu-content-split__gallery--three .nu-content-split__gallery-item--wide {
    grid-column: 1 / -1;
  }

  .nu-content-split__gallery img {
    aspect-ratio: 1 / 1;
  }

  .nu-hero__cert-logo {
    max-height: 33px;
  }
}

/* --------------------------------------------------------------------------
   3. Image Gallery
   -------------------------------------------------------------------------- */

.nu-image-gallery__item {
  overflow: hidden;
  margin: 0;
}

.nu-image-gallery__item--square {
  aspect-ratio: 1 / 1;
}

.nu-image-gallery__item--landscape {
  aspect-ratio: 16 / 9;
}

.nu-image-gallery__item--square .nu-image-gallery__img,
.nu-image-gallery__item--landscape .nu-image-gallery__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.nu-image-gallery__img {
  transition: transform var(--nu-transition-slow);
}

/* .nu-image-gallery item image scale on hover removed 2026-06-06 — no-motion hover rule. */

/* Single-image variant — one 1:1 tile, centred and capped in width so
 * it doesn't turn into a giant portrait on wide screens. */
.nu-image-gallery__grid--single {
  grid-template-columns: minmax(0, 720px);
  justify-content: center;
}

/* --------------------------------------------------------------------------
   4. Services List (Masonry)
   -------------------------------------------------------------------------- */

.nu-services-masonry__section-heading {
  /* Use the shared token so all section headings have the same
   * heading → body gap (~33px). The previous `0.75em` rule gave
   * ~25px — visibly tighter than other modules. */
  margin-bottom: var(--nu-gap);
  color: var(--nu-theme-heading);
}

/* Intro width matches the end of column 2 in a 3-column post grid above
 * (or any 3-col 33px-gap section). Formula: (100% - 2*gap)/3 * 2 + gap
 * = exactly col1 + gap + col2 width. Reverts to full-width on tablet
 * and below where the grid above stacks. */
.nu-services-masonry__intro {
  max-width: calc((100% - 2 * var(--nu-gap)) / 3 * 2 + var(--nu-gap));
  margin-bottom: var(--nu-gap-lg);
  color: var(--nu-theme-text);
}

@media (max-width: 1024px) {
  .nu-services-masonry__intro { max-width: none; }
}

/* Masonry-stable layout. JS (accordion.js → distributeMasonry) wraps the
 * items into N `<div class="nu-services-masonry__stack">` columns based
 * on viewport width. Each stack is a flex column, so expanding an
 * accordion in one column NEVER shifts items in other columns — row
 * alignment across columns does not exist. Original left-to-right fill
 * order is preserved via index % cols distribution.
 *
 * Spacing between category groups within a column is var(--nu-gap)*1.33
 * (≈44px). Spacing BETWEEN columns is var(--nu-gap) (33px). */
.nu-services-masonry {
  display: flex;
  flex-wrap: nowrap;
  gap: var(--nu-gap);
  align-items: flex-start;
}

.nu-services-masonry__stack {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: calc(var(--nu-gap) * 1.33);
}

.nu-services-masonry__col {
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  min-width: 0;
}

/* Accordion variants — same spacing as flat cards above */
details.nu-services-masonry__col {
  display: block;
}

.nu-services-masonry__heading {
  margin: 0 0 var(--nu-gap-sm);
  padding-bottom: 0.5em;
  border-bottom: 2px solid var(--nu-green);
  color: var(--nu-theme-heading);
}

.nu-services-masonry__heading a {
  color: var(--nu-theme-heading);
  text-decoration: none;
  transition: color var(--nu-transition);
}

.nu-services-masonry__heading a:hover {
  color: var(--nu-theme-accent);
}

/* Accordion-mode summary (only on categories with sub-services) */
.nu-services-masonry__summary {
  list-style: none;          /* strip native marker */
  cursor: pointer;
  display: flex;
  align-items: baseline;
  gap: 12px;
  justify-content: space-between;
}

.nu-services-masonry__summary::-webkit-details-marker {
  display: none;
}

.nu-services-masonry__heading-text {
  flex: 1 1 auto;
  min-width: 0;
}

/* Shared +/- accordion icon utility — used by services-list and FAQ.
 * Two pseudo-element bars form a "+", the vertical bar scales to 0 when
 * the parent <details> is open → animated "+/−" transition. Pure CSS,
 * no JS required, works with native <details>. */
.nu-accordion-icon {
  flex: 0 0 auto;
  position: relative;
  width: 18px;
  height: 18px;
  color: var(--nu-theme-accent);
  transition: transform var(--nu-transition);
}

.nu-accordion-icon::before,
.nu-accordion-icon::after {
  content: "";
  position: absolute;
  background: currentColor;
  border-radius: 1px;
}

.nu-accordion-icon::before {
  top: 50%;
  left: 0;
  right: 0;
  height: 2px;
  transform: translateY(-50%);
}

.nu-accordion-icon::after {
  left: 50%;
  top: 0;
  bottom: 0;
  width: 2px;
  transform: translateX(-50%);
  transition: transform var(--nu-transition);
}

details[open] > summary .nu-accordion-icon::after {
  transform: translateX(-50%) scaleY(0);
}

/* JS-enhanced close: while the panel collapses, [open] stays set (so
 * we can keep the panel visible during the animation), but the icon
 * should already show + so the two motions run in parallel. The
 * .is-closing class (added by accordion.js on close click, removed at
 * transitionend) forces the + shape. Higher specificity (3 classes)
 * than the [open] rule (2 classes + attr) → wins. */
.is-closing > summary .nu-accordion-icon::after,
.nu-faq-accordion__item.is-closing .nu-accordion-icon::after {
  transform: translateX(-50%) scaleY(1);
}

/* Flat (no sub-services) heading keeps the same visual weight as the
 * accordion summary — no toggle, no cursor. */
.nu-services-masonry__heading--flat {
  cursor: default;
}

.nu-services-masonry__list {
  list-style: none;
  padding-left: 0;
  margin: var(--nu-gap-sm) 0 0;
}

.nu-services-masonry__list li {
  padding: 10px 0;
  border-bottom: 1px solid var(--nu-theme-border);
  color: var(--nu-theme-text);
}

.nu-services-masonry__list li:last-child {
  border-bottom: none;
}

.nu-services-masonry__list li a {
  color: var(--nu-theme-text);
  text-decoration: none;
  transition: color var(--nu-transition);
}

.nu-services-masonry__list li a:hover {
  color: var(--nu-theme-accent);
}

/* Column count is driven by JS (distributeMasonry in accordion.js) — it
 * wraps items into 4 / 2 / 1 stacks based on viewport width. Because
 * each stack is a flex child with flex: 1 1 0, widths auto-balance.
 * Mobile: tighter vertical gap between stacked categories. */
@media (max-width: 767px) {
  .nu-services-masonry__stack {
    gap: var(--nu-gap);
  }
}

/* --------------------------------------------------------------------------
   5. Feature Columns
   -------------------------------------------------------------------------- */

.nu-feature-columns__heading {
  margin-bottom: var(--nu-gap);
}

.nu-feature-columns__grid {
  display: grid;
  gap: var(--nu-gap);
}

.nu-feature-columns__grid--2 { grid-template-columns: repeat(2, 1fr); }
.nu-feature-columns__grid--3 { grid-template-columns: repeat(3, 1fr); }
.nu-feature-columns__grid--4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 767px) {
  .nu-feature-columns__grid--2,
  .nu-feature-columns__grid--3,
  .nu-feature-columns__grid--4 { grid-template-columns: 1fr; }
}

.nu-feature-columns__col {
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  transition: box-shadow var(--nu-transition),
              border-color var(--nu-transition),
              transform var(--nu-transition);
}

/* Hover lift normalised 2026-06-03 to match destination + service cards. */
.nu-feature-columns__col:hover {
  box-shadow: var(--nu-glow-hover);
}
/* Glow-only hover per HIERARCHY-AUDIT §12 (boxed-hover rule, 2026-06-06).
 * Border-colour shift and translateY lift were both removed. */

/* Linked card: the heading anchor's hit area is stretched over the card. */
.nu-feature-columns__col--linked {
  position: relative;
  cursor: pointer;
}

.nu-feature-columns__col-link {
  color: inherit;
  text-decoration: none;
}

.nu-feature-columns__col-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.nu-feature-columns__col--linked:hover .nu-feature-columns__col-link,
.nu-feature-columns__col-link:focus-visible {
  color: var(--nu-theme-accent);
}

.nu-feature-columns__col-heading {
  margin-bottom: var(--nu-gap-sm);
}

.nu-feature-columns__col-text {
  margin-bottom: 0;
}

/* Section CTA below the grid */
.nu-feature-columns__cta {
  margin-top: var(--nu-gap);
}

/* Alignment utility classes (shared across modules) */
.nu-align--center { text-align: center; }
.nu-align--left { text-align: left; }
.nu-align--right { text-align: right; }

/* --------------------------------------------------------------------------
   6. Case Studies Grid
   -------------------------------------------------------------------------- */

.nu-case-studies-grid__heading {
  margin-bottom: var(--nu-gap);
}

.nu-case-studies-grid__card {
  background: var(--nu-theme-surface);
  overflow: hidden;
}

.nu-case-studies-grid__img-link {
  display: block;
  overflow: hidden;
}

.nu-case-studies-grid__img {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform var(--nu-transition-slow);
}

/* .nu-case-studies-grid card image scale on hover removed 2026-06-06 — glow-only hover rule. */

.nu-case-studies-grid__body {
  padding: 20px;
}

.nu-case-studies-grid__title {
  margin-bottom: var(--nu-gap-sm);
}

.nu-case-studies-grid__title a {
  color: var(--nu-theme-heading);
  text-decoration: none;
}

.nu-case-studies-grid__title a:hover {
  color: var(--nu-theme-accent);
}

.nu-case-studies-grid__read-more {
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
}

/* --------------------------------------------------------------------------
   7. Testimonials — arrow-driven horizontal scroll-snap slider.
   The EG Google Reviews plugin renders the review cards
   (<blockquote class="egr-review">) inside <div class="egr-reviews__grid">.
   carousel.js adds .nu-testimonials__track to that grid once it's wired up,
   which flips the layout from the plugin's grid to a scrollable flex row.
   -------------------------------------------------------------------------- */

.nu-testimonials__heading {
  text-align: center;
  margin: 0 0 var(--nu-gap);
  color: var(--nu-theme-heading);
}

.nu-testimonials__slider {
  position: relative;
}

.nu-testimonials__viewport {
  /* The arrow buttons sit outside the viewport at ≥900px; on narrow
   * screens they overlay the viewport corners. Overflow on the track
   * (not here) so the grid clips to the viewport edge. */
  overflow: visible;
}

/* Once JS applies .nu-testimonials__track to the plugin's .egr-reviews__grid,
 * the layout switches from CSS grid to a flex scroll-snap track. */
.egr-reviews__grid.nu-testimonials__track {
  display: flex;
  gap: var(--nu-gap);
  grid-template-columns: none; /* override plugin */
  overflow-x: auto;
  /* Stop trackpad scroll-chain leakage. Without this, a two-finger
   * horizontal swipe inside the track rubber-bands the body once the
   * track hits its scroll bounds — appears as page-level horizontal
   * scroll on macOS. `contain` keeps the scroll event inside. */
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  padding-bottom: 4px; /* breathing room for card shadows */
}

.egr-reviews__grid.nu-testimonials__track::-webkit-scrollbar {
  display: none;
}

/* Each card width = viewport-slice / columns-visible, minus the inter-card
 * gaps. data-columns on the slider drives the denominator. */
.nu-testimonials__slider[data-columns="1"] .egr-reviews__grid.nu-testimonials__track > .egr-review { flex: 0 0 calc(100% - 0px); }
.nu-testimonials__slider[data-columns="2"] .egr-reviews__grid.nu-testimonials__track > .egr-review { flex: 0 0 calc((100% - var(--nu-gap)) / 2); }
.nu-testimonials__slider[data-columns="3"] .egr-reviews__grid.nu-testimonials__track > .egr-review { flex: 0 0 calc((100% - var(--nu-gap) * 2) / 3); }

.egr-reviews__grid.nu-testimonials__track > .egr-review {
  scroll-snap-align: start;
}

@media (max-width: 900px) {
  .nu-testimonials__slider[data-columns="2"] .egr-reviews__grid.nu-testimonials__track > .egr-review,
  .nu-testimonials__slider[data-columns="3"] .egr-reviews__grid.nu-testimonials__track > .egr-review {
    flex: 0 0 calc((100% - var(--nu-gap)) / 2);
  }
}

/* On mobile widths, always show 1 review at a time — regardless of the
 * editor's `columns` choice. One card per slide makes quote text legible
 * on narrow screens; users swipe / tap arrows between them. */
@media (max-width: 767px) {
  .nu-testimonials__slider .egr-reviews__grid.nu-testimonials__track > .egr-review {
    flex: 0 0 100%;
  }
}

/* Arrows — flank the viewport on desktop, overlay on small screens. */
.nu-testimonials__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  color: var(--nu-theme-accent);
  cursor: pointer;
  transition: background var(--nu-transition),
              color var(--nu-transition),
              border-color var(--nu-transition);
}

.nu-testimonials__arrow:hover {
  background: var(--nu-green);
  border-color: var(--nu-green);
  color: #fff;
}

.nu-testimonials__arrow:focus-visible {
  outline: 2px solid var(--nu-green);
  outline-offset: 2px;
}

/* Arrows always overlay the slider corners (not the container margin) so
 * they're visible on every viewport width. The track has slight bottom
 * padding so card shadows aren't clipped. */
.nu-testimonials__arrow--prev { left: 4px; }
.nu-testimonials__arrow--next { right: 4px; }

/* Hide the arrows entirely on very small screens where cards stack to 1
 * column and scroll via swipe. */
@media (max-width: 500px) {
  .nu-testimonials__arrow {
    display: none;
  }
}

/* --------------------------------------------------------------------------
   7a. Reviews — Bento layout (1 big + 4 small)
   --------------------------------------------------------------------------
   3-col × 2-row grid. The first card (longest review, marked by JS as
   `.nu-reviews-bento__card--big`) spans both rows in column 1, giving
   it 2× the width of each small card. The 4 small cards auto-flow into
   the remaining cells.

   Cards line-clamp their body text to keep the rectangle uniform at
   rest. Each card with overflow gets a "Read more" button (added by
   JS) that toggles `.is-expanded` — removing the clamp and pushing
   that row to grow.

   Layout:

     +----------+----+----+
     |          |  2 |  3 |
     |    1     +----+----+
     |   (big)  |  4 |  5 |
     +----------+----+----+
   -------------------------------------------------------------------------- */

.nu-reviews-bento {
  position: relative;
}

.nu-reviews-bento .egr-reviews {
  margin: 0;
  padding: 0;
}
.nu-reviews-bento .egr-reviews__header,
.nu-reviews-bento .egr-reviews__heading,
.nu-reviews-bento .egr-reviews__intro {
  display: none;
}

.nu-reviews-bento .egr-reviews__grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr;
  grid-template-rows: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--nu-gap);
  align-items: stretch;
}

/* Each card = Tier-2 surface tint card */
.nu-reviews-bento .nu-reviews-bento__card {
  margin: 0;
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  transition: box-shadow var(--nu-transition);
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap-sm);
  min-width: 0;
}

.nu-reviews-bento .nu-reviews-bento__card:hover {
  box-shadow: var(--nu-glow-hover);
}

/* Big card spans 2 rows */
.nu-reviews-bento .nu-reviews-bento__card--big {
  grid-row: span 2;
}

/* Line-clamp the body text — keeps the rectangle uniform at rest.
 * Small cards get 4 lines, big card gets ~12 to match its taller slot. */
.nu-reviews-bento .nu-reviews-bento__card .egr-review__text {
  display: -webkit-box;
  -webkit-line-clamp: 4;
          line-clamp: 4;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0;
}

.nu-reviews-bento .nu-reviews-bento__card--big .egr-review__text {
  -webkit-line-clamp: 12;
          line-clamp: 12;
}

/* Owner reply also clamps */
.nu-reviews-bento .nu-reviews-bento__card .egr-review__reply-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
          line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.nu-reviews-bento .nu-reviews-bento__card--big .egr-review__reply-text {
  -webkit-line-clamp: 4;
          line-clamp: 4;
}

/* Expanded state — release the clamp, let the card grow. */
.nu-reviews-bento .nu-reviews-bento__card.is-expanded .egr-review__text,
.nu-reviews-bento .nu-reviews-bento__card.is-expanded .egr-review__reply-text {
  -webkit-line-clamp: unset;
          line-clamp: unset;
  display: block;
  overflow: visible;
}

/* "Read more" / "Show less" button — uses the canonical cta-link pattern */
.nu-reviews-bento .nu-reviews-bento__expand {
  align-self: flex-start;
  margin-top: auto;
  padding: 0 0 2px 0;
  background: transparent;
  background-image: linear-gradient(45deg,
    var(--nu-gradient-green-end),
    var(--nu-gradient-green-start));
  background-position: 0 100%;
  background-size: 100% 2px;
  background-repeat: no-repeat;
  border: 0;
  font-family: var(--nu-font);
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-accent);
  cursor: pointer;
  line-height: var(--nu-lh-snug);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  transition: color var(--nu-transition);
}

.nu-reviews-bento .nu-reviews-bento__expand:hover {
  color: var(--nu-theme-accent-hover);
  animation: nu-link-hover 0.8s ease-in-out forwards;
}

/* Tablet — drop big card to single-row + 2-col grid for smalls */
@media (max-width: 1024px) {
  .nu-reviews-bento .egr-reviews__grid {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto;
  }
  .nu-reviews-bento .nu-reviews-bento__card--big {
    grid-column: span 2;
    grid-row: span 1;
  }
}

/* Mobile — single column stack. Line-clamp tightens to compensate. */
@media (max-width: 600px) {
  .nu-reviews-bento .egr-reviews__grid {
    grid-template-columns: 1fr;
  }
  .nu-reviews-bento .nu-reviews-bento__card--big {
    grid-column: span 1;
  }
  .nu-reviews-bento .nu-reviews-bento__card .egr-review__text {
    -webkit-line-clamp: 6;
            line-clamp: 6;
  }
  .nu-reviews-bento .nu-reviews-bento__card--big .egr-review__text {
    -webkit-line-clamp: 8;
            line-clamp: 8;
  }
}

/* --------------------------------------------------------------------------
   7b. Reviews — Justified masonry layout
   --------------------------------------------------------------------------
   When the testimonials module's `layout` ACF field is `justified`, the
   template wraps the plugin shortcode in `[data-nu-reviews-justified]`
   and reviews-justify.js redistributes the .egr-review cards into N
   `.nu-reviews-justified__col` wrappers balanced by word count.

   See assets/js/reviews-justify.js for the algorithm.
   -------------------------------------------------------------------------- */

/* Bounded "bento" container.
 *
 * The justified review wall is given a fixed visible height that holds
 * regardless of how many reviews come back from the sync. Overflow scrolls
 * INSIDE the section (overscroll-behavior: contain so the page doesn't
 * rubber-band when you reach the scroll bounds).
 *
 * Heights are tokenised — editors pick from short/medium/tall/auto in
 * the ACF dropdown. Default = medium.
 *
 * The actual column distribution still comes from JS (LPT balancing by
 * word count), which means EACH column reads roughly the same height,
 * so even when the container caps at e.g. 650px the cut-off is even
 * across all three columns rather than ragged.
 */
.nu-reviews-justified {
  position: relative;
  overflow-y: auto;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
  scroll-snap-type: y proximity;
  /* Subtle scrollbar — visible enough to signal scroll, not loud */
  scrollbar-width: thin;
  scrollbar-color: var(--nu-theme-border) transparent;
}

.nu-reviews-justified::-webkit-scrollbar {
  width: 8px;
}
.nu-reviews-justified::-webkit-scrollbar-track {
  background: transparent;
}
.nu-reviews-justified::-webkit-scrollbar-thumb {
  background: var(--nu-theme-border);
  border-radius: 0;
}
.nu-reviews-justified::-webkit-scrollbar-thumb:hover {
  background: var(--nu-theme-muted);
}

/* Section height variants */
.nu-reviews-justified--height-short  { max-height: 500px; }
.nu-reviews-justified--height-medium { max-height: 650px; }
.nu-reviews-justified--height-tall   { max-height: 800px; }
.nu-reviews-justified--height-auto   { max-height: none; overflow-y: visible; }

/* Reviews snap into clean stops as the user scrolls — the top of each
 * review aligns to the top of the scrollport with breathing room. */
.nu-reviews-justified .egr-review {
  scroll-snap-align: start;
  scroll-margin-top: var(--nu-gap-sm);
}

/* Plugin's outer <section> + heading collapse to nothing — we render
 * our own heading from the template, and the section is just a passthrough. */
.nu-reviews-justified .egr-reviews {
  margin: 0;
  padding: 0;
}
.nu-reviews-justified .egr-reviews__header,
.nu-reviews-justified .egr-reviews__heading,
.nu-reviews-justified .egr-reviews__intro {
  display: none;
}

/* Cards stack vertically inside each column with consistent gap. */
.nu-reviews-justified__col {
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap);
  min-width: 0;
}

/* Reset the plugin's default .egr-review card chrome and rebuild from
 * theme tokens. Tier-2 card: surface tint, 1px border, glow shadow,
 * hover = glow brightens (per the boxed-hover rule). */
.nu-reviews-justified .egr-review {
  margin: 0;
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  transition: box-shadow var(--nu-transition);
  /* CSS custom property gets set per-card by JS as data-words attr;
   * any future per-bucket styling can use the bucket classes below. */
}

.nu-reviews-justified .egr-review:hover {
  box-shadow: var(--nu-glow-hover);
}

/* Optional bucket styling — short / medium / long. Keep subtle:
 * differentiate via emphasis, not layout. */
.nu-reviews-justified .egr-review--short  { /* same baseline */ }
.nu-reviews-justified .egr-review--medium { /* same baseline */ }
.nu-reviews-justified .egr-review--long   { /* same baseline */ }

/* Before JS runs the cards are in the plugin's grid — give them a
 * sensible single-column fallback so SSR + no-JS users still see a
 * usable stack. */
.nu-reviews-justified:not(.is-distributed) .egr-reviews__grid {
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap);
}

/* Mobile: 1 column regardless of data-columns. JS also enforces this
 * for runtime distribution, but the CSS rule makes the unstyled state
 * graceful. */
@media (max-width: 600px) {
  .nu-reviews-justified .egr-reviews__grid {
    flex-direction: column !important;
  }
  .nu-reviews-justified__col {
    width: 100%;
  }
}

/* --------------------------------------------------------------------------
   8. FAQ Accordion
   -------------------------------------------------------------------------- */

.nu-faq-accordion__heading {
  margin-bottom: var(--nu-gap);
}

.nu-faq-accordion__item {
  border-bottom: 1px solid var(--nu-theme-border);
}

.nu-faq-accordion__item:first-child {
  border-top: 1px solid var(--nu-theme-border);
}

.nu-faq-accordion__question {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px 0;
  font-weight: var(--nu-fw-bold);
  font-size: var(--nu-fs-h3);
  color: var(--nu-theme-heading);
  cursor: pointer;
  list-style: none;
}

.nu-faq-accordion__question::-webkit-details-marker {
  display: none;
}

.nu-faq-accordion__question-text {
  flex: 1 1 auto;
  min-width: 0;
}
/* +/- icon styled by the shared .nu-accordion-icon utility (see above) —
 * previously emitted via ::after with "+" / "−" text; replaced for a
 * consistent animated cross with the services-list accordion. */

.nu-faq-accordion__answer {
  color: var(--nu-theme-muted);
}

.nu-faq-accordion__answer p:last-child {
  margin-bottom: 0;
}

/* Padding lives on the JS-added inner wrapper (see accordion.js). This
 * keeps the animated outer panel free of a padding minimum, so height
 * can shrink to true zero on close — no tail-of-collapse snap. */
.nu-faq-accordion__answer > .nu-accordion-panel__inner {
  padding: 0 0 20px;
}

/* Fallback when JS is disabled / not yet enhanced: put the padding
 * back on the answer itself so the FAQ still reads with breathing
 * room. Removed via the wrapper rule above once JS runs. */
.nu-faq-accordion__item:not([data-nu-anim="1"]) .nu-faq-accordion__answer {
  padding: 0 0 20px;
}

/* Animated accordion panel — used by accordion.js on the FAQ answer
 * and on any [data-nu-accordion] <details> panel. JS toggles inline
 * height + opacity to animate; the transition here drives the motion.
 *
 * Duration + easing intentionally match --nu-transition so the panel
 * expand/collapse runs in lockstep with the +/− icon's scaleY
 * transform (see .nu-accordion-icon::after above). Same 0.3s
 * ease-in-out → both animations start, peak, and settle together. */
.nu-accordion-panel {
  overflow: hidden;
  will-change: height, opacity;
  transition:
    height  var(--nu-transition),
    opacity var(--nu-transition);
}

/* --------------------------------------------------------------------------
   9. Contact Form
   --------------------------------------------------------------------------
   Two layout modes (driven by ACF layout_mode, rendered in the module
   PHP as `.nu-contact-form--centered` or `.nu-contact-form--split`):

     - Centered: heading + intro + form stacked. Default for legacy.
     - Split:    copy column LEFT (heading, intro, bullets, phone callout),
                 form-in-a-box RIGHT. Matches mockups/location-optimal-*
                 and mockups/service-optimal-* prototypes.

   Input field styling (inside the form box) is shared between both
   layouts — defined further down in Section 17 (CF7-inline-fields)
   and applied via `.nu-contact-form__form ...` selectors.
   ------------------------------------------------------------------------ */

/* Typography hierarchy for the CTA contact section.
 *
 * Three sizes, two weights — no more. Per 2026-06-06 client direction:
 *   "I don't want lots of font weights and sizes throughout — a very
 *    simple straightforward hierarchy that is clear and consistent."
 *
 *   H2   (--nu-fs-h2)     bold   — section heading
 *   Body (--nu-fs-body)   regular — intro, bullets, phone link, inputs
 *   Small (--nu-fs-small) bold  — eyebrow label, form labels, (REQUIRED)
 *
 * Colours: heading / text / muted / accent. Theme tokens, no raw hex.
 */

.nu-contact-form__heading {
  /* Heading inherits canonical H2 scale (--nu-fs-h2, 700 weight) from
   * global.css. Only need the gap-to-intro here. */
  margin: 0 0 var(--nu-gap);
}

.nu-contact-form__intro {
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-regular);
  color: var(--nu-theme-muted);
  margin: 0 0 var(--nu-gap);
  line-height: var(--nu-lh-body);
}
.nu-contact-form__intro p { margin: 0 0 var(--nu-gap-sm); }
.nu-contact-form__intro > *:last-child { margin-bottom: 0; }

/* ── Split layout: copy left, form-box right ───────────────────────── */
.nu-contact-form__split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--nu-gap-lg);
  align-items: start;
}

.nu-contact-form__copy {
  display: flex;
  flex-direction: column;
}

.nu-contact-form--split .nu-contact-form__heading {
  text-align: left;
}

/* Bullets — body size, regular weight, brand 9×9 gradient-square markers.
 * Class-scoped because global `ul:not([class])` skips classed lists. */
.nu-contact-form__bullets {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap-sm);
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-regular);
}

.nu-contact-form__bullets li {
  position: relative;
  padding-left: 22px;
  line-height: var(--nu-lh-body);
}

.nu-contact-form__bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  background: linear-gradient(135deg,
    var(--nu-gradient-green-start),
    var(--nu-gradient-green-end));
}

/* "Prefer a call?" + phone — stacked. Eyebrow above, body-size accent
 * link below. Phone is bold + accent so it carries weight, but stays
 * the SAME SIZE as the rest of the copy column. */
.nu-contact-form__phone {
  margin-top: var(--nu-gap);
  padding-top: var(--nu-gap);
  border-top: 1px solid var(--nu-theme-border);
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.nu-contact-form__phone-label {
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-muted);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
}

.nu-contact-form__phone-link,
.nu-contact-form__phone-link:link,
.nu-contact-form__phone-link:visited {
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-accent);
  text-decoration: none;
  line-height: var(--nu-lh-snug);
  transition: color var(--nu-transition);
}

.nu-contact-form__phone-link:hover {
  color: var(--nu-theme-accent-hover);
}

/* Form-as-a-box — surface-tinted, gradient top border (Tier-2 card per
 * the design hierarchy doc). Lives only in the split layout. */
.nu-contact-form__form-col {
  position: relative;
}

.nu-contact-form--split .nu-contact-form__form {
  background: var(--nu-theme-surface);
  padding: var(--nu-pad-sm); /* 33px */
}
/* Gradient top stripe deleted 2026-06-06 — side/edge gradient accents
 * reserved exclusively for the hero. Form box reads as a Tier-2 card
 * via surface tint + glow on hover. */

/* Centered intro spacing — preserve legacy rhythm */
.nu-contact-form--centered .nu-contact-form__inner {
  max-width: 720px;
  margin: 0 auto;
}

/* Stack to single column at the standard 900px breakpoint used
 * elsewhere for two-column → one-column transitions */
@media (max-width: 900px) {
  .nu-contact-form__split {
    grid-template-columns: 1fr;
    gap: var(--nu-gap-lg);
  }
}

/* --------------------------------------------------------------------------
   10. Logo Carousel (infinite smooth scroll, or static row when items ≤ columns)
   -------------------------------------------------------------------------- */

.nu-logo-carousel__heading {
  text-align: center;
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-wide);
  color: var(--nu-theme-text);
  opacity: 0.7;
  margin: 0 0 var(--nu-gap);
  font-weight: var(--nu-fw-bold);
}

.nu-logo-carousel {
  --nu-logo-cols: 6;
  --nu-logo-carousel-duration: 30s;
}

/* Mask the edges so logos fade in/out on the ends (nicer than a hard cut) */
.nu-logo-carousel__viewport {
  overflow: hidden;
  mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 5%,
    #000 95%,
    transparent 100%
  );
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0,
    #000 5%,
    #000 95%,
    transparent 100%
  );
}

.nu-logo-carousel__track {
  display: flex;
  align-items: center;
  gap: var(--nu-gap);
  list-style: none;
  padding: 0;
  margin: 0;
  width: max-content;
}

/* Static mode — items ≤ columns, no JS, no animation. Just an evenly
 * spaced flex row that fills the container.  */
.nu-logo-carousel--static .nu-logo-carousel__viewport {
  mask-image: none;
  -webkit-mask-image: none;
}

.nu-logo-carousel--static .nu-logo-carousel__track {
  justify-content: space-between;
  gap: var(--nu-gap);
  width: 100%;
}

/* Item widths are set by carousel.js at runtime based on the viewport
 * width divided by --nu-logo-cols. We intentionally don't set width in
 * CSS here because a percentage-of-parent would be circular (the track
 * is max-content, which is sized by its children). */
.nu-logo-carousel__item {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Static row — no JS active. CSS handles the even distribution. */
.nu-logo-carousel--static .nu-logo-carousel__item {
  flex: 1 1 0;
  min-width: 0;
}

.nu-logo-carousel__logo {
  max-height: 50px;
  max-width: 100%;
  width: auto;
  opacity: 0.75;
  transition: opacity var(--nu-transition);
}

.nu-logo-carousel__viewport:hover .nu-logo-carousel__logo {
  opacity: 1;
}

.nu-logo-carousel--greyscale .nu-logo-carousel__logo {
  filter: grayscale(100%);
}

.nu-logo-carousel--greyscale .nu-logo-carousel__viewport:hover .nu-logo-carousel__logo {
  filter: grayscale(0);
}

/* White logos in light mode. Must out-rank the greyscale filter and its
 * hover state above, or white-on-white logos stay invisible. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .nu-logo-carousel .nu-logo-carousel__logo.nu-invert-on-light {
    filter: brightness(0) opacity(0.75);
  }
}

[data-theme="light"] .nu-logo-carousel .nu-logo-carousel__logo.nu-invert-on-light,
[data-theme="light"] .nu-logo-carousel .nu-logo-carousel__viewport:hover .nu-logo-carousel__logo.nu-invert-on-light {
  filter: brightness(0) opacity(0.75);
}

/* JS adds this class once it has cloned the items and measured duration.
 * The animation translates the track left by exactly half its width (the
 * length of one original set), so when it loops back the seam is invisible. */
.nu-logo-carousel__track--scrolling {
  animation: nu-logo-scroll var(--nu-logo-carousel-duration) linear infinite;
}

@keyframes nu-logo-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

/* Mobile: shrink columns to keep logos readable */
@media (max-width: 1024px) {
  .nu-logo-carousel { --nu-logo-cols: 4; }
}

@media (max-width: 600px) {
  .nu-logo-carousel { --nu-logo-cols: 3; }
}

/* --------------------------------------------------------------------------
   11. CTA Banner
   -------------------------------------------------------------------------- */

.nu-cta-banner__inner {
  text-align: center;
  padding: 40px;
}

/* On a gradient section, a CTA with no explicit card background becomes a
   solid dark card (like the gradient hero) so the gradient reads around it,
   not behind the text. An explicit card_background choice still wins. */
.nu-cta-banner.nu-style--gradient .nu-cta-banner__inner:not([class*="--bg-"]):not(.nu-style--invert) {
  background: var(--nu-theme-bg);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
}

.nu-cta-banner__heading {
  margin-bottom: var(--nu-gap);
}

.nu-cta-banner__body {
  max-width: 700px;
  margin-left: auto;
  margin-right: auto;
  margin-bottom: var(--nu-gap);
}

.nu-cta-banner__ctas {
  gap: 15px;
}

/* --------------------------------------------------------------------------
   12. Two Column Content
   -------------------------------------------------------------------------- */

.nu-two-col__grid {
  align-items: center;
}

.nu-two-col__image {
  width: 100%;
  height: auto;
}

.nu-two-col__content h2,
.nu-two-col__content h3 {
  margin-bottom: var(--nu-gap-sm);
}

.nu-two-col__content p:last-child {
  margin-bottom: 0;
}

/* --------------------------------------------------------------------------
   13. Process Steps
   -------------------------------------------------------------------------- */

.nu-process-steps__heading {
  margin-bottom: var(--nu-gap);
  text-align: center;
}

/* All steps in one even, connected row on desktop regardless of count
   (avoids the 4-col grid orphaning a 5th step); stacks responsively. */
.nu-process-steps__grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--nu-gap);
}
@media (max-width: 1024px) {
  .nu-process-steps__grid {
    grid-auto-flow: row;
    grid-auto-columns: auto;
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 600px) {
  .nu-process-steps__grid { grid-template-columns: 1fr; }
}

.nu-process-steps__step {
  position: relative;
  text-align: center;
  padding: 30px 20px;
}

.nu-process-steps__number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border: 2px solid var(--nu-green);
  border-radius: 50%;
  font-size: var(--nu-fs-h2);
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-accent);
  margin-bottom: var(--nu-gap);
}

.nu-process-steps__title {
  margin-bottom: var(--nu-gap-sm);
}

.nu-process-steps__description {
  color: var(--nu-theme-muted);
  font-size: var(--nu-fs-small);
}

/* Timeline connector line between steps */
@media (min-width: 1025px) {
  .nu-process-steps__step:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 58px;
    right: -10px;
    width: calc(100% - 76px);
    height: 2px;
    background: linear-gradient(90deg, var(--nu-green), transparent);
    transform: translateX(50%);
    pointer-events: none;
  }
}

/* --------------------------------------------------------------------------
   14. Partner Feature — 50/50 split with 1:1 image, using the shared
   .nu-content-split layout (see §2 content block). Features list uses
   the brand gradient-square bullet (same visual as any other list on
   the site).
   -------------------------------------------------------------------------- */

/* Media column: 1:1 aspect so it balances the text column vertically */
.nu-partner-feature__media {
  display: block;
}

.nu-partner-feature__image {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

.nu-partner-feature__heading {
  margin-bottom: var(--nu-gap-sm);
}

/* Features list — brand gradient-square bullet, identical to global ul */
.nu-partner-feature__features {
  list-style: none;
  padding-left: 0;
  margin: var(--nu-gap-sm) 0 var(--nu-gap);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.nu-partner-feature__features li {
  position: relative;
  padding-left: 22px;
  line-height: var(--nu-lh-body);
  color: var(--nu-theme-text);
}

.nu-partner-feature__features li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  background: linear-gradient(135deg, var(--nu-gradient-green-start), var(--nu-gradient-green-end));
}

.nu-partner-feature__cta {
  margin-top: var(--nu-gap-sm);
}

/* --------------------------------------------------------------------------
   15. Cards & Shared Components
   -------------------------------------------------------------------------- */

/* Case study & generic cards */
.nu-card {
  background: var(--nu-theme-surface);
  overflow: hidden;
  transition: box-shadow var(--nu-transition);
}

.nu-card:hover {
  box-shadow: var(--nu-glow-hover);
}

.nu-card__image-link {
  display: block;
  overflow: hidden;
}

.nu-card__image {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  transition: transform var(--nu-transition-slow);
}

/* .nu-card image scale on hover removed 2026-06-06 — glow-only hover rule. */

.nu-card__body {
  padding: 24px;
}

.nu-card__title {
  font-size: var(--nu-fs-h3);
  margin-bottom: var(--nu-gap-sm);
}

.nu-card__title a {
  color: var(--nu-theme-heading);
  text-decoration: none;
}

.nu-card__title a:hover {
  color: var(--nu-theme-accent);
  text-decoration: none;
}

.nu-card__date {
  display: block;
  font-size: var(--nu-fs-small);
  color: var(--nu-mid-grey);
  margin-bottom: var(--nu-gap);
}

/* Case study single page */
.nu-case-study__hero-image {
  margin-top: 2em;
}

.nu-case-study__featured-img {
  width: 100%;
  height: auto;
}

.nu-case-study__intro {
  gap: 40px;
}

.nu-case-study__overview {
  font-size: var(--nu-fs-small);
}

.nu-case-study__overview .case-list {
  list-style: none;
  padding-left: 0;
}

.nu-case-study__overview .case-list li {
  padding: 6px 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

/* Case study gallery styles live in §25 Case Study, further down. */

/* --------------------------------------------------------------------------
   16. Work Archive Cards
   -------------------------------------------------------------------------- */

.nu-work-grid {
  gap: 30px;
}

.nu-work-card {
  background: var(--nu-theme-surface);
  overflow: hidden;
  transition: box-shadow var(--nu-transition);
}

.nu-work-card:hover {
  box-shadow: var(--nu-glow-hover);
}

.nu-work-card__image-link {
  display: block;
  overflow: hidden;
}

.nu-work-card__image {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  display: block;
  transition: transform var(--nu-transition-slow);
}

/* .nu-work-card image scale on hover removed 2026-06-06 — glow-only hover rule. */

/* No padding — title aligns with image edges */
.nu-work-card__title {
  font-size: var(--nu-fs-h3);
  margin: 16px 0 6px;
  color: var(--nu-theme-heading);
}

.nu-work-card__title a {
  color: var(--nu-theme-heading);
  text-decoration: none;
}

.nu-work-card__title a:hover {
  color: var(--nu-theme-accent);
}

.nu-work-card__date {
  display: block;
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  margin-bottom: 12px;
}

/* Case study back link */
.nu-case-study__back {
  margin-bottom: var(--nu-gap);
}

/* --------------------------------------------------------------------------
   17. Contact Form — Inline fields
   -------------------------------------------------------------------------- */

.nu-contact-form__heading {
  margin-bottom: var(--nu-gap);
  color: var(--nu-theme-heading);
}

.nu-contact-form__intro {
  margin-bottom: var(--nu-gap-lg);
}

/* CF7-specific layout rules deleted 2026-06-06 — site standardised on
 * Gravity Forms. GF's grid layout is styled via the `.gform_wrapper`
 * block further down. */

.nu-contact-form__form input[type="text"],
.nu-contact-form__form input[type="email"],
.nu-contact-form__form input[type="tel"],
.nu-contact-form__form input[type="url"],
.nu-contact-form__form textarea,
.nu-contact-form__form select {
  width: 100%;
  padding: 14px 16px;
  background: var(--nu-theme-input-bg);
  border: 1px solid var(--nu-theme-input-border);
  color: var(--nu-theme-text);
  font-family: var(--nu-font);
  font-size: var(--nu-fs-body);
  transition: border-color var(--nu-transition);
}

.nu-contact-form__form input::placeholder,
.nu-contact-form__form textarea::placeholder {
  color: var(--nu-theme-muted);
  opacity: 0.6;
}

.nu-contact-form__form input:focus,
.nu-contact-form__form textarea:focus,
.nu-contact-form__form select:focus {
  outline: none;
  border-color: var(--nu-green);
}

/* .nu-contact-form__form label deleted 2026-06-06 — was muted lower-case
 * (off-brand). Canonical label styling now lives in the GF/CF7 normalise
 * block (uppercase, bold, text colour). */

.nu-contact-form__form input[type="submit"] {
  display: inline-block;
  font-family: var(--nu-font);
  font-weight: var(--nu-fw-bold);
  font-size: var(--nu-fs-body);
  padding: 14px 40px;
  background: var(--nu-green);
  color: var(--nu-bg-dark);
  border: 2px solid var(--nu-green);
  cursor: pointer;
  transition: background-color var(--nu-transition), color var(--nu-transition);
  min-height: 44px;
}

.nu-contact-form__form input[type="submit"]:hover {
  background: var(--nu-blue);
  border-color: var(--nu-blue);
  color: var(--nu-theme-heading);
}

/* --------------------------------------------------------------------------
   Post / Case Study Cards — transparent bg, type pills
   -------------------------------------------------------------------------- */

.nu-post-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--nu-gap);
}

.nu-post-card {
  background: transparent;
  overflow: visible;
}

.nu-post-card__image-link {
  display: block;
  overflow: hidden;
  border-radius: 0;
}

.nu-post-card__image-link img,
.nu-post-card__image {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  display: block;
  transition: transform var(--nu-transition-slow);
}

/* .nu-post-card image scale on hover removed 2026-06-06 — glow-only hover rule. */

.nu-post-card__pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 12px;
}

/* Single case-study hero: pills sit above the H1 with standardised
 * breathing room matching other heading→body gaps. */
.nu-case-study__hero .nu-post-card__pills {
  margin-top: 0;
  margin-bottom: var(--nu-gap-sm);
}

.nu-post-card__pill,
a.nu-post-card__pill,
a.nu-post-card__pill:link,
a.nu-post-card__pill:visited {
  display: inline-block;
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  padding: 3px 10px;
  border-radius: 2px;
  text-decoration: none;
  transition: opacity var(--nu-transition);
}

a.nu-post-card__pill:hover,
a.nu-post-card__pill:focus-visible {
  opacity: 0.85;
  text-decoration: none;
}

/* Badge colours must survive :hover.
 *
 * The global `a:hover` rule sets `color: var(--nu-theme-accent-hover)`,
 * which in dark mode is #20B6BA. That is the exact teal used as the
 * mechanical badge background, so on hover the label turned the same
 * colour as its own pill and vanished.
 *
 * `a:hover` scores (0,1,1); a bare `.nu-post-card__pill--x` scores
 * (0,1,0) and loses. Adding the `a` element and the `:hover` /
 * `:focus-visible` pseudo-class brings these to (0,2,1), which beats it
 * outright, so the fix does not depend on stylesheet load order.
 *
 * Every badge therefore holds its resting label colour in all states.
 * The only hover feedback is the shared opacity shift above. */
.nu-post-card__pill--work,
a.nu-post-card__pill--work:hover,
a.nu-post-card__pill--work:focus-visible {
  background: var(--nu-green);
  color: var(--nu-bg-dark);
}

.nu-post-card__pill--post,
a.nu-post-card__pill--post:hover,
a.nu-post-card__pill--post:focus-visible {
  background: var(--nu-blue);
  color: var(--nu-bg-dark);
}

/* Service-type badges — distinct per term, consistent visual weight. */
.nu-post-card__pill--service,
a.nu-post-card__pill--service:hover,
a.nu-post-card__pill--service:focus-visible {
  background: var(--nu-blue);
  color: var(--nu-bg-dark);
}

.nu-post-card__pill--service-electrical,
a.nu-post-card__pill--service-electrical:hover,
a.nu-post-card__pill--service-electrical:focus-visible {
  background: #F5C518;
  color: var(--nu-bg-dark);
}

.nu-post-card__pill--service-mechanical,
a.nu-post-card__pill--service-mechanical:hover,
a.nu-post-card__pill--service-mechanical:focus-visible {
  background: var(--nu-blue);
  color: var(--nu-bg-dark);
}

/* #C63F33 rather than the original #D94A3D: white on #D94A3D measured
 * 4.20:1, under the 4.5:1 AA threshold for this 12px label. #C63F33
 * gives 5.05:1 and is visually near-identical. */
.nu-post-card__pill--service-fire-and-security,
a.nu-post-card__pill--service-fire-and-security:hover,
a.nu-post-card__pill--service-fire-and-security:focus-visible {
  background: #C63F33;
  color: var(--nu-white);
}

.nu-post-card__title {
  font-size: var(--nu-fs-h3);
  margin: 8px 0 6px;
}

.nu-post-card__title a {
  color: var(--nu-theme-heading);
  text-decoration: none;
}

.nu-post-card__title a:hover {
  color: var(--nu-theme-accent);
}

.nu-post-card__date {
  display: block;
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  margin-bottom: 10px;
}

/* --------------------------------------------------------------------------
   Shared responsive adjustments
   -------------------------------------------------------------------------- */

@media (max-width: 767px) {
  /* CTA banner inner padding ONLY when the banner actually has a
   * background treatment. When the editor sets background_style: none
   * and boxed: off, the banner becomes plain text on the page bg —
   * extra internal padding inset would push content off the gutter. */
  .nu-section--boxed .nu-cta-banner__inner,
  [class*="nu-bg--"]:not(.nu-bg--none) .nu-cta-banner__inner,
  .nu-style--gradient .nu-cta-banner__inner {
    padding: 25px 20px;
  }

  .nu-feature-columns__col {
    padding: 20px;
  }

  .nu-post-grid {
    grid-template-columns: 1fr;
    gap: 66px;  /* doubled mobile gap for clear visual separation between project cards */
  }
}

/* ==========================================================================
   18. Forms (Gravity Forms + CF7 — standardised, NOT theme-switched)
   White background, border, no radius, regardless of dark/light mode.
   ========================================================================== */

/* Container */
.gform_wrapper,
/* .wpcf7-form base reset removed 2026-06-06 — CF7 retired. */

/* Gravity Forms layout reset 2026-06-06.
 *
 * GF's "Orbital" theme (loaded by default since GF 2.7) applies its own
 * grid layout to .gform_wrapper and .gform_fields with `display: grid`
 * + a 12-track template. That fights our intended simple-stack layout
 * inside the form box and was rendering inputs at 80px wide.
 *
 * We forcibly reset the wrapper + fields to a clean vertical stack and
 * force every input/textarea/select to 100% width regardless of GF's
 * .medium/.large/.small size classes. */

.nu-contact-form .gform_wrapper,
.nu-contact-form .gform_wrapper.gform-theme,
.gform_wrapper.gform-theme--foundation,
.gform_wrapper.gform-theme--framework {
  display: block !important;
  grid-template-columns: none !important;
}

.gform_wrapper .gform_fields {
  display: flex !important;
  flex-direction: column;
  gap: 14px !important;       /* GF Orbital sets 40px row-gap — beat it */
  row-gap: 14px !important;
  grid-template-columns: none !important;
  margin: 0 !important;
  padding: 0 !important;
  list-style: none;
}

.gform_wrapper .gfield {
  width: 100%;
  grid-column: auto !important;
  margin: 0 !important;
  padding: 0 !important;
  border: 0;
}

.gform_wrapper .ginput_container {
  width: 100%;
}

/* Label — Gravity Forms only (site standardised on GF 2026-06-06).
 * High specificity + !important to win against GF's orbital stylesheet
 * which loads after ours and otherwise sets font-weight: 500 and
 * color: rgb(17, 35, 55). */
.nu-contact-form .gform_wrapper .gfield_label,
.nu-contact-form .gform_wrapper legend.gfield_label,
.nu-contact-form .gform_wrapper .gform-field-label,
.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label {
  display: block !important;
  font-size: var(--nu-fs-small) !important;
  font-weight: var(--nu-fw-bold) !important;
  color: var(--nu-theme-text) !important;
  margin-bottom: 6px !important;
  text-transform: uppercase !important;
  letter-spacing: var(--nu-ls-label) !important;
  line-height: var(--nu-lh-snug) !important;
}

.gform_wrapper .gfield_required {
  color: var(--nu-theme-accent);
  margin-left: 4px;
}

/* Inputs — white bg, black text, border, no radius.
 * Width forced to 100% to override GF's .medium / .large / .small
 * size classes which otherwise constrain the field to ~80px. */
.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="tel"],
.gform_wrapper input[type="url"],
.gform_wrapper input[type="number"],
.gform_wrapper input.medium,
.gform_wrapper input.large,
.gform_wrapper input.small,
.gform_wrapper textarea,
.gform_wrapper select {
  width: 100% !important;
  max-width: 100% !important;
  padding: 14px 16px !important;
  background: #FFFFFF !important;
  color: #272724 !important;
  border: 1px solid #CCCCCC !important;
  border-radius: 0 !important;
  font-family: var(--nu-font);
  font-size: var(--nu-fs-body) !important;
  line-height: var(--nu-lh-snug);
  transition: border-color var(--nu-transition);
  box-shadow: none;
  -webkit-appearance: none;
  appearance: none;
}

.gform_wrapper input:focus,
.gform_wrapper textarea:focus,
.gform_wrapper select:focus {
  outline: none;
  border-color: var(--nu-green) !important;
  box-shadow: 0 0 0 2px rgba(121, 198, 140, 0.2);
}

.gform_wrapper input::placeholder,
.gform_wrapper textarea::placeholder {
  color: #888888;
  opacity: 1;
}

/* Name field sub-inputs (Gravity Forms advanced name field) */
.gform_wrapper .ginput_complex.ginput_container_name {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}

.gform_wrapper .ginput_complex.ginput_container_name > span {
  display: block;
}

.gform_wrapper .ginput_complex label {
  display: none;  /* Rely on placeholders */
}

/* Textarea min height */
.gform_wrapper textarea {
  min-height: 120px;
  resize: vertical;
}

/* Submit button — matches the .nu-cta-link pattern (gradient underline
 * with the nu-link-hover swoosh animation). Uses --nu-fs-cta (~17→21px)
 * so it sits between body and H3 — readable as a clear submit affordance
 * without dominating the form box. Weight stays regular (400) per the
 * cta-link family.
 *
 * IMPORTANT: background-position and background-size are NOT marked
 * !important so the nu-link-hover keyframe can animate them. Only the
 * properties GF actively tries to override (color, background-color,
 * border, padding) get !important. */
.gform_wrapper .gform_footer,
.gform_wrapper .gform_page_footer {
  margin-top: var(--nu-gap) !important;
  padding: 0 !important;
}

.gform_wrapper .gform_button,
.gform_wrapper input[type="submit"].gform_button {
  display: inline-block;
  font-family: var(--nu-font) !important;
  font-weight: var(--nu-fw-regular) !important;
  font-size: var(--nu-fs-cta) !important;
  line-height: var(--nu-lh-snug) !important;
  color: var(--nu-theme-accent) !important;
  background-color: transparent !important;
  background-image: linear-gradient(45deg,
    var(--nu-gradient-green-end),
    var(--nu-gradient-green-start));
  background-position: 0 100%;
  background-size: 100% 2px;
  background-repeat: no-repeat;
  border: 0 !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  padding: 0 0 4px 0 !important;
  margin: 0 !important;
  cursor: pointer;
  width: auto !important;
  min-height: auto !important;
  transition: color var(--nu-transition), background-size 0.3s ease-in-out;
}

.gform_wrapper .gform_button:hover,
.gform_wrapper input[type="submit"].gform_button:hover {
  color: var(--nu-theme-accent-hover) !important;
  background-color: transparent !important;
  animation: nu-link-hover 0.8s ease-in-out forwards;
}

/* Validation */
.gform_wrapper .gfield_error input,
.gform_wrapper .gfield_error textarea,
.gform_wrapper .gfield_error select {
  border-color: #c3351c !important;
}

.gform_wrapper .validation_error {
  color: #c3351c;
  margin-bottom: var(--nu-gap);
  padding: 12px 16px;
  background: rgba(195, 53, 28, 0.08);
  border-left: 3px solid #c3351c;
  font-size: var(--nu-fs-small);
}

.gform_wrapper .validation_message {
  color: #c3351c;
  font-size: var(--nu-fs-small);
  margin-top: 4px;
}

/* Success confirmation message */
.gform_confirmation_message {
  padding: var(--nu-gap);
  background: rgba(121, 198, 140, 0.1);
  border-left: 3px solid var(--nu-green);
  color: var(--nu-theme-text);
}

/* ============================================================
 * Shared helpers — bullet lists, tags, pills
 * ============================================================ */

.nu-bullet-list {
  list-style: none;
  padding: 0;
  margin: var(--nu-gap-sm) 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.nu-bullet-list li {
  position: relative;
  padding-left: 26px;
  color: var(--nu-theme-text);
  line-height: var(--nu-lh-body);
}

.nu-bullet-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  border-radius: 0;
  background: var(--nu-green);
  background: linear-gradient(135deg, var(--nu-gradient-green-start, #119F6B), var(--nu-gradient-green-end, #87CC9F));
  flex-shrink: 0;
}

/* Case-study prose <ul>s pick up the brand bullet via the global
   `ul:not([class])` rule in global.css — no scoped duplication needed. */

/* Tags — pill label showing service type */
.nu-tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-bold);
  letter-spacing: var(--nu-ls-tight);
  text-transform: uppercase;
  line-height: var(--nu-lh-snug);
  white-space: nowrap;
}

.nu-tag--domestic {
  background: var(--nu-theme-accent-subtle);
  color: var(--nu-theme-accent);
  border: 1px solid rgba(121, 198, 140, 0.4);
}

.nu-tag--commercial {
  background: var(--nu-theme-accent-subtle);
  color: var(--nu-theme-accent);
  border: 1px solid rgba(17, 159, 107, 0.35);
}

.nu-tag--both {
  background: var(--nu-theme-accent-subtle);
  color: var(--nu-theme-accent);
  border: 1px solid rgba(17, 159, 107, 0.35);
}

.nu-tag--inline {
  font-size: var(--nu-fs-small);
  padding: 2px 8px;
}

/* Pill — simple location chip */
.nu-pill {
  display: inline-flex;
  align-items: center;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--nu-theme-surface, rgba(0,0,0,0.04));
  border: 1px solid var(--nu-theme-border, rgba(0,0,0,0.08));
  color: var(--nu-theme-text);
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-regular);
  line-height: var(--nu-lh-snug);
}

/* Hero bits used by new page templates */
.nu-hero__body {
  color: var(--nu-theme-text);
  margin: var(--nu-gap-sm) 0 var(--nu-gap);
}

.nu-hero__body p + p {
  margin-top: 0.8em;
}

/* ============================================================
 * Service Areas module — nationwide vs regional cards
 * ============================================================ */

.nu-service-areas__heading {
  text-align: center;
  margin: 0 0 var(--nu-gap-sm);
  color: var(--nu-theme-heading);
}

.nu-service-areas__intro {
  max-width: 720px;
  margin: 0 auto var(--nu-gap);
  text-align: center;
  color: var(--nu-theme-text);
}

.nu-service-areas__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--nu-gap);
}

@media (max-width: 900px) {
  .nu-service-areas__grid { grid-template-columns: 1fr; }
}

.nu-service-areas__card {
  position: relative;
  border: 1px solid var(--nu-theme-border, rgba(0,0,0,0.08));
  background: var(--nu-theme-card-bg, transparent);
  overflow: hidden;
  display: flex;
}

.nu-service-areas__card--nationwide::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(17, 159, 107, 0.06), rgba(135, 204, 159, 0.12));
  pointer-events: none;
}

.nu-service-areas__card-inner {
  position: relative;
  padding: calc(var(--nu-gap) * 1.1);
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap-sm);
  width: 100%;
}

.nu-service-areas__card-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px; /* breathing room between the eyebrow badge and the heading */
}

.nu-service-areas__tag {
  align-self: flex-start;
}

.nu-service-areas__card-title {
  font-size: var(--nu-fs-h3);
  margin: 0;
  color: var(--nu-theme-heading);
  line-height: var(--nu-lh-tight);
}

.nu-service-areas__card-body {
  color: var(--nu-theme-text);
  margin: 0;
  line-height: var(--nu-lh-body);
  opacity: 0.88;
}

.nu-service-areas__feature-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.nu-service-areas__feature-list li {
  position: relative;
  padding-left: 22px;
  color: var(--nu-theme-text);
  font-size: var(--nu-fs-small);
}

/* Bullet normalised to 9x9 (2026-06-03) — matches the global
   ul:not([class]) bullet treatment used everywhere else. */
.nu-service-areas__feature-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  background: linear-gradient(135deg, var(--nu-gradient-green-start, #119F6B), var(--nu-gradient-green-end, #87CC9F));
  border-radius: 2px;
}

/* Nationwide card — bullets beside the UK map. Stacks on narrow widths.
   No extra margin: spacing above/below is the card-inner flex gap
   (var(--nu-gap-sm)), standardised with the rest of the card rhythm. */
.nu-service-areas__nationwide-split {
  display: flex;
  align-items: center;
  gap: var(--nu-gap);
}
.nu-service-areas__nationwide-split .nu-service-areas__feature-list {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}
.nu-service-areas__nationwide-split .nu-service-areas__map {
  /* Explicit width: an inline SVG with only width:100% collapses to 0
     inside a flex item. A definite basis keeps it sized. */
  flex: 0 0 130px;
  width: 130px;
  max-width: 42%;
  margin: 0;
}

@media (max-width: 520px) {
  .nu-service-areas__nationwide-split {
    flex-direction: column;
    align-items: flex-start;
  }
  .nu-service-areas__nationwide-split .nu-service-areas__map {
    flex: 0 0 auto;
    width: 150px;
    max-width: 60%;
    margin: 8px auto 0;
  }
}

/* Nationwide card — UK map visual */
.nu-service-areas__map {
  width: 100%;
  max-width: 150px;
  height: auto;
  color: var(--nu-theme-accent);
  opacity: 0.85;
}

.nu-service-areas__pin {
  fill: var(--nu-green);
}

/* Regional card — primary + secondary location lists */
.nu-service-areas__label {
  display: block;
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-wide);
  color: var(--nu-theme-heading); /* distinct from the green town links */
  margin-bottom: 12px;
  font-weight: var(--nu-fw-bold);
}

.nu-service-areas__primary-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
}

.nu-service-areas__primary-list li {
  display: inline-flex;
  flex-direction: column;
  line-height: var(--nu-lh-tight);
  gap: 6px; /* breathing room between the town name + region label */
}

.nu-service-areas__primary-list a {
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  flex-direction: column;
  gap: 6px;
}

/* Linked primary town = green; hover = blue + underline. Unlinked towns
   (no page yet) keep the default white below. */
.nu-service-areas__primary-list a strong { color: var(--nu-theme-link); }
.nu-service-areas__primary-list a:hover strong {
  color: var(--nu-theme-link-hover);
  text-decoration: underline;
}

.nu-service-areas__primary-list strong {
  font-size: var(--nu-fs-body);
  color: var(--nu-theme-heading);
  font-weight: var(--nu-fw-bold);
  display: block;
  line-height: var(--nu-lh-tight);
}

.nu-service-areas__primary-list span {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-text);
  opacity: 0.65;
  line-height: var(--nu-lh-tight);
}

.nu-service-areas__pill-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

/* Full-version pills: linked town = green, hover = blue + underline;
   unlinked towns keep the default white .nu-pill colour. */
.nu-service-areas__pill-list a.nu-pill {
  text-decoration: none;
  color: var(--nu-theme-link);
  transition: border-color 150ms ease, color 150ms ease;
}

.nu-service-areas__pill-list a.nu-pill:hover {
  border-color: var(--nu-green);
  color: var(--nu-theme-link-hover);
  text-decoration: underline;
}

/* Full version stacks the postcode under the town inside the pill. */
.nu-service-areas__pill-list .nu-pill--stacked {
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  line-height: var(--nu-lh-tight);
}
.nu-service-areas__pill-list .nu-pill__town { line-height: var(--nu-lh-tight); }
.nu-service-areas__pill-list .nu-pill__postcode {
  font-size: 0.85em;
  color: var(--nu-theme-text); /* white, one step down from the town */
  line-height: var(--nu-lh-tight);
}

/* Postcode line under a primary town — white, smaller than the town but
   fully legible so it reads at a glance. */
.nu-service-areas__primary-list .nu-service-areas__postcode {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-text);
  opacity: 1;
  font-weight: var(--nu-fw-bold);
  letter-spacing: var(--nu-ls-tight);
  line-height: var(--nu-lh-tight);
}

/* Note: "We also cover" pills are single-line town text/links only.
   Postcodes are held in Site Settings for reuse on location / service
   pages, not rendered in this compact strip. */

/* Condensed variant (block toggle): drop the pill border/background/radius
   so the towns read as a plain text/link list. Used on the homepage; other
   pages keep the full pill badges. */
.nu-service-areas__pill-list--plain {
  gap: 6px 18px;
}
.nu-service-areas__pill-list--plain .nu-pill {
  border: none;
  background: none;
  border-radius: 0;
  padding: 0;
}
.nu-service-areas__pill-list--plain a.nu-pill {
  color: var(--nu-theme-link);
}
.nu-service-areas__pill-list--plain a.nu-pill:hover {
  border-color: transparent;
  color: var(--nu-theme-accent-hover);
  text-decoration: underline;
}

/* Button sits a standard gap below the content (the card-inner flex gap),
   not pushed to the card floor — keeps the bullets → button distance
   consistent instead of ballooning on the shorter card. */
.nu-service-areas__card-cta {
  margin-top: 0;
}

/* ------------------------------------------------------------
 * Data Table module — price / spec guidance table. The table
 * itself reuses .nu-data-table + .nu-table-scroll (defined in the
 * blog section below); only the section furniture lives here.
 * ---------------------------------------------------------- */
.nu-data-table-section__heading {
  margin-bottom: var(--nu-gap-sm);
}

.nu-data-table-section__intro {
  margin-bottom: var(--nu-gap);
  max-width: 68ch;
}

.nu-data-table-section__footnote {
  margin: 0;
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  max-width: 68ch;
}

/* The shared table styles carry a --nu-gap-lg bottom margin for prose
   flow; inside this section the section padding already does that job. */
.nu-data-table-section .nu-table-scroll {
  margin-bottom: var(--nu-gap);
}
.nu-data-table-section .nu-data-table {
  margin-bottom: 0;
}

/* 50/50 split: writing section + table, with a left/right toggle.
   Table keeps the shared .nu-data-table styling unchanged. */
.nu-data-table-section__split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--nu-gap-lg);
  align-items: start;
}
.nu-data-table-section__split .nu-table-scroll { margin-bottom: 0; }
.nu-data-table-section__split--table-left .nu-data-table-section__text { order: 2; }
.nu-data-table-section__text > :first-child { margin-top: 0; }
.nu-data-table-section__text > :last-child { margin-bottom: 0; }
.nu-data-table-section__text h2,
.nu-data-table-section__text h3 { margin: 0 0 var(--nu-gap-sm); line-height: var(--nu-lh-tight); }
.nu-data-table-section__text p { margin: 0 0 1em; color: var(--nu-theme-text); line-height: var(--nu-lh-body); }
@media (max-width: 820px) {
  .nu-data-table-section__split { grid-template-columns: 1fr; gap: var(--nu-gap); }
  .nu-data-table-section__split--table-left .nu-data-table-section__text { order: 0; }
}

/* Optional label above a data table (e.g. "What to expect"), with the brand
   gradient underline echoing the table's header rule. */
.nu-data-table__title {
  font-size: var(--nu-fs-h3);
  font-weight: var(--nu-fw-bold);
  line-height: var(--nu-lh-tight);
  color: var(--nu-theme-heading);
  margin: 0 0 var(--nu-gap-sm);
  padding-bottom: 12px;
  background: linear-gradient(90deg, var(--nu-gradient-green-start), var(--nu-gradient-green-end)) left bottom / 100% 2px no-repeat;
}

/* Spec Tables — several small tables in a 1/2/3-column grid. */
.nu-spec-tables__heading { margin-bottom: var(--nu-gap-sm); }
.nu-spec-tables__intro { margin-bottom: var(--nu-gap); max-width: 68ch; }
.nu-spec-tables__grid {
  display: grid;
  gap: var(--nu-gap-lg); /* bare tables need more air than padded cards do */
  grid-template-columns: 1fr;
  align-items: start;
}
.nu-spec-tables__grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.nu-spec-tables__grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) {
  .nu-spec-tables__grid--2,
  .nu-spec-tables__grid--3 { grid-template-columns: 1fr; }
}
.nu-spec-tables__title {
  font-size: var(--nu-fs-h3);
  color: var(--nu-theme-heading);
  margin: 0 0 var(--nu-gap-sm);
  line-height: var(--nu-lh-tight);
}
.nu-spec-tables__item .nu-table-scroll { margin-bottom: 0; }
.nu-spec-tables__item .nu-data-table { margin-bottom: 0; }
.nu-spec-tables__footnote {
  margin: var(--nu-gap-sm) 0 0;
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
}

/* ------------------------------------------------------------
 * Areas Covered module — single coverage block (no commercial /
 * domestic split) for location + service pages. Reuses every
 * .nu-service-areas__* list class above; only the standalone
 * spacing is defined here, because outside the two-card layout
 * there is no card-inner flex gap to separate the groups.
 * ---------------------------------------------------------- */
.nu-areas-covered .nu-service-areas__primary {
  margin-bottom: var(--nu-gap);
}

.nu-areas-covered .nu-service-areas__primary-list {
  gap: var(--nu-gap-sm) var(--nu-gap);
}

/* Services Tagged module retired 2026-04-18 — use services_list instead. */

/* ============================================================
 * Use Cases module — icon + title + text grid
 * ============================================================ */

.nu-use-cases__heading {
  text-align: center;
  margin: 0 0 var(--nu-gap-sm);
  color: var(--nu-theme-heading);
}

.nu-use-cases__intro {
  max-width: 720px;
  margin: 0 auto var(--nu-gap);
  text-align: center;
  color: var(--nu-theme-text);
}

.nu-use-cases__grid {
  display: grid;
  gap: var(--nu-gap);
  list-style: none;
  padding: 0;
  margin: 0;
}

.nu-use-cases__grid--2 { grid-template-columns: repeat(2, 1fr); }
.nu-use-cases__grid--3 { grid-template-columns: repeat(3, 1fr); }
.nu-use-cases__grid--4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 900px) {
  .nu-use-cases__grid--3,
  .nu-use-cases__grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .nu-use-cases__grid--2,
  .nu-use-cases__grid--3,
  .nu-use-cases__grid--4 { grid-template-columns: 1fr; }
}

/* Eligibility cards: title + optional status pill + text. No icons.
 * Surface card with a gradient left-bar revealed on hover (site pattern). */
.nu-use-cases__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--nu-theme-card-bg);
  border: 1px solid var(--nu-theme-border);
  padding: 28px 26px 26px;
  text-align: left;
  overflow: hidden;
  transition: border-color var(--nu-transition), box-shadow var(--nu-transition);
}
.nu-use-cases__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: linear-gradient(135deg, var(--nu-gradient-green-start), var(--nu-gradient-green-end));
  opacity: 0;
  transition: opacity var(--nu-transition);
}
.nu-use-cases__item:hover {
  border-color: var(--nu-theme-input-border);
  box-shadow: var(--nu-glow-hover);
}
.nu-use-cases__item:hover::before { opacity: 1; }

.nu-use-cases__title {
  font-size: var(--nu-fs-h3);
  font-weight: var(--nu-fw-bold);
  line-height: var(--nu-lh-tight);
  margin: 0;
  color: var(--nu-theme-heading);
}

/* Status pill — the "when / legal status", surfaced above the text so it is
 * scannable and quotable. Pills are the one place a non-zero radius is used. */
.nu-use-cases__pill {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  font-size: 0.72rem;
  font-weight: var(--nu-fw-bold);
  letter-spacing: 0.03em;
  text-transform: uppercase;
  line-height: 1.3;
  padding: 5px 12px;
  border-radius: 999px;
}
.nu-use-cases__pill--law {
  background: var(--nu-theme-accent-subtle);
  color: var(--nu-theme-accent);
  border: 1px solid rgba(121, 198, 140, 0.35);
}
.nu-use-cases__pill--recommended {
  background: transparent;
  color: var(--nu-theme-muted);
  border: 1px solid var(--nu-theme-input-border);
}

.nu-use-cases__text {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  margin: 0;
  line-height: var(--nu-lh-body);
}

/* ============================================================
 * Clients Row module — static logo strip
 * ============================================================ */

.nu-clients-row__heading {
  text-align: center;
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-wide);
  color: var(--nu-theme-text);
  opacity: 0.7;
  margin: 0 0 var(--nu-gap);
  font-weight: var(--nu-fw-bold);
}

.nu-clients-row__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: calc(var(--nu-gap) * 1.5);
  list-style: none;
  padding: 0;
  margin: 0;
}

.nu-clients-row__item {
  display: flex;
  align-items: center;
  justify-content: center;
}

.nu-clients-row__item img {
  max-height: 56px;
  width: auto;
  max-width: 160px;
  object-fit: contain;
  transition: opacity 200ms ease, filter 200ms ease;
}

.nu-clients-row--greyscale .nu-clients-row__item img {
  filter: grayscale(100%);
  opacity: 0.65;
}

.nu-clients-row--greyscale .nu-clients-row__item img:hover {
  filter: grayscale(0);
  opacity: 1;
}

@media (max-width: 700px) {
  .nu-clients-row__list { gap: var(--nu-gap); }
  .nu-clients-row__item img { max-height: 40px; max-width: 120px; }
}

/* ============================================================
 * Case Study — hero contents nav + meta strip + lede
 * ============================================================ */

.nu-case-study__breadcrumb {
  font-size: var(--nu-fs-small);
  margin: 0 0 var(--nu-gap-sm);
  color: var(--nu-theme-text);
  opacity: 0.75;
}

.nu-case-study__breadcrumb a {
  color: var(--nu-theme-accent);
  text-decoration: none;
}

.nu-case-study__breadcrumb a:hover { text-decoration: underline; }

.nu-case-study__contents {
  margin-top: var(--nu-gap);
  padding: var(--nu-gap-sm) var(--nu-gap);
  border: 1px solid var(--nu-theme-border, rgba(0,0,0,0.08));
  background: var(--nu-theme-surface, rgba(0,0,0,0.02));
}

/* When nested inside a .nu-hero--box-shadow panel (which already uses the
   surface token), drop the extra tint and border so it doesn't look like
   two boxes stacked. A subtle top divider is enough. */
.nu-hero--box-shadow .nu-case-study__contents {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--nu-theme-border);
  padding: var(--nu-gap) 0 0;
  margin-top: var(--nu-gap);
}

/* ────────────────────────────────────────────────────────────
 * Case study hero — single-image gallery override.
 *
 * The default .nu-hero__gallery-grid is a 2×2 designed for 2 squares +
 * 1 wide image. Case studies have exactly ONE featured image that
 * should fill the full right column.
 * ──────────────────────────────────────────────────────────── */
.nu-case-study__hero .nu-hero__gallery-grid {
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
  height: 100%;
}

.nu-case-study__hero .nu-hero__gallery-item,
.nu-case-study__hero .nu-hero__gallery-item--wide {
  grid-column: 1;
}

.nu-case-study__hero .nu-hero__gallery-item img,
.nu-case-study__hero .nu-hero__gallery-item--wide img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

/* Align top of gallery with top of text column inside the hero panel */
.nu-case-study__hero .nu-hero__inner {
  align-items: stretch;
}

/* Intro text (ACF: intro_text) sits between H1 and contents nav.
   Style it as a hero subheading — readable, slightly muted. */
.nu-case-study__intro-text {
  font-size: var(--nu-fs-body);
  color: var(--nu-theme-muted);
  margin: 0 0 var(--nu-gap-sm);
  line-height: var(--nu-lh-body);
}

.nu-case-study__intro-text p:last-child { margin-bottom: 0; }

.nu-case-study__contents-label {
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  color: var(--nu-theme-accent);
  margin: 0 0 10px;
  font-weight: var(--nu-fw-bold);
}

.nu-case-study__contents-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.nu-case-study__contents-list li {
  counter-increment: contents;
}

.nu-case-study__contents-list {
  counter-reset: contents;
}

.nu-case-study__contents-list a {
  display: flex;
  align-items: baseline;
  gap: 10px;
  color: var(--nu-theme-text);
  text-decoration: none;
  font-size: var(--nu-fs-small);
  padding: 4px 0;
  transition: color 150ms ease;
}

.nu-case-study__contents-list a::before {
  content: counter(contents, decimal-leading-zero);
  color: var(--nu-theme-accent);
  font-weight: var(--nu-fw-bold);
  font-size: var(--nu-fs-small);
  min-width: 22px;
}

.nu-case-study__contents-list a:hover {
  color: var(--nu-theme-accent);
}

/* Wrapper — narrow reading column for the body sections */
.nu-case-study__body-wrap {
  max-width: 820px;
  margin-left: auto;
  margin-right: auto;
}

/* .nu-case-study__intro-text is defined earlier (nested inside the hero
   panel section) — don't duplicate it here. */

/* Overview / "Client and Project Overview" — larger intro content */
.nu-case-study__lede {
  font-size: var(--nu-fs-body);
  line-height: var(--nu-lh-body);
  color: var(--nu-theme-heading);
  margin: 0 0 var(--nu-gap);
  padding-bottom: var(--nu-gap);
  border-bottom: 1px solid var(--nu-theme-border);
}

.nu-case-study__lede p:last-child { margin-bottom: 0; }

/* Meta strip — 4 columns on desktop, collapses to 2 then 1 */
.nu-case-study__meta {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--nu-gap-sm) var(--nu-gap);
  margin: 0 0 var(--nu-gap-lg);
  padding: var(--nu-gap) 0;
  border-top: 1px solid var(--nu-theme-border);
  border-bottom: 1px solid var(--nu-theme-border);
}

@media (max-width: 900px) {
  .nu-case-study__meta { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 500px) {
  .nu-case-study__meta { grid-template-columns: 1fr; }
}

.nu-case-study__meta-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.nu-case-study__meta dt {
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  color: var(--nu-theme-accent);
  font-weight: var(--nu-fw-bold);
  margin: 0;
}

.nu-case-study__meta dd {
  margin: 0;
  color: var(--nu-theme-heading);
  font-weight: var(--nu-fw-regular);
  font-size: var(--nu-fs-body);
}

/* ────────────────────────────────────────────────────────────
 * Case study body prose (Flexible Content output)
 * ──────────────────────────────────────────────────────────── */

/* H2 gets the gradient-bar treatment — matches the rest of the design system
   (accent left-bar instead of a solid border). H3 falls through to the
   global --nu-fs-h3 token. */
/* Per design hierarchy (2026-06-03): vertical gradient bars are hero
   only. Case-study H2 now uses a short 2px gradient underline — same
   family as .nu-cta-link, used as a heading accent. */
.nu-case-study__body h2 {
  position: relative;
  display: inline-block;
  margin: 48px 0 18px;
  padding-bottom: 8px;
  font-size: var(--nu-fs-h2);
  color: var(--nu-theme-heading);
}

.nu-case-study__body h2::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 64px;
  height: 2px;
  background: linear-gradient(90deg, var(--nu-gradient-green-start), var(--nu-gradient-green-end));
}

.nu-case-study__body > *:first-child,
.nu-case-study__body h2:first-child { margin-top: 0; }

.nu-case-study__body h3 {
  font-size: var(--nu-fs-h3);
  color: var(--nu-theme-heading);
  margin: 32px 0 12px;
}

.nu-case-study__prose p {
  color: var(--nu-theme-text);
  line-height: var(--nu-lh-body);
  margin-bottom: var(--nu-gap);
}

.nu-case-study__prose p:last-child { margin-bottom: 0; }

/* ────────────────────────────────────────────────────────────
 * Case study gallery — full-width edge-to-edge inside the body column
 * ──────────────────────────────────────────────────────────── */
.nu-case-study__gallery {
  display: grid;
  gap: 9px;
  margin: 40px 0;
}

.nu-case-study__gallery--cols-1 { grid-template-columns: 1fr; }
.nu-case-study__gallery--cols-2 { grid-template-columns: repeat(2, 1fr); }
.nu-case-study__gallery--cols-3 { grid-template-columns: repeat(3, 1fr); }
.nu-case-study__gallery--cols-4 { grid-template-columns: repeat(4, 1fr); }

@media (max-width: 767px) {
  .nu-case-study__gallery--cols-3,
  .nu-case-study__gallery--cols-4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 500px) {
  .nu-case-study__gallery--cols-2,
  .nu-case-study__gallery--cols-3,
  .nu-case-study__gallery--cols-4 { grid-template-columns: 1fr; }
}

.nu-case-study__gallery-item {
  margin: 0;
  overflow: hidden;
}

.nu-case-study__gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--nu-transition-slow);
}

/* Lightbox trigger wrapping each case-study gallery image. */
.nu-case-study__gallery-link {
  display: block;
  height: 100%;
  cursor: zoom-in;
}

.nu-case-study__gallery-link:focus-visible {
  outline: 2px solid var(--nu-theme-accent);
  outline-offset: 2px;
}

/* .nu-case-study gallery image scale on hover removed 2026-06-06 — no-motion hover rule. */

/* Aspect ratio variants */
.nu-case-study__gallery--aspect-square    .nu-case-study__gallery-item img { aspect-ratio: 1 / 1; }
.nu-case-study__gallery--aspect-landscape .nu-case-study__gallery-item img { aspect-ratio: 4 / 3; }
.nu-case-study__gallery--aspect-wide      .nu-case-study__gallery-item img { aspect-ratio: 16 / 9; }
.nu-case-study__gallery--aspect-auto      .nu-case-study__gallery-item img { aspect-ratio: auto; height: auto; }

/* ────────────────────────────────────────────────────────────
 * Case study pull-quote / blockquote component
 * Flex content `quote` layout renders as this component.
 * ──────────────────────────────────────────────────────────── */
.nu-blockquote {
  margin: var(--nu-gap-lg) 0;
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border-left: 3px solid var(--nu-green);
}

.nu-blockquote__text {
  font-style: italic;
  font-size: var(--nu-fs-body);
  line-height: var(--nu-lh-body);
  color: var(--nu-theme-heading);
  margin: 0 0 12px;
}

.nu-blockquote__attribution {
  font-weight: var(--nu-fw-bold);
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-accent);
  margin: 0;
}

/* ────────────────────────────────────────────────────────────
 * Featured image in the hero gallery column
 * ──────────────────────────────────────────────────────────── */
.nu-case-study__featured-img {
  width: 100%;
  height: auto;
  display: block;
}

/* ==========================================================================
   Shared utility — section eyebrow
   Used by any module that wants the small uppercase accent label above an H2.
   ========================================================================== */
.nu-eyebrow {
  display: block;
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-wide);
  color: var(--nu-theme-accent);
  font-weight: var(--nu-fw-bold);
  margin-bottom: 12px;
}

/* ==========================================================================
   19. FAQ + Reviews + Contact (combined page-builder layout)
   Left column: FAQ accordion. Right column stacked: reviews + form.
   ========================================================================== */

.nu-faq-review-contact__header {
  text-align: center;
  max-width: 900px;
  margin: 0 auto var(--nu-gap-lg);
}

.nu-faq-review-contact__heading {
  margin: 0 0 var(--nu-gap-sm);
  color: var(--nu-theme-heading);
}

.nu-faq-review-contact__intro {
  margin: 0;
  color: var(--nu-theme-muted);
}

.nu-faq-review-contact__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--nu-gap);
  align-items: start;
}

@media (max-width: 900px) {
  .nu-faq-review-contact__grid { grid-template-columns: 1fr; }
}

.nu-faq-review-contact__left {
  min-width: 0;
}

/* Right column — reviews on top, contact form below. */
.nu-faq-review-contact__right {
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap);
  min-width: 0;
}

.nu-faq-review-contact__reviews {
  /* Let the plugin's own card styles do the work. Just make sure the
     container doesn't clip the plugin's shadows or outline. */
  min-width: 0;
}

/* Contact card — matches the surface-panel language used by the hero box */
.nu-faq-review-contact__contact {
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
}

.nu-faq-review-contact__contact-heading {
  margin: 0 0 8px;
  color: var(--nu-theme-heading);
  font-size: var(--nu-fs-h3);
}

.nu-faq-review-contact__contact-intro {
  margin: 0 0 var(--nu-gap-sm);
  color: var(--nu-theme-muted);
  font-size: var(--nu-fs-small);
}

/* When GF renders inside this card, tighten its top spacing a touch so the
   intro paragraph doesn't double-gap with the first form field. */
.nu-faq-review-contact__contact .gform_wrapper {
  margin-top: 0;
}

@media (max-width: 600px) {
  .nu-faq-review-contact__contact { padding: var(--nu-gap-sm); }
}

/* --------------------------------------------------------------------------
   19. Lightbox (conditionally loaded via assets/js/lightbox.js)
   -------------------------------------------------------------------------- */

.nu-lightbox {
  position: fixed;
  inset: 0;
  background: rgba(15, 24, 32, 0.92);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 200;
  padding: 40px;
}

.nu-lightbox.is-open {
  display: flex;
}

.nu-lightbox__frame {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.nu-lightbox__img {
  max-width: 100%;
  max-height: 85vh;
  object-fit: contain;
  display: block;
}

.nu-lightbox__caption {
  color: var(--nu-white);
  font-size: var(--nu-fs-small);
  text-align: center;
  min-height: 1em;
}

.nu-lightbox__close,
.nu-lightbox__prev,
.nu-lightbox__next {
  position: absolute;
  background: transparent;
  color: var(--nu-white);
  border: 0;
  font-size: 2rem;
  cursor: pointer;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: color var(--nu-transition);
}

.nu-lightbox__close:hover,
.nu-lightbox__prev:hover,
.nu-lightbox__next:hover {
  color: var(--nu-green);
}

.nu-lightbox__close { top: 16px; right: 16px; }
.nu-lightbox__prev  { left: 16px;  top: 50%; transform: translateY(-50%); }
.nu-lightbox__next  { right: 16px; top: 50%; transform: translateY(-50%); }

@media (max-width: 600px) {
  .nu-lightbox { padding: 20px; }
  .nu-lightbox__close,
  .nu-lightbox__prev,
  .nu-lightbox__next { font-size: 1.5rem; }
}


/* ==========================================================================
   20. Destination Cards
   --------------------------------------------------------------------------
   Prominent 2-3 card row used to route visitors to landing pages
   (Commercial / Domestic / Mechanical / Fire & Security). Each card is
   the click target, wraps eyebrow + heading + body + optional bullets +
   visible CTA affordance. Visual signature: 6px gradient left bar +
   surface tint + glow shadow + slight lift on hover.
   ========================================================================== */

.nu-destination-cards__heading {
  text-align: center;
  margin-bottom: var(--nu-gap-sm);
}

.nu-destination-cards__intro {
  text-align: center;
  margin: 0 auto var(--nu-gap-lg);
  max-width: 720px;
  color: var(--nu-theme-muted);
}

.nu-destination-cards__grid {
  display: grid;
  gap: var(--nu-gap);
}

.nu-destination-cards__grid--2 { grid-template-columns: repeat(2, 1fr); }
.nu-destination-cards__grid--3 { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 900px) {
  .nu-destination-cards__grid--2,
  .nu-destination-cards__grid--3 { grid-template-columns: 1fr; }
}

.nu-destination-cards__card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap-sm);
  padding: 50px 33px;
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  text-decoration: none;
  color: var(--nu-theme-text);
  transition: box-shadow var(--nu-transition),
              border-color var(--nu-transition),
              transform var(--nu-transition);
}

/* Per design hierarchy (2026-06-03): the 6px vertical gradient bar is
   reserved for the hero. Destination cards now use a subtle gradient
   tint overlay that fades in on hover — same gradient family, distinct
   mechanic. The "--bar" modifier name is preserved so existing ACF data
   keeps working; the visual treatment is the new tint. */
.nu-destination-cards__card--bar::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(135deg,
                              rgba(17, 159, 107, 0.10),
                              rgba(135, 204, 159, 0.06));
  opacity: 0;
  transition: opacity var(--nu-transition);
}

a.nu-destination-cards__card--bar:hover::after { opacity: 1; }

a.nu-destination-cards__card:hover {
  box-shadow: var(--nu-glow-hover);
}
/* Glow-only hover per HIERARCHY-AUDIT §12 (boxed-hover rule, 2026-06-06). */

/* Suppress cascade-underline from global a:hover. Hover affordance is
   already carried by border colour + lift + glow + arrow translate. */
a.nu-destination-cards__card:hover,
a.nu-destination-cards__card:hover * {
  text-decoration: none;
}

.nu-destination-cards__eyebrow {
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-wide);
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-accent);
}

.nu-destination-cards__card-heading {
  font-size: var(--nu-fs-h3);
  margin: 0;
  color: var(--nu-theme-heading);
}

.nu-destination-cards__body {
  color: var(--nu-theme-text);
}

.nu-destination-cards__body p {
  margin: 0;
}

.nu-destination-cards__bullets {
  list-style: none;
  padding-left: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.nu-destination-cards__bullets li {
  position: relative;
  padding-left: 22px;
  line-height: var(--nu-lh-body);
}

.nu-destination-cards__bullets li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  background: linear-gradient(135deg,
                              var(--nu-gradient-green-start),
                              var(--nu-gradient-green-end));
}

.nu-destination-cards__cta {
  margin-top: auto;
  padding-top: var(--nu-gap-sm);
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-accent);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.nu-destination-cards__cta-arrow {
  display: inline-flex;
  align-items: center;
}
/* No translation on hover — see HIERARCHY-AUDIT §9 (no-arrow-motion rule). */


/* ==========================================================================
   21. Service Card Grid
   --------------------------------------------------------------------------
   Compact banner-style cards used to list individual service pages.
   Each card is the click target, heading + short description on the
   left, arrow on the right. Visual signature: 4px gradient left bar +
   surface tint + arrow animates on hover.
   ========================================================================== */

.nu-service-cards__heading {
  text-align: center;
  margin-bottom: var(--nu-gap-sm);
}

.nu-service-cards__intro {
  text-align: center;
  margin: 0 auto var(--nu-gap-lg);
  max-width: 720px;
  color: var(--nu-theme-muted);
}

/* CSS-columns masonry. Cards have varying body heights now that the
 * description is a WYSIWYG (bullets / paragraphs / mixed), so a fixed
 * row-grid would create awkward empty space below shorter cards. CSS
 * columns flow each card top-to-bottom inside its column, packed
 * naturally with no JS. Reading order is column-major (top-left, then
 * down, then next column) which is acceptable for service listings.
 *
 * --column-fill: balance distributes content across the columns evenly. */
.nu-service-cards__grid {
  column-gap: var(--nu-gap);
  column-fill: balance;
}

.nu-service-cards__grid--2 { column-count: 2; }
.nu-service-cards__grid--3 { column-count: 3; }
.nu-service-cards__grid--4 { column-count: 4; }

/* Each card is the column-fragment unit. break-inside prevents a card
 * splitting across a column boundary. The display + width pair ensures
 * the card fills its column width inside the column-flow context. */
.nu-service-cards__card {
  /* Masonry: each card is the column-flow unit. break-inside avoids
   * a card splitting across columns. margin-bottom is the gap between
   * stacked cards inside a column (column-gap handles the horizontal). */
  break-inside: avoid;
  width: 100%;
  margin-bottom: var(--nu-gap);

  /* Card chrome */
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: var(--nu-gap-sm);
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  text-decoration: none;
  color: var(--nu-theme-text);
  transition: box-shadow var(--nu-transition),
              border-color var(--nu-transition),
              transform var(--nu-transition);
}

@media (max-width: 1024px) {
  .nu-service-cards__grid--3,
  .nu-service-cards__grid--4 { column-count: 2; }
}

@media (max-width: 600px) {
  .nu-service-cards__grid--2,
  .nu-service-cards__grid--3,
  .nu-service-cards__grid--4 { column-count: 1; }
}

/* No gradient left bar on service cards — cleaner look. Hover
   affordance comes from border colour + lift + glow + arrow translate. */

a.nu-service-cards__card:hover {
  box-shadow: var(--nu-glow-hover);
}
/* Glow-only hover per HIERARCHY-AUDIT §12 (boxed-hover rule, 2026-06-06). */

/* Suppress cascade-underline from global a:hover. */
a.nu-service-cards__card:hover,
a.nu-service-cards__card:hover * {
  text-decoration: none;
}

.nu-service-cards__card-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}

.nu-service-cards__card-heading {
  font-size: var(--nu-fs-h3);
  font-weight: var(--nu-fw-bold);
  margin: 0;
  color: var(--nu-theme-heading);
  line-height: var(--nu-lh-tight);
}

/* Card description is now a WYSIWYG container — accepts paragraphs,
 * bullets, headings. The global `ul:not([class])` rule supplies the
 * brand 9×9 gradient-square bullet automatically (no scoped override
 * needed). First/last child margin reset keeps the card body flush at
 * the top and bottom of the body column. */
.nu-service-cards__card-description {
  color: var(--nu-theme-muted);
  font-size: var(--nu-fs-body);
  line-height: var(--nu-lh-body);
}

.nu-service-cards__card-description > *:first-child { margin-top: 0; }
.nu-service-cards__card-description > *:last-child { margin-bottom: 0; }

.nu-service-cards__card-description p {
  margin: 0 0 var(--nu-gap-sm);
}

.nu-service-cards__card-description ul {
  /* Inherits brand-bullet styling from global `ul:not([class])`.
   * Keep the description colour for the list rows. */
  color: var(--nu-theme-muted);
}

.nu-service-cards__arrow {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  margin-top: 6px;
  color: var(--nu-theme-accent);
  line-height: 1;
}
/* No translation on hover — see HIERARCHY-AUDIT §9 (no-arrow-motion rule).
 * Hover affordance is the card lift + border tint + glow only. */


/* ==========================================================================
   22. Location Overview
   --------------------------------------------------------------------------
   Designed introduction block for town and location pages.
   Two layout modes:
     --stacked  : heading and intro above the services grid (default)
     --split    : heading and intro on the left, services on the right
   Two box styles:
     --boxed    : surface card + 6px gradient left bar (design signature)
     --plain    : no background, no border, no bar (inline content)
   ========================================================================== */

.nu-location-overview__card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap);
}

/* ------ Boxed style ------
   Surface card with border + shadow. No gradient bar (hero exclusive).
   Padding aligned to the site's boxed-card standard: --nu-gap (33px)
   at desktop, tightening to --nu-gap-sm at ≤600px via the shared
   card-padding rule further down. Previously used a hardcoded 50px
   that put this block visually apart from every other boxed card. */
.nu-location-overview--boxed .nu-location-overview__card {
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
}

/* Per design hierarchy (2026-06-03): the 6px vertical gradient bar is
   reserved for the hero. Boxed location_overview now relies on the
   surface card + 1px border + glow shadow alone — quieter than the
   hero, distinct from the destination-card hover tint. */

/* ------ Plain style ------ */
.nu-location-overview--plain .nu-location-overview__card {
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}

/* ------ Split layout ------
   Heading + intro on the left, services on the right. Falls back to
   single column at the site's canonical tablet breakpoint. */
.nu-location-overview--split .nu-location-overview__card {
  flex-direction: row;
  align-items: flex-start;
  gap: var(--nu-gap-lg);
}

.nu-location-overview--split .nu-location-overview__text {
  flex: 1;
  min-width: 0;
}

.nu-location-overview--split .nu-location-overview__services-col {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap-sm);
}

@media (max-width: 1024px) {
  .nu-location-overview--split .nu-location-overview__card {
    flex-direction: column;
    gap: var(--nu-gap);
  }
}

/* Standardised vertical rhythm: heading → intro → card-heading all sit a
   single --nu-gap-sm (20px) apart, instead of ad-hoc margins. */
.nu-location-overview__text {
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap-sm);
}

.nu-location-overview__heading {
  font-size: var(--nu-fs-h2);
  color: var(--nu-theme-heading);
  margin: 0;
  line-height: var(--nu-lh-tight);
}

.nu-location-overview__intro {
  color: var(--nu-theme-text);
}

.nu-location-overview__intro p {
  margin: 0 0 1em;
}

.nu-location-overview__intro p:last-child { margin-bottom: 0; }

.nu-location-overview__services-heading {
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-wide);
  color: var(--nu-theme-accent);
  margin: 0; /* spacing handled by the __text flex gap / card gap */
}

/* Bigger right chevron on the Overview Cards (this is where the client wants
   the larger arrow). Scoped so the Services page service cards are unaffected. */
.nu-location-overview .nu-service-cards__arrow {
  width: 34px;
  height: 34px;
}
.nu-location-overview .nu-service-cards__arrow .nu-chevron {
  width: 11px;
  height: 11px;
  border-right-width: 2px;
  border-bottom-width: 2px;
}

/* Services inside location_overview now render with the shared Service
   Cards component (.nu-service-cards__*) — see section 21. The old compact
   row treatment (.nu-location-overview__services / __service-card /
   __service-heading / __service-arrow) was retired 2026-08-05. */
/* No translation on hover — see HIERARCHY-AUDIT §9 (no-arrow-motion rule). */


/* Section 23 (Contact Form — Split layout) deleted 2026-06-06.
 * Was a duplicate of Section 9 rules and was winning the cascade with
 * a bloated `font-size: clamp(1.4rem, 1.2rem + 0.8vw, 1.8rem)` on the
 * phone link (~28.8px). Canonical contact-form rules live in Section 9
 * only. */


/* ==========================================================================
   Mobile box-padding override (added 2026-06-06)
   --------------------------------------------------------------------------
   At default the card-internal padding is var(--nu-gap) / var(--nu-pad-sm)
   = 33px, which on a 375-500px viewport leaves the content area at only
   84-86% of the card width. Drop to 20px (--nu-gap-sm) below 600px so
   content gets ~90%+ width. Applied uniformly so every card type pulls
   the same tighter rhythm.
   ========================================================================== */
@media (max-width: 600px) {
  .nu-hero--box-shadow .nu-hero__inner,
  .nu-hero.nu-style--gradient .nu-hero__inner,
  .nu-accent-box,
  .nu-feature-columns__col,
  .nu-service-cards__card,
  .nu-reviews-bento .nu-reviews-bento__card,
  .nu-reviews-justified .egr-review,
  .nu-contact-form--split .nu-contact-form__form,
  .nu-blockquote,
  .nu-card,
  .nu-faq-review-contact__contact,
  .nu-location-overview--boxed .nu-location-overview__card,
  .nu-service-areas__card-inner,
  .gform_confirmation_message {
    padding: var(--nu-gap-sm);  /* 20px */
  }
}


/* ==========================================================================
   Section background + boxed modifier (added 2026-06-06)
   --------------------------------------------------------------------------
   Optional ACF controls on 9 layouts (hero, content_block, cta_banner,
   partner_feature, two_column_content, use_cases, service_areas,
   contact_form, faq_review_contact) let editors:
     1. Apply a section-level background colour (5 options).
     2. Wrap section content in a "card" via .nu-section--boxed.
   These are independent dimensions — any combination is valid.
   ========================================================================== */

/* Background styles applied to <section.nu-section> */
.nu-section.nu-bg--none {
  background: transparent;
}

.nu-section.nu-bg--surface {
  background: var(--nu-theme-surface);
}

.nu-section.nu-bg--surface-alt {
  background: var(--nu-theme-bg-var-1);
}

.nu-section.nu-bg--accent-soft {
  background: linear-gradient(135deg,
    var(--nu-theme-accent-subtle) 0%,
    transparent 60%);
}

.nu-section.nu-bg--gradient {
  background: linear-gradient(135deg,
    var(--nu-gradient-green-start),
    var(--nu-gradient-green-end));
  color: var(--nu-white);
}

.nu-section.nu-bg--gradient h1,
.nu-section.nu-bg--gradient h2,
.nu-section.nu-bg--gradient h3,
.nu-section.nu-bg--gradient h4 {
  color: var(--nu-white);
}

/* Boxed modifier — turns the .nu-container into a Tier-2 card.
 * Stays inside the same 1333px max-width so the rhythm is unchanged;
 * the visual difference is the surface tint + border + glow + extra
 * internal padding. */
.nu-section--boxed > .nu-container {
  background: var(--nu-theme-surface);
  border: 1px solid var(--nu-theme-border);
  box-shadow: var(--nu-glow);
  padding-top: var(--nu-pad-sm);
  padding-bottom: var(--nu-pad-sm);
  transition: box-shadow var(--nu-transition);
}

/* When the section also has a bg, narrow the boxed container a touch
 * so the underlying section bg is visible around it (otherwise the
 * boxed card "eats" the entire band visually). */
.nu-section.nu-bg--surface.nu-section--boxed > .nu-container,
.nu-section.nu-bg--surface-alt.nu-section--boxed > .nu-container,
.nu-section.nu-bg--accent-soft.nu-section--boxed > .nu-container,
.nu-section.nu-bg--gradient.nu-section--boxed > .nu-container {
  background: var(--nu-theme-bg);
  max-width: 1100px;
}

/* Mobile — reduce the boxed container's internal padding for the same
 * reason as the existing card-padding rule above (content gets squashed
 * at 33px on a 375px viewport). */
@media (max-width: 600px) {
  .nu-section--boxed > .nu-container {
    padding-top: var(--nu-gap-sm);
    padding-bottom: var(--nu-gap-sm);
  }
}

/* ==========================================================================
   24. Case Study — Products & Materials + Gallery heading
   Products render as a responsive auto-fit grid of clean spec cards below
   the meta strip. No gradient left bar (used only on heroes). Brand sits
   on top in the accent colour; product/model sits underneath in body text.
   ========================================================================== */

.nu-case-study__products-heading,
.nu-case-study__gallery-heading {
  font-size: var(--nu-fs-h3);
  margin: 0 0 var(--nu-gap);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-tight);
  color: var(--nu-theme-muted);
  font-weight: var(--nu-fw-bold);
}

/* Products & Materials — Nulectrics standard bullet-list pattern
 * (9x9 gradient square bullet, brand bold, product muted after). */
.nu-case-study__products {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.nu-case-study__products li::before { display: none; } /* neutralise generic ul::before */

.nu-case-study__product {
  position: relative;
  padding: 0 0 0 22px;
  line-height: var(--nu-lh-body);
  background: transparent;
  border: none;
}
.nu-case-study__product::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  background: linear-gradient(135deg,
    var(--nu-gradient-green-start),
    var(--nu-gradient-green-end));
}
.nu-case-study__product:hover { box-shadow: none; }

.nu-case-study__product-brand {
  font-weight: var(--nu-fw-bold);
  color: var(--nu-theme-heading);
  margin-right: 6px;
}
.nu-case-study__product-name {
  color: var(--nu-theme-muted);
}

/* ------------------------------------------------------------------
   20. Blog posts (single.php)
   Article layout, author trust block, related posts, GEO components.
   ------------------------------------------------------------------ */

.nu-container--narrow {
  max-width: 902px;
}

/* --- Two-column post layout: sticky TOC (30%) + article body (70%).
   Width = case-study body (820px) + 15% = 943px, LEFT-aligned to the container
   gutter (no auto margins). The header above is uncapped — it spans the normal
   container width like any other page hero. --- */
.nu-post__layout {
  max-width: 943px;
  display: grid;
  grid-template-columns: 30% 1fr;
  gap: var(--nu-gap-lg);
  /* No align-items:start — the TOC column must stretch to full row height so
     the sticky nav inside it has travel room. (start shrinks it to content
     height and sticky never moves.) */
  align-items: stretch;
}
.nu-post__toc {
  position: sticky;
  top: calc(var(--nu-header-h) + 20px);
  max-height: calc(100vh - var(--nu-header-h) - 40px);
  overflow-y: auto;
}
.nu-post__toc-label {
  font-size: var(--nu-fs-small);
  font-weight: var(--nu-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  color: var(--nu-theme-accent);
  margin: 0 0 var(--nu-gap-sm);
}
.nu-post__toc-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.nu-post__toc-item {
  margin: 0;
}
.nu-post__toc-link {
  display: block;
  padding: 6px 0 6px 14px;
  border-left: 2px solid var(--nu-theme-border);
  color: var(--nu-theme-muted);
  text-decoration: none;
  font-size: var(--nu-fs-small);
  line-height: var(--nu-lh-snug);
  transition: color var(--nu-transition), border-color var(--nu-transition);
}
.nu-post__toc-item--h3 .nu-post__toc-link {
  padding-left: 26px;
  font-size: calc(var(--nu-fs-small) * 0.95);
}
.nu-post__toc-link:hover {
  color: var(--nu-theme-accent);
}
.nu-post__toc-link.is-active {
  color: var(--nu-theme-accent);
  border-left-color: var(--nu-theme-accent);
  font-weight: var(--nu-fw-bold);
}
/* Offset in-page anchor jumps for the sticky header. */
.nu-post__body h2,
.nu-post__body h3 {
  scroll-margin-top: calc(var(--nu-header-h) + 24px);
}
@media (max-width: 900px) {
  .nu-post__layout {
    grid-template-columns: 1fr;
    gap: var(--nu-gap);
  }
  .nu-post__toc {
    position: static;
    max-height: none;
    overflow: visible;
    padding: var(--nu-gap-sm) 0;
    border-top: 1px solid var(--nu-theme-border);
    border-bottom: 1px solid var(--nu-theme-border);
  }
}

/* --- Blog archive: card grid + pagination --- */
.nu-blog-archive__header {
  margin-bottom: 0;
}
.nu-blog-archive__title {
  margin: 0 0 var(--nu-gap-sm);
}
.nu-blog-archive__intro {
  color: var(--nu-theme-muted);
  max-width: 720px;
}
.nu-post-card__excerpt {
  color: var(--nu-theme-muted);
  font-size: var(--nu-fs-small);
  line-height: var(--nu-lh-body);
  margin: 4px 0 0;
}
.nu-pagination {
  margin-top: var(--nu-gap-lg);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--nu-gap-sm);
}
.nu-pagination__info {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  letter-spacing: var(--nu-ls-tight);
  margin: 0;
}
.nu-pagination__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: center;
}
.nu-pagination .page-numbers {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 44px;
  min-height: 44px;
  padding: 0 14px;
  border: 2px solid var(--nu-theme-border);
  color: var(--nu-theme-text);
  text-decoration: none;
  font-weight: var(--nu-fw-bold);
  transition: background-color var(--nu-transition), color var(--nu-transition), border-color var(--nu-transition);
}
.nu-pagination a.page-numbers:hover {
  border-color: var(--nu-theme-accent);
  color: var(--nu-theme-accent);
  background: var(--nu-theme-surface);
}
.nu-pagination .page-numbers.current {
  background: var(--nu-green);
  border-color: var(--nu-theme-accent);
  color: var(--nu-bg);
}
.nu-pagination .page-numbers.dots {
  border-color: transparent;
  min-width: 0;
  padding: 0 4px;
}
@media (max-width: 500px) {
  /* Prev/Next collapse to just the arrow on small screens. */
  .nu-pagination__label { display: none; }
}

/* --- Post header (sits in its own gradient band; band padding handles spacing) --- */
.nu-post__header {
  margin-bottom: 0;
}
.nu-post__breadcrumb {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  margin-bottom: var(--nu-gap-sm);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.nu-post__breadcrumb a {
  color: var(--nu-theme-muted);
  text-decoration: none;
}
.nu-post__breadcrumb a:hover {
  color: var(--nu-theme-accent);
}
.nu-post__meta-top {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: var(--nu-gap-sm);
}
.nu-post__title {
  margin: 0 0 var(--nu-gap-sm);
}
.nu-post__dek {
  font-size: var(--nu-fs-lead);
  line-height: var(--nu-lh-body);
  color: var(--nu-theme-muted);
  margin: 0;
}

/* --- Answer block: the 40 to 80 word direct answer at the top.
       Highest-lift GEO element. Visually a quiet emphasis panel. --- */
.nu-answer-block {
  background: var(--nu-theme-surface);
  padding: var(--nu-gap);
  margin: 0 0 var(--nu-gap);
  position: relative;
}
.nu-answer-block p {
  margin: 0;
  font-size: var(--nu-fs-lead);
  line-height: var(--nu-lh-body);
}
.nu-answer-block p + p {
  margin-top: 12px;
}

/* Answer block is now its own "quick answer" section directly below the hero
   (see hero.php). Question-shaped H2 paired with the answer panel for AEO;
   keeps the hero itself uncluttered. */
.nu-answer-section__q {
  font-size: var(--nu-fs-h3);
  margin: 0 0 var(--nu-gap-sm);
}
.nu-answer-section__a {
  /* No accent left-border: the surface fill already sets the panel apart, and
     a gradient/accent bar would echo the hero's own gradient border. */
}

/* Two-column band: answer left, key facts + fading review right. */
.nu-answer-section__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--nu-gap-lg);
  align-items: start;
}
.nu-answer-section__grid--single { display: block; }
.nu-answer-section__grid--single .nu-answer-section__a { max-width: 760px; }
.nu-answer-section__side {
  display: flex;
  flex-direction: column;
  gap: var(--nu-gap);
}

/* Key-fact bullets (brand gradient square marker). */
.nu-answer-facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.nu-answer-facts__item {
  position: relative;
  padding-left: 26px;
  font-size: var(--nu-fs-lead);
  line-height: var(--nu-lh-snug);
  font-weight: var(--nu-fw-bold);
}
.nu-answer-facts__item::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.42em;
  width: 11px;
  height: 11px;
  background: linear-gradient(135deg, var(--nu-gradient-green-start), var(--nu-gradient-green-end));
}

/* Fading single Google review. Items overlap in one grid cell so the card
   sizes to the tallest and crossfades cleanly. */
.nu-answer-review {
  display: grid;
  background: var(--nu-theme-surface);
  padding: var(--nu-gap);
}
.nu-answer-review__item {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.6s ease-in-out;
}
.nu-answer-review__item.is-active {
  opacity: 1;
  visibility: visible;
}
.nu-answer-review__stars {
  display: block;
  color: var(--nu-theme-accent);
  letter-spacing: 2px;
  font-size: var(--nu-fs-small);
  margin-bottom: 10px;
}
.nu-answer-review__text {
  margin: 0 0 12px;
  font-size: var(--nu-fs-body);
  line-height: var(--nu-lh-body);
}
.nu-answer-review__name {
  font-weight: var(--nu-fw-bold);
  font-size: var(--nu-fs-small);
}
.nu-answer-review__src {
  color: var(--nu-theme-muted);
  font-weight: var(--nu-fw-regular);
}

@media (max-width: 900px) {
  .nu-answer-section__grid {
    grid-template-columns: 1fr;
    gap: var(--nu-gap);
  }
}
@media (prefers-reduced-motion: reduce) {
  .nu-answer-review__item { transition: none; }
}

/* --- Key takeaways --- */
.nu-key-takeaways {
  background: var(--nu-theme-surface);
  padding: var(--nu-gap);
  margin: 0 0 var(--nu-gap-lg);
}
.nu-key-takeaways__heading {
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  color: var(--nu-theme-accent);
  margin: 0 0 var(--nu-gap-sm);
}
.nu-key-takeaways ul {
  margin: 0;
}

/* --- Table of contents --- */
.nu-toc {
  border-top: 1px solid var(--nu-theme-border);
  border-bottom: 1px solid var(--nu-theme-border);
  padding: var(--nu-gap) 0;
  margin: 0 0 var(--nu-gap-lg);
}
.nu-toc__heading {
  font-size: var(--nu-fs-body);
  font-weight: var(--nu-fw-bold);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  color: var(--nu-theme-muted);
  margin: 0 0 var(--nu-gap-sm);
}
.nu-toc ol {
  margin: 0;
  padding-left: 1.2em;
}
.nu-toc li {
  margin-bottom: 8px;
  line-height: var(--nu-lh-snug);
}
.nu-toc a {
  color: var(--nu-theme-text);
  text-decoration: none;
}
.nu-toc a:hover {
  color: var(--nu-theme-accent);
}

/* --- Prose body --- */
.nu-prose h2 {
  margin-top: var(--nu-gap-lg);
  margin-bottom: var(--nu-gap-sm);
  scroll-margin-top: calc(var(--nu-header-h, 100px) + 20px);
}
.nu-prose h3 {
  margin-top: var(--nu-gap);
  margin-bottom: 12px;
}
.nu-prose p {
  margin: 0 0 var(--nu-gap-sm);
}
.nu-prose > *:first-child {
  margin-top: 0;
}

/* --- Data tables: quoted verbatim by LLMs, so keep them clean --- */
.nu-prose table,
.nu-data-table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 var(--nu-gap-lg);
  font-size: var(--nu-fs-small);
}
.nu-prose table th,
.nu-data-table th {
  text-align: left;
  font-weight: var(--nu-fw-bold);
  padding: 12px;
  border-bottom: 2px solid var(--nu-theme-accent);
  background: var(--nu-theme-surface);
}
.nu-prose table td,
.nu-data-table td {
  padding: 12px;
  border-bottom: 1px solid var(--nu-theme-border);
  vertical-align: top;
}
.nu-prose table tr:last-child td,
.nu-data-table tr:last-child td {
  border-bottom: none;
}
/* Wide tables scroll rather than breaking the page */
.nu-table-scroll {
  overflow-x: auto;
  margin: 0 0 var(--nu-gap-lg);
}
.nu-table-scroll table {
  margin-bottom: 0;
  min-width: 480px;
}

/* --- Blog post FAQ ---
 * The FAQ items themselves are the shared `.nu-faq-accordion` block (see
 * inc/faq.php + the FAQ module CSS above). This `.nu-post-faq` wrapper
 * only adds the top margin that separates the block from the article
 * body on a blog post. Markup, accordion behaviour, and styling of the
 * items are identical to the page module and case studies. */
.nu-post-faq {
  margin-top: var(--nu-gap-lg);
}

/* --- Service areas strip --- */
.nu-service-strip {
  border-top: 1px solid var(--nu-theme-border);
  padding-top: var(--nu-gap);
  margin-top: var(--nu-gap-lg);
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
}

/* --- Author block --- */
.nu-post__footer {
  margin-top: var(--nu-gap-lg);
  padding-top: var(--nu-gap);
  border-top: 1px solid var(--nu-theme-border);
}
.nu-post__author-label {
  display: block;
  font-size: var(--nu-fs-small);
  text-transform: uppercase;
  letter-spacing: var(--nu-ls-label);
  color: var(--nu-theme-muted);
  margin-bottom: 6px;
}
.nu-post__author-name {
  display: block;
  font-size: var(--nu-fs-lead);
  margin-bottom: 8px;
}
.nu-post__author-bio {
  display: block;
  color: var(--nu-theme-muted);
  line-height: var(--nu-lh-body);
}

/* --- Related posts --- */
.nu-post-related__heading {
  margin-bottom: var(--nu-gap);
}
.nu-post-related__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--nu-gap);
}
.nu-post-related__card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: var(--nu-gap);
  background: var(--nu-theme-surface);
  text-decoration: none;
  color: inherit;
  transition: box-shadow var(--nu-transition);
}
.nu-post-related__card:hover {
  box-shadow: var(--nu-glow);
}
.nu-post-related__title {
  font-weight: var(--nu-fw-bold);
  line-height: var(--nu-lh-snug);
}
.nu-post-related__excerpt {
  font-size: var(--nu-fs-small);
  color: var(--nu-theme-muted);
  line-height: var(--nu-lh-body);
}
.nu-post-related__cta {
  color: var(--nu-theme-accent);
  font-size: var(--nu-fs-small);
  margin-top: auto;
}

/* --- Post CTA --- */
.nu-post-cta__inner {
  max-width: 720px;
}
.nu-post-cta__heading {
  margin-bottom: var(--nu-gap-sm);
}
.nu-post-cta__body {
  margin-bottom: var(--nu-gap-sm);
}

@media (max-width: 900px) {
  .nu-post-related__grid {
    grid-template-columns: 1fr;
  }
}

/* Answer-block note variant: an up-front caveat or status statement.
   Same panel as the answer block but with the brand gradient bar so it
   reads as "stop and note this" rather than "here is your answer". */
.nu-answer-block--note {
  border-left: 4px solid transparent;
  border-image: linear-gradient(180deg,
    var(--nu-gradient-green-start), var(--nu-gradient-green-end)) 1;
}
.nu-answer-block--note p {
  font-size: var(--nu-fs-body);
}

/* ==========================================================================
   Batch fixes (2026-08-21)
   ========================================================================== */

/* Gravity Forms selects/inputs: force dark text on the white field. Some
   browsers honour -webkit-text-fill-color over `color`, which is what made
   the Service Area / Service dropdowns render white-on-white. */
.gform_wrapper input,
.gform_wrapper select,
.gform_wrapper textarea,
.gform_wrapper select option {
  color: #272724 !important;
  -webkit-text-fill-color: #272724 !important;
  opacity: 1 !important;
}

/* Google review cards: drop the plugin's left accent bar (that green pseudo
   line belongs only on specific components), and give the cards a very subtle
   Nulectrics-colour gradient wash over the surface. */
.egr-review::before { content: none !important; }
.egr-review {
  background:
    linear-gradient(135deg, rgba(17,159,107,0.10), rgba(32,182,186,0.05)),
    var(--nu-theme-surface) !important;
}

/* CTA banner — selectable CARD background (independent of the section bg). */
.nu-cta-banner__inner--bg-surface {
  background: var(--nu-theme-surface);
}
.nu-cta-banner__inner--bg-gradient {
  background:
    linear-gradient(135deg, rgba(17,159,107,0.14), rgba(32,182,186,0.08)),
    var(--nu-theme-surface);
}
.nu-cta-banner__inner.nu-style--invert {
  background: var(--nu-theme-bg);
}

/* Post author CTA (moved out of the old invert banner). */
.nu-post__author-cta {
  margin: var(--nu-gap-sm) 0 0;
}
