/* ---------------------------------------------------------------------------
   Components: the six The7 shortcodes reimplemented, plus the hero that
   replaces Revolution Slider. Class names match The7's so the per-instance
   .vc_custom_* rules WPBakery generates still apply.
--------------------------------------------------------------------------- */

/* ⚠️ The7's compiled sheet carries a GLOBAL `a, a:hover { color:
   var(--the7-links-color) }`, and it is enqueued after main.css — so it beat
   `a { color: var(--ajc-accent) }` and left every link outside .page-content /
   .entry-content gold: the skip link, the logo wrapper, the post navigation.
   The earlier link sweep missed them because it only looked inside the content
   containers; the full-page pre-flight caught them.

   Overriding the variable is the right lever rather than chasing selectors —
   it is literally "the links colour", and it also carries
   .shortcode-tooltip. Set here, not in tokens.css, because the7-css-vars.css
   defines it on :root and loads after tokens.
   --ajc-highlight keeps #ffc000 for focus rings and rating stars. */
:root{
  --the7-links-color:#282c37;
  --the7-links-hover-color:#282c37;
}

/* ---------- hero (replaces revslider) ---------- */
.hero{position:relative;overflow:hidden;background:var(--ajc-accent);color:#fff;
  min-height:clamp(24rem,52vh,34rem);display:flex;align-items:center}
.hero__bg{position:absolute;inset:0}
.hero__bg img{width:100%;height:100%;object-fit:cover}
.hero__bg::after{content:"";position:absolute;inset:0;
  background:linear-gradient(to right,rgba(40,44,55,.86) 0%,rgba(40,44,55,.62) 45%,rgba(40,44,55,.25) 100%)}
.hero__inner{position:relative;z-index:2;padding:56px 0}
.hero__title{color:#fff;margin:0 0 .5em;max-width:20ch}
.hero__text{max-width:62ch;font-size:16px;line-height:28px;margin:0 0 1.6em;color:rgba(255,255,255,.94)}
.hero__cta{display:flex;gap:.9rem;flex-wrap:wrap;margin:0}

/* ---------- buttons (dt_default_button) ---------- */
/* ⚠️ The base button rule lives in main.min.css, which this theme deliberately
   does not load, so it has to be restated here — measured off live, not guessed:
       .dt-btn{display:inline-flex;…;white-space:nowrap}
       .default-btn-shortcode{white-space:normal}
   Losing it produced two visible faults on the homepage. `inline-block` is
   harmless alone, but `align-items:stretch` on a flex PARENT then blockifies the
   button and stretches it: "Get A Free Quote" sits in an .ajc-cards equal-height
   column whose .wpb_wrapper is a flex column, so it rendered 550px wide against
   live's 147. And with no `nowrap`, "View all reviews →" wrapped to two lines —
   80px tall against live's 37. */
.dt-btn{
  display:inline-flex;align-items:center;justify-content:center;
  white-space:nowrap;align-self:flex-start;
  /* live measures border-width:0 (--the7-btn-*-border-width is 0px). The 2px
     border here was invisible — same colour as the fill — but made every button
     exactly 4px wider and taller than live's. */
  text-decoration:none;border:0 solid var(--ajc-btn-bg);
  background:var(--ajc-btn-bg);color:var(--ajc-btn-color);
  font-family:var(--ajc-btn-font);font-weight:var(--ajc-btn-weight);
  border-radius:var(--ajc-radius);transition:opacity .15s ease,background-color .15s ease;
}
.default-btn-shortcode{white-space:normal}
.dt-btn > span{display:block}
/* Sizes come from The7's own variables (the7-css-vars.css, which we DO load):
   13px/15px on 8px 14px for `s`, and live computes exactly that on every small
   button on the homepage. The hard-coded 14px/18px on 11px 22px here was
   invented and made every one of them a size too big. */
.dt-btn-s{
  font-size:var(--the7-btn-s-font-size,13px);
  line-height:var(--the7-btn-s-line-height,15px);
  padding:var(--the7-btn-s-padding,8px 14px);
}
.dt-btn-m{
  font-size:var(--the7-btn-m-font-size,14px);
  line-height:var(--the7-btn-m-line-height,16px);
  padding:var(--the7-btn-m-padding,12px 18px);
}
.dt-btn-l{font-size:var(--ajc-btn-size);line-height:var(--ajc-btn-lh);padding:15px 30px}
.dt-btn:hover{opacity:.88;color:var(--ajc-btn-color)}
/* The hero's outline button needs a border of its own now the base is 0. */
.dt-btn--ghost{background:transparent;border:2px solid rgba(255,255,255,.7);color:#fff}
.dt-btn--ghost:hover{background:rgba(255,255,255,.14);opacity:1}
.btn-inline-left{margin-right:auto}
/* ⚠️ dt_default_button puts the alignment class on the ANCHOR, not a wrapper,
   so `text-align:center` only centred the label inside the button. And inside
   the .ajc-cards equal-height column the button is a FLEX ITEM, where
   text-align does nothing at all and align-self is the only thing that moves
   it — which is why the homepage cards sat at 30/222 against live's 136/136
   once .dt-btn gained align-self:flex-start. margin-inline covers the
   non-flex case, align-self the flex one. */
.dt-btn.btn_center,.dt-btn.btn-center{align-self:center;margin-inline:auto}
.btn_center:not(.dt-btn),.btn-center:not(.dt-btn){display:block;text-align:center}
.btn_center .dt-btn,.btn-center .dt-btn{margin-inline:auto}

/* ---------- dt_fancy_image ---------- */
.shortcode-single-image-wrap{margin:0}
/* honour the declared display box; centre it when narrower than the column */
.shortcode-single-image-wrap[style*="--ajc-img-w"]{max-width:var(--ajc-img-w)}
.shortcode-single-image-wrap[style*="--ajc-img-w"].aligncenter{margin-inline:auto}
/* ⚠️ Do NOT put `aspect-ratio:var(--ajc-img-ratio,auto)` here. The `auto`
   fallback is not a no-op: writing aspect-ratio:auto explicitly CANCELS the
   intrinsic ratio the browser derives from an img's width/height attributes.
   With height:auto and WordPress's sizes="auto" lazy images, the height then has
   nothing solid to resolve against — Chrome 151 laid a 240x100 logo out 1500px
   tall on the owner's machine (Chromium 124 and Firefox 132 here did not). The
   ratio is now set only where one actually exists, in the rule below. */
.shortcode-single-image-wrap img{
  width:100%;border-radius:var(--ajc-img-radius,0);
  height:auto;
  object-fit:contain;
}
/* ⚠️ `cover` ONLY where the shortcode declared BOTH width and height — that is
   the only case where The7 crops to a box, and the only case where a box exists
   to crop to. Applied unconditionally it is a trap: an image whose box height
   goes wrong for any reason (a stretched flex item, an ancestor with a definite
   height) gets magnified to fill it and centre-cropped, turning a logo into an
   unreadable 13px slice of itself. `contain` cannot do that — worst case the
   image letterboxes. Reported by the owner 2026-08-05 with box=218x1500 on a
   429x180 logo. */
.shortcode-single-image-wrap[style*="--ajc-img-ratio"] img{
  aspect-ratio:var(--ajc-img-ratio);height:auto;object-fit:cover;
}
.shortcode-single-image-wrap .fancy-media-wrap{position:relative;overflow:hidden;line-height:0}
.shortcode-single-image-wrap a{display:block;line-height:0}
.shortcode-single-image-wrap.enable-bg-rollover img{transition:transform .45s cubic-bezier(.2,.7,.3,1)}
.shortcode-single-image-wrap.enable-bg-rollover a:hover img{transform:scale(1.04)}
.fancy-media-caption{
  font-size:13px;line-height:22px;color:var(--ajc-ink);padding-top:.6rem;margin:0;
}
.alignleft{float:left;margin:0 1.5rem 1rem 0}
.alignright{float:right;margin:0 0 1rem 1.5rem}
/* The7's shortcode wrapper floats but takes no side margin — the 1.5rem above is
   for inline content images. Left on, it cost the Merseyside map 24px of width
   (526 against live's 550). */
.shortcode-single-image-wrap.alignleft,.shortcode-single-image-wrap.alignright{margin:0}
.aligncenter{margin-inline:auto}

/* ---------- dt_icon_text ---------- */
.dt-icon-text{display:flex;gap:1rem;align-items:flex-start}
.dt-icon-text__icon{flex:0 0 auto;line-height:0;color:var(--ajc-accent)}
.dt-icon-text__icon svg{display:block}
.dt-icon-text__title{margin:0 0 .4em}
.dt-icon-text__desc p{margin:0 0 1em}
.dt-icon-text__desc p:last-child{margin-bottom:0}
.dt-icon-text .dt-btn{margin-top:.6rem}
/* Whole-card links (apply_link="block") must not look like body links. */
a.dt-icon-text--linked{text-decoration:none;color:inherit;transition:background-color .15s ease}
a.dt-icon-text--linked .dt-icon-text__title{color:var(--ajc-accent)}

/* ---------- /contact/ methods ------------------------------------------------
   Owner 2026-08-09. The six ways to reach the company were split 1 / 2 / 3
   across three builder columns — lopsided, and the three social ones rendered
   as identical "Read more" buttons. Lay all six out as one even grid.

   `display:contents` on the column chain promotes the cards out of their
   builder columns so the ROW can grid them; without it the grid would only see
   three columns of uneven length. Scoped to this row on this page. */
@media (min-width:779px){
  .page-id-308 .wpb_row:has(.dt-icon-text){
    display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
    background:var(--ajc-line);border:1px solid var(--ajc-line);
    /* ⚠️ Padding must go, and become margin. The row carries 80px/20px from the
       builder, and the divider colour behind the grid filled all of it — an
       80px grey band above the cards that read as a rendering fault. */
    padding:0 !important;margin:3rem 0 !important;
  }
  /* The row after this one carries WPBakery's -30px top margin. Harmless when
     the cards row had no background; with one it pulled "What to expect" 30px
     up and over the bottom row of cards. */
  .page-id-308 .wpb_row:has(.dt-icon-text) + .wpb_row{margin-top:0 !important}
  .page-id-308 .wpb_row:has(.dt-icon-text) > .wpb_column,
  .page-id-308 .wpb_row:has(.dt-icon-text) > .wpb_column > .vc_column-inner,
  .page-id-308 .wpb_row:has(.dt-icon-text) > .wpb_column > .vc_column-inner > .wpb_wrapper{
    display:contents;
  }
  /* ⚠️ `display:contents` does NOT suppress an element's pseudo-elements — they
     still generate boxes, and here they became grid items. The7's clearfix puts
     ::before/::after on every .vc_column-inner and .wpb_wrapper, so six phantom
     cells interleaved with the six cards and scattered them across the grid
     (Address landed in column 2, Messenger in column 1 of row 2). Third time
     this clearfix has caused a layout fault; the brand bar hit it twice. */
  .page-id-308 .wpb_row:has(.dt-icon-text) .vc_column-inner::before,
  .page-id-308 .wpb_row:has(.dt-icon-text) .vc_column-inner::after,
  .page-id-308 .wpb_row:has(.dt-icon-text) .wpb_wrapper::before,
  .page-id-308 .wpb_row:has(.dt-icon-text) .wpb_wrapper::after{display:none !important}
  .page-id-308 .dt-icon-text{background:#fff;padding:1.5rem 1.6rem;margin:0}
  .page-id-308 a.dt-icon-text--linked:hover{background:var(--the7-content-boxes-bg,rgba(0,0,0,.04))}
}
@media (max-width:778px){
  .page-id-308 .dt-icon-text{padding:1rem 0}
}

/* ---------- carousels (dt_media_gallery_carousel, dt_testimonials_carousel) --
   Scroll-snap rather than a JS slider library: keyboard, touch and reduced
   motion all work for free, and it drops a dependency.                       */
/* 10px, not 1rem — measured off the live Owl carousel, where .dt-owl-item
   carries margin-right:10px and each of 4 slides is 192.8px in an 805px track. */
.ajc-carousel{position:relative;--ajc-carousel-gap:10px}
.ajc-carousel__track{
  display:grid;grid-auto-flow:column;
  grid-auto-columns:calc((100% - (var(--per) - 1) * var(--ajc-carousel-gap)) / var(--per));
  gap:var(--ajc-carousel-gap);overflow-x:auto;scroll-snap-type:x mandatory;
  scrollbar-width:none;padding-bottom:.25rem;
}
.ajc-carousel__track::-webkit-scrollbar{display:none}
.ajc-carousel__item{scroll-snap-align:start}
/* The7's media gallery renders SQUARE, not 3:2 — see ajc_the7_square_url(). */
.ajc-carousel__item img{width:100%;height:auto;aspect-ratio:1 / 1;object-fit:cover;border-radius:var(--radius,0)}
.ajc-carousel__nav{
  position:absolute;top:50%;transform:translateY(-50%);z-index:3;
  width:44px;height:44px;border:0;border-radius:50%;cursor:pointer;
  background:rgba(40,44,55,.82);color:#fff;
}
.ajc-carousel__nav::before{content:"";display:block;width:9px;height:9px;margin-inline:auto;
  border-top:2px solid #fff;border-right:2px solid #fff}
.ajc-carousel__nav--prev{left:-6px}
.ajc-carousel__nav--prev::before{transform:rotate(-135deg)}
.ajc-carousel__nav--next{right:-6px}
.ajc-carousel__nav--next::before{transform:rotate(45deg)}
.ajc-carousel__nav:hover{background:var(--ajc-accent)}
@media (max-width:778px){ .ajc-carousel__track{grid-auto-columns:86%} .ajc-carousel__nav{display:none} }

/* ---------- testimonial card (redesigned 2026-08-09, owner request) ----------
   Not a port. The7's layout-5 put a round avatar left of the quote, and on this
   site that avatar is the same AJC logo on every card — it identified nobody and
   cost 142px of the 550px column. Owner: "redesign that area entirely… I don't
   think the icon/logo is needed."

   The idea: for a builder the evidence is the house, not the face. So the card
   reads rating → quote → the job itself → who said it, and the freed width goes
   to the photos.

   The one deliberate move is the type scale below. Every slide in a carousel is
   forced to the height of the longest quote, so "Good job well done, would
   recommend" used to sit in a large void at 16px. Sizing the quote to its own
   length fills the card honestly instead of padding it out. */
/* Desktop keeps the equal-height cards (signed off): the grid stretches every
   item to the tallest and the content is optically centred inside it. Mobile
   does NOT — see the breakpoint at the end of this block for why. */
.testimonial-item{margin:0;background:var(--the7-content-boxes-bg,#f7f7f8);border:0;padding:2rem 1.9rem;
  display:flex;flex-direction:column;justify-content:center;box-sizing:border-box}
/* ⚠️ Sizing the WRAPPER does nothing: `.wsm-stars` carries its own
   `font-size:15px` from the Customiser's Additional CSS (the `wp-custom-css`
   block), which prints last in the head and so wins at equal specificity. The
   span has to be targeted directly, and above (0,1,0) to beat it. That rule is
   site-wide and shared with live, so it is overridden here rather than edited.
   Its `color:#f5b301 !important` still wins and is left alone — that gold is
   what the reviews grid uses too. */
.testimonial-item .testimonial-rating{line-height:1;margin:0 0 1.15rem}
.testimonial-item .testimonial-rating .wsm-stars{font-size:24px;line-height:1;
  letter-spacing:.14em;margin-left:0;vertical-align:top}
/* ⚠️ The element selector is load-bearing. The7 styles
   `blockquote:not(.wp-block-quote):not(.elementor-blockquote)` — specificity
   (0,2,1) — which beat a plain `.testimonial-item .testimonial-content` (0,2,0)
   and flattened every card back to its 18px. Including `blockquote` here ties
   the specificity, and components.css loads after the vendored sheet. */
.testimonial-item blockquote.testimonial-content{margin:0;padding:0;border:0;color:var(--ajc-accent);
  /* The7 gives every blockquote background:var(--the7-content-boxes-bg), which
     is rgba(0,0,0,.04) — the SAME translucent value as the card. Two layers of
     4% black stack, so the quote rendered as a darker panel inside the card. */
  background:transparent;
  font-family:var(--ajc-font-head);
  font-weight:400;font-style:normal;quotes:none;text-wrap:pretty}
.testimonial-item .testimonial-content p{margin:0 0 .6em}
.testimonial-item .testimonial-content p:last-child{margin-bottom:0}
/* Length-based scale. Thresholds are character counts of the rendered excerpt. */
.testimonial-item blockquote.testimonial-content--xl{font-size:26px;line-height:36px;letter-spacing:-.01em}
.testimonial-item blockquote.testimonial-content--l {font-size:21px;line-height:32px}
.testimonial-item blockquote.testimonial-content--m {font-size:18px;line-height:29px}
.testimonial-item blockquote.testimonial-content--s {font-size:16px;line-height:27px}

/* Attribution is data, so it stays quiet: the quote is the loud thing. `auto`
   top margin pins it to the bottom of the card, which is what makes the varying
   quote lengths read as deliberate rather than as slack. */
.testimonial-item .testimonial-vcard{display:flex;flex-wrap:wrap;align-items:baseline;
  gap:.5rem .7rem;margin-top:0;padding-top:1.4rem}
.testimonial-item .testimonial-name{font-family:var(--ajc-font-head);
  font-weight:700;font-size:12px;line-height:18px;letter-spacing:.09em;
  text-transform:uppercase;color:var(--ajc-accent)}
.testimonial-item .testimonial-date{font-size:12px;line-height:18px;color:#999}

/* Job photos: the proof. Fixed 4:3 boxes so a mixed set of shapes still lines
   up, and an explicit ratio rather than `auto` — `aspect-ratio:auto` cancels the
   ratio the browser derives from an img's width/height attributes, which once
   laid a logo out 1500px tall. */
.testimonial-item .testimonial-photos{display:flex;flex-wrap:wrap;gap:8px;margin:1.4rem 0 0}
.testimonial-item .testimonial-photo{position:relative;flex:1 1 140px;max-width:200px;margin:0;
  overflow:hidden;line-height:0}
.testimonial-item .testimonial-photo img{display:block;width:100%;height:auto;
  aspect-ratio:4/3;object-fit:cover}
/* Before/After is real sequence information about the work, not decoration —
   which is the only reason it earns a marker. */
.testimonial-item .testimonial-photo-label{position:absolute;left:0;bottom:0;
  background:var(--ajc-accent);color:#fff;font-family:var(--ajc-font-head);
  font-size:9px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  line-height:1;padding:5px 8px}

@media (max-width:778px){
  .testimonial-item{padding:1.5rem 1.4rem}
  .testimonial-item blockquote.testimonial-content--xl{font-size:21px;line-height:30px}
  .testimonial-item blockquote.testimonial-content--l {font-size:19px;line-height:29px}
  /* flex-basis, not width: the 140px basis from the desktop rule still won and
     stacked the pair, doubling the photo block to 308px. */
  .testimonial-item .testimonial-photo{flex:1 1 calc(50% - 4px);max-width:calc(50% - 4px)}
  /* A 14% sliver of the next card showed a column of broken words. 8% is a card
     edge — still says "there are more", without looking like a rendering fault. */
  .ajc-carousel--testimonials .ajc-carousel__track{grid-auto-columns:92%}
  /* ⚠️ The height of this carousel is set by its TALLEST slide, wherever the
     slack ends up. Letting each card size itself just moved the hole outside
     the card: 225px between a short card and the button, of which only 20px
     was real spacing. The fix is to close the spread between the tallest and
     shortest slide (excerpt cap + the photo rule below), not to move it
     around, so the cards stay equal-height and there is no gap outside. */
  .testimonial-item .testimonial-photo:only-child{flex-basis:62%;max-width:62%}
}
.wsm-stars{color:var(--ajc-highlight);letter-spacing:.1em}

/* ---------- dt_before_after ---------- */
.ajc-ba__media{position:relative;overflow:hidden;line-height:0}
.ajc-ba__media img{width:100%;height:100%;object-fit:cover}
.ajc-ba__after,.ajc-ba__before{position:absolute;inset:0}
.ajc-ba__before{clip-path:inset(0 calc(100% - var(--w,50%)) 0 0)}
.ajc-ba__media > .ajc-ba__after{position:relative}
.ajc-ba__range{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:ew-resize;z-index:4}
.ajc-ba__line{position:absolute;top:0;bottom:0;left:var(--w,50%);width:2px;background:#fff;z-index:2;pointer-events:none}
.ajc-ba__line::after{content:"";position:absolute;top:50%;left:50%;width:34px;height:34px;
  transform:translate(-50%,-50%);border-radius:50%;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.35)}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;transition-duration:.001ms!important}
  .ajc-carousel__track{scroll-behavior:auto}
}

/* ---------- content container ------------------------------------------
   The7's .wf-wrap. Rows inside it inherit the site width; a row marked
   full-width still escapes, exactly as WPBakery behaved.
---------------------------------------------------------------------- */
/* The7: .wf-wrap is max-width 1250px with 44px of INTERNAL padding, so the
   usable column is 1162px and text begins ~139px in on a 1440 viewport.
   Getting this wrong widened every column and changed all the line wrapping,
   which shifted every section below it. */
/* ⚠️ max-width MUST be 100%, not --ajc-wrap. The7's compiled sheet sets an
   explicit `width:1250px` on `#main > .wf-wrap, #bottom-bar > .wf-wrap,
   #footer > .wf-wrap` (and on `.page-title > .wf-wrap, #fancy-header >
   .wf-wrap`), and keeps it safe with its own global `.wf-wrap{max-width:100%}`.
   Overriding that cap to 1250px removed the safety net, so on a 414px phone the
   footer wrap laid out 1250px wide, document scrollWidth went to 1250, and the
   browser zoomed the whole page out to fit it — measured 2026-08-06.
   `width:1250px; max-width:100%` resolves to min(1250, parent) at every width,
   which is exactly The7's behaviour. */
.wf-wrap{width:var(--ajc-wrap);max-width:100%;margin-inline:auto;box-sizing:border-box}
/* The7's real geometry, from #main > .wf-wrap in its compiled sheet:
   width 1250px with 50px padding a side (content 1150px), dropping to 20px
   below 778px. Matched at the same specificity so it reliably wins. */
#main > .wf-wrap{width:var(--ajc-wrap);max-width:100%;padding:0 50px;margin-inline:auto;box-sizing:border-box}
@media (max-width:778px){ #main > .wf-wrap{padding:0 20px} }
/* Do NOT zero the row margins: WPBakery uses -15px on .vc_row to cancel the
   15px padding on each .vc_column-inner. Removing them leaves the padding
   uncancelled and insets all content (mobile left edge 76px vs 20px).
   The gutter is 25px, not WPBakery's 15px — see the grid section below. */

/* WPBakery's rows carry negative side margins (-25px, -30px nested) to cancel
   the column padding, so on a narrow viewport they legitimately stick out past
   the content box — live does exactly the same (its rows also run to x=419 on a
   414px screen). The7 absorbs it with `body{overflow-x:hidden}` in main.min.css,
   which this theme deliberately does not load, so the overhang became a real
   10px horizontal scroll on mobile.
   ⚠️ `clip`, not `hidden`: `overflow:hidden` makes body a scroll container and
   `position:sticky` descendants stop sticking — that would silently kill the
   sticky header. `clip` does not establish one. Verified 2026-08-06 that the
   header still pins after this change. */
html,body{overflow-x:clip}

.page-content .vc_row[data-vc-full-width="true"]{width:100vw;margin-left:calc(50% - 50vw)}

/* ---------- sidebar layout (The7's wf-container-main) ---------- */
.wf-container-main{display:flex;gap:40px;align-items:flex-start}
.sidebar-right .wf-container-main{flex-direction:row}
.sidebar-left  .wf-container-main{flex-direction:row-reverse}
.wf-container-main > #content{flex:1 1 auto;min-width:0}
/* 345px, not 300 — live is content 805 + 50 gap + sidebar 345 = the 1200 container. */
.wf-container-main > .sidebar{flex:0 0 345px;max-width:345px}
.sidebar-none .wf-container-main{display:block}
.sidebar .widget{margin-bottom:2.4rem}
.sidebar .widget-title{font-size:var(--ajc-h4-size);line-height:var(--ajc-h4-lh);margin:0 0 1rem}
.sidebar ul{list-style:none;margin:0;padding:0}
.sidebar li{border-bottom:1px solid var(--ajc-line)}
.sidebar li a{display:block;padding:.7rem 0;text-decoration:none;font-weight:600}
@media (max-width:990px){
  .wf-container-main{display:block}
  .wf-container-main > .sidebar{max-width:none;margin-top:2.5rem}
}

/* ---------- fancy header typography ----------------------------------------
   The7 styles .fancy-title from its base stylesheet (main.min.css), which this
   theme deliberately does not load — so the heading fell back to a lighter
   weight. --the7-title-font-size is 26px.
-------------------------------------------------------------------------- */
.fancy-header{position:relative;display:flex;align-items:center;
  min-height:var(--ajc-fancy-h,180px);overflow:hidden}
/* The7 stores `.fancy-header .wf-wrap{min-height:200px}` in the per-page
   the7_fancy_title_css meta, and makes that wrap the flex container that
   vertically centres the title. Leaving it a block pinned the heading to the
   top of the banner (y=132 against the live y=208) — the hero-text
   misalignment. Centring here also makes the h1 shrink to its text, matching
   the live 220px-wide .entry-title instead of a full-width 1150px box. */
.fancy-header .wf-wrap{position:relative;z-index:2;width:100%;
  display:flex;align-items:center}
.fancy-header-overlay{position:absolute;inset:0;z-index:1;background:rgba(0,0,0,.35)}
.fancy-title{
  font-family:var(--ajc-font-head);font-weight:700;
  font-size:26px;line-height:1.25;color:#fff;margin:0;
}
.fancy-title-head{margin:0}
/* No mobile .fancy-title size here: 20px was invented. The real value is
   generated per page by The7 from _dt_fancy_header_responsive_font_size and is
   emitted by ajc_fancy_header_responsive_css() — 30px/38px on every page. */

/* ---------- heading typography, after the vendored sheet -------------------
   Scoped to plain headings inside .wpb_text_column only. A broad
   `.page-content h1-h6` rule also captured Ultimate's headings, which carry
   their own generated sizing — that regressed the homepage 43%→51%.
-------------------------------------------------------------------------- */
.wpb_text_column h1,.wpb_text_column h2,.wpb_text_column h3,
.wpb_text_column h4,.wpb_text_column h5,.wpb_text_column h6{
  font-family:var(--ajc-font-head);
  font-weight:var(--ajc-head-weight);
  color:var(--ajc-heading);
}
.wpb_text_column h2{font-size:var(--ajc-h2-size);line-height:var(--ajc-h2-lh)}
.wpb_text_column h3{font-size:var(--ajc-h3-size);line-height:var(--ajc-h3-lh)}
.wpb_text_column h4{font-size:var(--ajc-h4-size);line-height:var(--ajc-h4-lh)}

/* ---------- hero, restated after the vendored sheet ------------------------
   .hero__title lives in main.css, which loads before the vendored The7 CSS and
   therefore loses on the h1 sizing. Restated here so the hero heading renders
   at display size rather than body size.
-------------------------------------------------------------------------- */
.hero__title{
  font-family:var(--ajc-font-head);font-weight:var(--ajc-head-weight);
  font-size:var(--ajc-h1-size);line-height:var(--ajc-h1-lh);
  color:#fff;margin:0 0 .5em;max-width:20ch;
}
.hero__text{font-size:16px;line-height:28px;color:rgba(255,255,255,.94)}
@media (max-width:778px){ .hero__title{font-size:32px;line-height:42px} }

/* The vendored The7 rule `.top-bar{min-height:36px;padding:3px 50px}` targets
   the INNER bar in The7's DOM. Here `.top-bar` is the outer full-width strip
   wrapping a 36px-tall `.top-bar__inner`, so that 3px top+bottom made the bar
   42px and pushed the entire page down 6px — the header, the hero banner and
   every section below it. The inline padding is still wanted (it lines the
   content up at x=145, same as live); only the block padding is wrong. */
.top-bar{padding-block:0}

/* ---------- mobile header ---------------------------------------------------
   The7 drops the top bar entirely on mobile — the baseline shows only the logo
   and hamburger. Leaving it visible pushed every mobile page down by ~38px.
-------------------------------------------------------------------------- */
@media (max-width:778px){
  .top-bar{display:none}

  /* Measured off live: 60px bar, full-size 150x40 logo at x=20,y=10. The 64px
     bar and shrunken 130px logo here were invented, not measured. */
  .header__inner{padding-inline:20px;height:auto;min-height:60px}
}

/* ---------- WPBakery grid ---------------------------------------------------
   Only js_composer's *custom* (per-site) stylesheet is enqueued — The7 replaces
   the core grid CSS with its own, which lives in main.min.css and is
   deliberately not loaded here. Without these the column padding is never
   cancelled and every nesting level insets content by 15px a side (mobile left
   edge was 76px, then 50px, against a baseline of 20px).
-------------------------------------------------------------------------- */
.page-content .vc_row{margin-left:-25px;margin-right:-25px}
/* Nested rows use -30px, not -25px — measured: live .vc_inner is 610 wide at
   x=715 inside a 550 wrapper at x=745. With 25px column padding that nets -5px
   per side, which is what makes its columns 280 rather than 275. */
.page-content .vc_row.vc_inner{margin-left:-30px;margin-right:-30px}
.page-content .vc_column_container{padding-left:0;padding-right:0}
/* 25px, matching The7's gutter (measured: live .wpb_row is 1200 wide at x=120
   inside a 1150 content box at x=145, i.e. -25px a side, and a 4-column row
   yields 1200/4 - 50 = 250px images). WPBakery's own 15px made every column
   13px too wide — which is why the brand logos rendered 265px against 250px.
   The row margin and this padding must move together or the content edge
   shifts: edge = wrap padding - row margin + this. */
.page-content .vc_column_container > .vc_column-inner{padding-left:25px;padding-right:25px}

/* The7 applies --the7-page-left/right-margin (50px) to #main. This theme adds
   the #main wrapper, so it inherits that inset on top of .wf-wrap's own
   padding. On mobile the baseline sits at 20px, so neutralise it there. */
@media (max-width:778px){
  #main{padding-left:0;padding-right:0;margin-left:0;margin-right:0}
  /* Must track the 25px column padding above, or the mobile content edge moves:
     20px wrap padding - 25px row margin + 25px column padding = 20px. */
  .page-content .vc_row{margin-left:-25px;margin-right:-25px}
  .page-content .vc_row.vc_inner{margin-left:-30px;margin-right:-30px}
}

/* ---------- post title bar + breadcrumbs -----------------------------------
   The7 lays the title bar out as heading-left / breadcrumbs-right on one row,
   with the breadcrumbs as an inline list. Unstyled they rendered as a numbered
   vertical list under the title.
-------------------------------------------------------------------------- */
/* ⚠️ No vertical padding. The bar's height comes from the wrap's min-height, as
   it does on live; an extra 18px top and bottom made every page-title bar 36px
   too tall — 166 against live's 130 on desktop and 116 against 80 on mobile.
   That is the privacy page and all 34 posts, at every viewport width. */
.page-title{background:var(--the7-page-title-bg-color,rgba(0,0,0,.04))}
.page-title > .wf-wrap{display:flex;align-items:center;justify-content:space-between;
  gap:2rem;max-width:100%;margin-inline:auto;padding:0 50px;box-sizing:border-box}
.page-title-head{margin:0;flex:1 1 auto;min-width:0}
.page-title .entry-title{
  font-family:var(--ajc-font-head);font-weight:var(--ajc-head-weight);
  font-size:var(--ajc-h3-size);line-height:var(--ajc-h3-lh);color:var(--ajc-heading);margin:0;
}
.page-title-breadcrumbs{flex:0 0 auto}
.page-title-breadcrumbs .assistive-text{position:absolute!important;width:1px;height:1px;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.breadcrumbs{list-style:none;display:flex;flex-wrap:wrap;align-items:center;gap:.4rem;
  margin:0;padding:0;font-size:12px;color:var(--ajc-mute,#8a8a8a)}
.breadcrumbs li{display:flex;align-items:center;gap:.4rem}
.breadcrumbs li + li::before{content:"/";color:#bbb}
.breadcrumbs a{color:var(--ajc-ink);text-decoration:none}
.breadcrumbs a:hover{color:var(--ajc-link)}
@media (max-width:778px){
  .page-title > .wf-wrap{display:block;padding:0 20px}
  .page-title-breadcrumbs{margin-top:.6rem}
}

/* ---------- post thumbnail: date block + category badge ---------- */
.post-thumbnail{position:relative;line-height:0;margin:0 0 1.6rem}
.post-thumbnail img{width:100%;height:auto}
.post-thumbnail .fancy-date{
  position:absolute;top:14px;right:14px;z-index:2;
  background:#fff;border-radius:2px;padding:.45rem .7rem;text-align:center;line-height:1.15;
  box-shadow:0 1px 4px rgba(0,0,0,.18);
}
.post-thumbnail .fancy-date a{text-decoration:none;color:var(--ajc-ink);display:block}
.fancy-date .entry-month,.fancy-date .entry-year{display:block;font-size:10px;color:var(--ajc-mute,#888)}
.fancy-date .entry-date{display:block;font-size:20px;font-weight:700;
  border-top:1px solid #e3e3e3;border-bottom:1px solid #e3e3e3;padding:1px 0;margin:1px 0}
.entry-meta{font-size:12px;color:var(--ajc-mute,#8a8a8a);margin:0 0 1.2rem;
  display:flex;flex-wrap:wrap;gap:.9rem;align-items:center}
.entry-meta a{color:var(--ajc-ink);text-decoration:none}
.entry-meta a:hover{color:var(--ajc-link)}
.entry-content p{margin:0 0 1.2em}
/* Lists in post content. Measured off live: padding-left 0 with the list inset
   20px, and margins 0/10 — not the browser default 40px padding and 1em
   margins. Ours were 334px of usable width against live's 354px, so every list
   wrapped more, AND carried 18px of extra margin. On a short post that is
   noise; on the two long articles it accumulated to +242 and +442px. */
.entry-content ul,
.entry-content ol{margin:0 0 10px 20px;padding-left:0}
.entry-content li{margin:0}
/* Live closes the related grid with 35px of breathing room. */
.single-related-posts{padding-bottom:35px}
/* ⚠️ The template comment says this markup mirrors The7's "so the vendored
   stylesheet applies with no extra CSS". It does not: the .items-grid layout
   lives in main.min.css, which this theme deliberately drops — the same gap
   that cost us the button metrics. Rendered, the six items stacked full width
   and each thumbnail's `.alignleft` float cascaded the next one further right
   and down, producing a staircase. Live measures three 396px items per row
   with a 110x80 thumbnail. */
.single-related-posts .items-grid{
  display:grid;grid-template-columns:repeat(3,1fr);gap:26px 24px;
}
.single-related-posts .related-item{margin:0;min-width:0}
.single-related-posts .post-format-standard{display:flex;gap:15px;align-items:flex-start}
.single-related-posts .mini-post-img{flex:0 0 110px}
/* The float is what staircased them; inside a flex row it has no business. */
.single-related-posts .mini-post-img .alignleft{float:none;margin:0;display:block;line-height:0}
.single-related-posts .mini-post-img img{width:110px;height:80px;object-fit:cover;display:block}
.single-related-posts .post-content{min-width:0;font-size:14px;line-height:22px;color:var(--ajc-mute,#8a8a8a)}
.single-related-posts .post-content a{
  color:var(--ajc-accent);text-decoration:none;font-weight:600;
  font-size:15px;line-height:22px;display:inline-block;margin-bottom:.25rem;
}
.single-related-posts .post-content a:hover{text-decoration:underline}
@media (max-width:990px){ .single-related-posts .items-grid{grid-template-columns:repeat(2,1fr)} }
@media (max-width:640px){ .single-related-posts .items-grid{grid-template-columns:1fr} }

/* Post navigation — also unstyled, for the same reason. */
.post-navigation{margin:0 0 2.5rem;padding-top:1.6rem;border-top:1px solid var(--ajc-line)}
.post-navigation .nav-links{display:flex;flex-wrap:wrap;gap:1.5rem;justify-content:space-between}
.post-navigation .nav-previous,.post-navigation .nav-next{
  display:flex;flex-direction:column;gap:.15rem;max-width:48%;text-decoration:none;
}
.post-navigation .nav-next{text-align:right;margin-left:auto}
.post-navigation .meta-nav{
  font-size:12px;line-height:18px;letter-spacing:.08em;text-transform:uppercase;
  color:var(--ajc-mute,#8a8a8a);
}
.post-navigation .post-title{
  font-family:var(--ajc-font-head);font-weight:700;font-size:15px;line-height:23px;
  color:var(--ajc-accent);
}
.post-navigation a:hover .post-title{text-decoration:underline}
@media (max-width:640px){
  .post-navigation .nav-previous,.post-navigation .nav-next{max-width:100%}
  .post-navigation .nav-next{text-align:left;margin-left:0}
}
/* Tables in post content: live uses 5px cell padding and a 10px bottom margin.
   Ours were 1px, which made every table noticeably shorter (639 -> 546 on one
   of them) and, being tighter, harder to read. */
.entry-content table{margin:0 0 10px}
.entry-content table td,
.entry-content table th{padding:5px}

.post-thumbnail .category-badge{
  position:absolute;top:14px;left:14px;z-index:2;
  background:rgba(30,34,44,.88);border-radius:2px;padding:.3rem .55rem;line-height:1.2;
}
.post-thumbnail .category-badge a{color:#fff;font-size:11px;text-decoration:none}

/* NOT applied: The7's -10px .wf-container-main margin moves the mobile edge
   from 40px to 30px (target 20-26) but scores WORSE across the board
   (54→58, 50→56, 55→58) because the reflow changes line breaks and shifts
   everything vertically. Geometry and score disagree here; left as-is. */

/* ---------- typography: force the body face onto content ------------------
   The7's ONLY font-family rule is `#the7-body{font-family:var(--the7-base-font-family)}`.
   Everything else inherits. Body copy was falling back to the browser serif, so
   set it explicitly on the content containers here, where it loads last.
-------------------------------------------------------------------------- */
body,#the7-body,
.page-content,.entry-content,.wpb_text_column,.wpb_wrapper,
.page-content p,.entry-content p,.wpb_text_column p,
.page-content li,.entry-content li,.sidebar,.sidebar *,
.uvc-heading,.uvc-heading *,.dt-icon-text,.testimonial-item,.testimonial-item *{
  font-family:var(--ajc-font-body);
}

/* The7 only ever sets a paragraph's margin-BOTTOM; its reset (in the
   deliberately-unloaded main.min.css) zeroes the top. Without that, the browser
   default margin-block-start:1em survived, and because .vc_column-inner carries
   a `display:table` ::before clearfix the margin could not collapse out of the
   column — adding 14px to every WPBakery text column on the site. */
.page-content p,.entry-content p,.wpb_text_column p{margin-top:0}
.page-content h1,.page-content h2,.page-content h3,.page-content h4,
.entry-content h1,.entry-content h2,.entry-content h3,.entry-content h4,
.uvc-heading h1,.uvc-heading h2,.uvc-heading h3,.uvc-heading h4,
.fancy-title,.hero__title,.page-title .entry-title,.widget-title{
  font-family:var(--ajc-font-head);
}

/* ---------- footer ---------- */
#footer{background:var(--ajc-footer-bg,#252525);color:var(--ajc-footer,#aaa)}
#footer a{color:inherit}
#footer a:hover{color:#fff}
#bottom-bar .wf-container-bottom{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;
  flex-wrap:wrap;min-height:60px;padding:10px 0;font-size:13px;
}
#bottom-bar .wf-wrap{max-width:100%;margin-inline:auto;padding:0 50px;box-sizing:border-box}
#bottom-bar p{margin:0}
/* The7 scales footer logos down; without this they render at natural size. */
.footer-logos img,#footer .widget img{max-height:60px;width:auto;display:inline-block}
@media (max-width:778px){
  #bottom-bar .wf-wrap{padding:0 20px}
  #bottom-bar .wf-container-bottom{flex-direction:column;text-align:center;gap:.4rem}
}

/* ---------- hero: left aligned, not centred ---------- */
.hero .wrap,.hero__inner{text-align:left}
.hero__inner{margin-left:0;margin-right:auto}
/* .hero is display:flex, so .wrap becomes a flex item and shrinks to its
   content width — then margin-inline:auto centres that narrow box, which is why
   the hero copy sat ~300px in. width:100% makes it fill the row first. */
.hero .wrap{width:100%;max-width:var(--ajc-wrap);margin-inline:auto;padding-inline:50px;box-sizing:border-box}
@media (max-width:778px){ .hero .wrap{padding-inline:20px} }

/* ---------- fancy header: title should clear the header, not sit under it ---------- */
.fancy-header .wf-wrap{max-width:100%;margin-inline:auto;padding:0 50px;box-sizing:border-box}
.fancy-header{padding:0}
@media (max-width:778px){ .fancy-header .wf-wrap{padding:0 20px} }

/* ---------- service cards: centre the round thumbnail ----------
   ⚠️ Must not touch alignleft/alignright. Those are floats on live, and an auto
   inline margin beats the float once the wrapper is a flex item (the .ajc-cards
   equal-height rule below makes .wpb_wrapper a flex column). Auto cross-axis
   margins also cancel `align-items:stretch`, so the box stopped filling its
   column and collapsed to the image's intrinsic width — that is what centred
   and shrank the Merseyside map under "Areas We Cover". */
.shortcode-single-image-wrap[style*="--ajc-img-w"]:not(.alignleft):not(.alignright){margin-inline:auto}
.wpb_column .shortcode-single-image-wrap[style*="--ajc-img-radius"]{margin-inline:auto}

/* ---------- sidebar: match The7's list treatment ---------- */
.sidebar .widget{margin:0 0 2rem;padding:0}
.sidebar .widget-title{font-size:20px;line-height:30px;margin:0 0 .8rem;color:var(--ajc-heading)}
.sidebar .custom-menu{list-style:none;margin:0;padding:0}
.sidebar .custom-menu li{border-bottom:1px solid var(--ajc-line,#e6e6e6)}
.sidebar .custom-menu li:first-child{border-top:1px solid var(--ajc-line,#e6e6e6)}
.sidebar .custom-menu a{display:block;padding:.75rem 0;text-decoration:none;
  font-weight:600;font-size:14px;color:var(--ajc-ink)}
.sidebar .custom-menu a:hover{color:var(--ajc-link)}
.sidebar .widget_media_image img{max-width:100%;height:auto;margin:0 auto;display:block}



/* Pages with the title bar disabled open straight into content. ONE of them —
   About — starts with a row carrying `margin-top:-30px`, and with no banner
   above it that pulls the first paragraph up under the static header. That was
   the overlap reported 2026-08-05.

   ⚠️ The original fix was `#main{padding-top:34px}` on every title-disabled
   page, which was too blunt: measured across all six, only About has the
   negative margin. The other five (services, customerreviews, review, thanks,
   enquiry-received) put their first row at exactly y=126 on live — flush under
   the header — so the padding was pure gap, and the owner reported it as one
   above the Services banner.

   Neutralising the pull-up instead fixes About and leaves the rest matching
   live. `!important` because the -30px comes from a WPBakery vc_custom_ rule,
   which is !important. Do NOT go back to padding #main: live's masthead is
   position:absolute and swaps to a 60px sticky header almost immediately, so
   live tolerates a row at y=96 that a static header cannot. */
.ajc-title-disabled #main{padding-top:0}
/* ⚠️ Selector verified with el.matches() in the browser, not read off the DOM
   tree: `.page-content > .wpb-content-wrapper` does NOT match here even though
   the ancestor walk suggests it should, so descendant combinators it is. */
.ajc-title-disabled .wpb-content-wrapper > .wpb_row:first-of-type,
.ajc-title-disabled .page-content > .wpb_row:first-of-type{margin-top:0 !important}
.ajc-title-disabled #main > .wf-wrap{position:relative;z-index:1}

/* ===========================================================================
   SIDEBAR — deliberately improved on the original rather than copied.
   The old one was an unbounded list floating in white space with no sense of
   being a panel and no indication of where you are.
=========================================================================== */
.sidebar .widget{
  background:#fff;border:1px solid var(--ajc-line,#e6e6e6);border-radius:4px;
  padding:1.25rem 1.35rem 1.4rem;margin:0 0 1.25rem;
}
.sidebar .widget-title{
  font-family:var(--ajc-font-head);font-weight:700;font-size:16px;line-height:1.3;
  letter-spacing:.01em;color:var(--ajc-heading);margin:0 0 .9rem;
  padding-bottom:.7rem;border-bottom:2px solid var(--ajc-accent);
}
.sidebar .custom-menu{list-style:none;margin:0;padding:0}
.sidebar .custom-menu li{border:0}
.sidebar .custom-menu li + li{border-top:1px solid #eef0f2}
.sidebar .custom-menu a{
  display:flex;align-items:center;gap:.6rem;padding:.62rem 0;
  font:600 14px/1.35 var(--ajc-font-body);color:var(--ajc-ink);text-decoration:none;
  transition:color .12s ease,padding-left .12s ease;
}
.sidebar .custom-menu a::before{
  content:"";flex:0 0 auto;width:6px;height:6px;border-right:2px solid #c6cbd2;
  border-bottom:2px solid #c6cbd2;transform:rotate(-45deg);transition:border-color .12s ease;
}
.sidebar .custom-menu a:hover{color:var(--ajc-accent);padding-left:.25rem}
.sidebar .custom-menu a:hover::before{border-color:var(--ajc-accent)}
/* where you are now */
.sidebar .custom-menu .current-menu-item > a,
.sidebar .custom-menu .current_page_item > a{color:var(--ajc-accent);position:relative}
.sidebar .custom-menu .current-menu-item > a::before,
.sidebar .custom-menu .current_page_item > a::before{border-color:var(--ajc-accent)}

/* the K Rend badge reads as an accreditation, not a stray image */
.sidebar .widget_media_image{text-align:center;padding:1.5rem 1.35rem}
.sidebar .widget_media_image img{max-width:180px;height:auto;margin:0 auto;display:block}

/* ===========================================================================
   CONTACT FORM — improved on the original at the owner's request.
   ⚠️ The WPCode snippet prints its OWN <style> block in the body
   (`.wsm-contact-form{max-width:700px;margin:0 auto}` plus `.wsm-field`
   spacing). Inline styles come after our stylesheet, so these overrides use
   `form.wsm-contact-form` (element+class) to outrank it without !important.
   Fields are wrapped in .wsm-field divs — target those, not bare inputs.
=========================================================================== */
form.wsm-contact-form{
  display:grid;grid-template-columns:1fr 1fr;gap:1.1rem 1.25rem;
  max-width:none;width:100%;margin:0;
}
form.wsm-contact-form .wsm-field{margin:0}
/* long fields and the actions span both columns */
form.wsm-contact-form .wsm-field:has(textarea),
form.wsm-contact-form .wsm-field:has(button),
form.wsm-contact-form .wsm-field:has(input[type=submit]),
form.wsm-contact-form .wsm-field:has(#wsm_website){grid-column:1 / -1}
form.wsm-contact-form p:has(button),
form.wsm-contact-form p:has(input[type=submit]){grid-column:1 / -1;margin:0}
form.wsm-contact-form button,
form.wsm-contact-form input[type=submit]{grid-column:1 / -1;justify-self:start}

form.wsm-contact-form label{
  display:block;font:600 12px/1.4 var(--ajc-font-body);letter-spacing:.02em;
  color:var(--ajc-heading);margin:0 0 .35rem;
}
form.wsm-contact-form input[type=text],form.wsm-contact-form input[type=email],
form.wsm-contact-form input[type=tel],form.wsm-contact-form select,
form.wsm-contact-form textarea{
  width:100%;padding:.72rem .85rem;border:1px solid #d5d8dd;border-radius:3px;
  font:400 14px/1.5 var(--ajc-font-body);background:#fff;color:var(--ajc-ink);
  transition:border-color .12s ease,box-shadow .12s ease;
}
form.wsm-contact-form textarea{min-height:160px;resize:vertical}
form.wsm-contact-form input:focus,form.wsm-contact-form select:focus,
form.wsm-contact-form textarea:focus{
  outline:0;border-color:var(--ajc-accent);box-shadow:0 0 0 3px rgba(40,44,55,.12);
}
form.wsm-contact-form button,form.wsm-contact-form input[type=submit]{
  background:var(--ajc-btn-bg);color:#fff;border:0;cursor:pointer;
  font:700 15px/1.2 var(--ajc-btn-font);padding:.9rem 1.9rem;
  border-radius:var(--ajc-radius);transition:opacity .12s ease;
}
form.wsm-contact-form button:hover{opacity:.9}
/* honeypot */
form.wsm-contact-form #wsm_website,
form.wsm-contact-form label[for="wsm_website"]{position:absolute!important;left:-9999px}
@media (max-width:778px){ form.wsm-contact-form{grid-template-columns:1fr} }

/* ---------- service cards: line the Read More buttons up ---------------------
   Owner request 2026-08-05. The rows already carry equal_height="yes", so the
   COLUMNS stretch — but the content stacks from the top, so "Read More" lands
   wherever the copy ends (measured gaps on the homepage grid: 56/30/30/30/56/
   30/30). Make the chain from card to button a flex column and let the button
   take the slack.

   ⚠️ The :not(:has(.vc_row-o-equal-height)) guard is load-bearing. The homepage
   card grid is itself an inner row sitting at exactly the same structural depth
   as a card's own text block — inside an outer equal-height row's column. So a
   purely structural selector cannot tell them apart, and matching the grid set
   flex-direction:column on it: the six cards stopped sitting 3-across, stacked
   one per row, and the equal heights died with them. The guard excludes any
   column that contains a nested equal-height row, i.e. the grid wrappers.

   ⚠️ No height/min-height on the card. It already stretches via the column's
   default align-items:stretch. height:100% made the tallest card overflow its
   own bottom padding; min-height:100% was worse — a percentage height cannot
   resolve against a flex parent of indefinite height.

   Opt-in per page via the .ajc-cards body class (functions.php); eight pages
   use equal_height rows and only these two are card grids. A departure from the
   live site, like the sidebar and contact form. */
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner > .vc_column_container,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner > .vc_column_container > .vc_column-inner,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner > .vc_column_container > .vc_column-inner > .wpb_wrapper{
  display:flex;
  flex-direction:column;
}
/* grow, never shrink: flex-shrink:1 let the tallest card squeeze out its own
   bottom padding and put that button flush against the edge. */
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner > .vc_column_container,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner > .vc_column_container > .vc_column-inner,
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner > .vc_column_container > .vc_column-inner > .wpb_wrapper{
  flex:1 0 auto;
}
/* The slack collects here, so every button sits the same distance off the
   bottom however long the description runs. */
.ajc-cards .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner a.dt-btn{
  margin-top:auto;
}

/* On /services/ the "Fascia's, Soffits and Guttering" card was added later than
   the other six and its WPBakery rule (vc_custom_1770145582294) omits
   padding-bottom, where the rest use vc_custom_1495105364136 with 40px — so its
   button sat flush to the card edge. Identical on live: an authoring slip, not
   a port bug. !important because WPBakery's generated rules are. */
.page-id-27 .vc_row-o-equal-height > .vc_column_container:not(:has(.vc_row-o-equal-height)) > .vc_column-inner > .wpb_wrapper > .vc_inner{
  padding-bottom:40px !important;
}


/* ---------- review photo lightbox -------------------------------------------
   Paired with the module at the end of components.js. Kept deliberately plain:
   a dark backdrop, the photo, a caption. The Before/After label carries through
   as the caption, which is the one bit of context the full-size image loses. */
body.ajc-lb-open{overflow:hidden}
.ajc-lb{
  /* ⚠️ Above the cookie banner, which is z-index:99999 (set in the WPCode
     footer injection). At 9999 the banner sat on top of the photo and over the
     caption. It reappears as soon as the viewer closes. */
  position:fixed;inset:0;z-index:100000;
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  padding:clamp(12px,4vw,48px);
  background:rgba(18,20,26,.92);
}
.ajc-lb[hidden]{display:none}
.ajc-lb__fig{margin:0;display:flex;flex-direction:column;gap:.75rem;max-height:100%;min-width:0}
.ajc-lb__img{
  display:block;max-width:100%;max-height:calc(100vh - 9rem);
  width:auto;height:auto;object-fit:contain;background:#000;
}
.ajc-lb__cap{
  display:flex;justify-content:space-between;align-items:baseline;gap:1rem;
  font-family:var(--ajc-font-head);font-size:13px;line-height:20px;color:rgba(255,255,255,.86);
}
.ajc-lb__caption{font-weight:700;letter-spacing:.06em;text-transform:uppercase}
.ajc-lb__count{color:rgba(255,255,255,.55);white-space:nowrap}
.ajc-lb__close{
  position:absolute;top:.5rem;right:.75rem;
  width:44px;height:44px;border:0;cursor:pointer;
  background:transparent;color:#fff;font-size:32px;line-height:1;
}
.ajc-lb__nav{
  flex:0 0 auto;width:44px;height:44px;border:0;cursor:pointer;border-radius:50%;
  background:rgba(255,255,255,.12);position:relative;
}
.ajc-lb__nav:hover{background:rgba(255,255,255,.22)}
.ajc-lb__nav[hidden]{display:none}
.ajc-lb__nav::before{
  content:"";position:absolute;top:50%;left:50%;width:10px;height:10px;
  border-right:2px solid #fff;border-bottom:2px solid #fff;
}
.ajc-lb__nav--prev::before{transform:translate(-35%,-50%) rotate(135deg)}
.ajc-lb__nav--next::before{transform:translate(-65%,-50%) rotate(-45deg)}
.ajc-lb__close:focus-visible,.ajc-lb__nav:focus-visible{outline:3px solid var(--ajc-highlight);outline-offset:2px}
/* The thumbnails are now buttons in all but name. */
a.wsm-review-photo,a.testimonial-photo{cursor:zoom-in}
@media (max-width:640px){
  .ajc-lb{padding:8px}
  .ajc-lb__nav{position:absolute;bottom:14px;z-index:1}
  .ajc-lb__nav--prev{left:14px}
  .ajc-lb__nav--next{right:14px}
  .ajc-lb__img{max-height:calc(100vh - 11rem)}
}

/* ---------- /about/ ----------------------------------------------------------
   Owner 2026-08-09: "supposed to be showing what the company is and looks a bit
   basic". Same duplicated template as the other four — reviews-style 6-column
   with the Showcase gallery beside it — so the copy ran in a 550px gutter while
   half the page repeated /home/showcase/.

   The copy was never the problem; the structure was. Four values were buried in
   a run of paragraphs with the value's name inside the sentence, and Federation
   of Master Builders membership trailed the page as a footnote. Content now
   carries real headings and a .ajc-values wrapper (see the content-edit list in
   SWITCHOVER.md); this styles it.

   Cards, not icons: an icon per value would be four pieces of decoration
   standing in for four pieces of meaning. The value names are the content. */
@media (min-width:779px){
  .page-id-154 .wpb_column:has(.ajc-values),
  .page-id-154 .wpb_column:has(.ajc-values) + .wpb_column{width:100% !important;float:none !important}
}
/* The intro paragraph moved here from above the hero, and it sat flush against
   the photo below it: it is the last <p> in its text block, so WPBakery's
   `.wpb_text_column p:last-child{margin-bottom:0}` zeroes its margin. Space the
   photo instead of fighting that rule.
   ⚠️ Scoped to the column holding the values — `.shortcode-single-image-wrap`
   also matches all four brand-bar logos on this page. Verified with matches():
   1 of 5 wrappers. */
.page-id-154 .wpb_column:has(.ajc-values) .shortcode-single-image-wrap{margin-top:1.6rem}
.ajc-values{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:1px;margin:1.4rem 0 2rem;
  /* 1px gap over a rule-coloured background draws the dividers, so the cards
     read as one block rather than four floating boxes. */
  background:var(--ajc-line);border:1px solid var(--ajc-line);
}
.ajc-value{background:#fff;padding:1.4rem 1.5rem}
.ajc-value h4{
  margin:0 0 .5rem;font-family:var(--ajc-font-head);font-weight:700;
  font-size:16px;line-height:24px;color:var(--ajc-accent);
}
.ajc-value p{margin:0;font-size:14px;line-height:25px;color:var(--ajc-ink)}

/* FMB membership — a credential, so it gets the accent rule the values don't. */
.ajc-credential{
  margin:1.4rem 0 0;padding:.9rem 1.1rem;
  background:var(--the7-content-boxes-bg,rgba(0,0,0,.04));
  border-left:3px solid var(--ajc-accent);
  font-size:14px;line-height:24px;
}
.ajc-credential strong{color:var(--ajc-accent)}
.ajc-credential a{color:var(--ajc-accent);text-decoration:underline;text-underline-offset:2px}

/* Contact form styled as the review form's twin — owner asked for the two to
   feel uniform. Same white card, same hairline, same centred 680px measure,
   and the heading above it shares the band so the block reads as one thing.
   The grey section behind it goes: two different panel treatments for two
   forms doing the same job was the inconsistency. */
@media (min-width:779px){
  .page-id-308 .wpb_column:has(form.wsm-contact-form) > .vc_column-inner > .wpb_wrapper{
    max-width:680px;margin-inline:auto;
  }
}
/* ⚠️ The grey panel is NOT the row's own background — it is Ultimate's
   `.upb_row_bg` layer painting #e4e2e2 inside the row, so setting the row
   transparent did nothing on its own. Scoped to this row; other rows use that
   layer legitimately for their photo backgrounds. */
.page-id-308 .wpb_row:has(form.wsm-contact-form){background:transparent !important}
.page-id-308 .wpb_row:has(form.wsm-contact-form) .upb_row_bg{display:none !important}
.page-id-308 form.wsm-contact-form{
  max-width:100%;margin-inline:auto;
  background:#fff;border:1px solid var(--ajc-line);
  padding:1.9rem 1.8rem;box-sizing:border-box;
}
@media (max-width:778px){
  .page-id-308 form.wsm-contact-form{padding:1.4rem 1.2rem}
}

/* ---------- /review/ (Leave Us A Review) layout ------------------------------
   Owner request 2026-08-09. Same inherited two-column template as
   /customerreviews/: the review form sits in a 6-column at 550px with a
   "Showcase" gallery competing for attention beside it. This is the page the
   client hands to customers in person, so it should be one task, centred, with
   nothing else asking to be clicked.

   Form gets its own full-width band and is centred at a readable measure;
   showcase drops underneath, three across. No content removed, nothing edited
   in the database — the live page is untouched.
   Selectors verified with el.matches(); scoped by page id because the five
   duplicated pages share the same vc_custom_ hashes. */
@media (min-width:779px){
  .page-id-1705 .wpb_column:has(form.wsm-review-form),
  .page-id-1705 .wpb_column:has(form.wsm-review-form) + .wpb_column{
    width:100% !important;float:none !important;
  }
  /* Centre the heading, the intro and the form together as one block, rather
     than centring the form alone and leaving the copy hanging left. */
  .page-id-1705 .wpb_column:has(form.wsm-review-form) > .vc_column-inner > .wpb_wrapper{
    max-width:680px;margin-inline:auto;
  }
  .page-id-1705 .wpb_column:has(form.wsm-review-form) + .wpb_column{margin-top:3rem}
  .page-id-1705 .wpb_column:has(form.wsm-review-form) + .wpb_column .vc_inner > .wpb_column{
    flex:0 0 calc(33.333% - 14px);max-width:calc(33.333% - 14px);
  }
}
/* The form's own 600px cap is narrower than the band it now sits in.
   Boxed as a white card so it reads as the task on the page, distinct from the
   grey notice above it. White-on-white with a hairline rather than another
   tinted panel: two grey boxes stacked would compete, and the form should be
   the thing you land on. */
.page-id-1705 form.wsm-review-form{
  max-width:100%;margin-inline:auto;
  background:#fff;border:1px solid var(--ajc-line);
  padding:1.9rem 1.8rem;box-sizing:border-box;
}
@media (max-width:778px){
  .page-id-1705 form.wsm-review-form{padding:1.4rem 1.2rem}
}

/* "Something not right?" — the route out for an unhappy customer, added
   2026-08-09 in place of the "Discuss your project with us today" CTA that
   used to close this page. Someone who has just had work done is not shopping
   for more, and a public review form is the wrong place to find out a job went
   wrong. Deliberately quiet: an aside above the form, not a warning. The gold
   rule is the only accent, and it must not compete with Submit review.
   Renders as an ordinary paragraph on the live theme, which is fine. */
/* ⚠️ The bottom margin needs !important. WPBakery ships
   `.wpb_text_column p:last-child{margin-bottom:0}`, the notice IS the last
   paragraph in its text block, and js_composer's stylesheet is enqueued after
   this one — so an equally specific rule loses on order and the box sat flush
   against the form with a 0px gap. */
.ajc-review-notice{
  margin:1.6rem 0 2rem;margin-bottom:2rem !important;padding:.9rem 1.1rem;
  background:var(--the7-content-boxes-bg,rgba(0,0,0,.04));
  border-left:3px solid var(--ajc-accent);
  font-size:14px;line-height:24px;color:var(--ajc-ink);
}
.ajc-review-notice strong{color:var(--ajc-accent)}
/* ⚠️ NOT the site link gold. --ajc-link is #ffc000 (The7's links colour), which
   on this box's near-#f5f5f5 background measures about 1.5:1 — effectively
   unreadable, and it fails WCAG AA by a wide margin. The accent is ~12.5:1 on
   the same background. Underlined so the links are still obviously links
   without relying on colour alone. */
.ajc-review-notice a{color:var(--ajc-accent);text-decoration:underline;text-underline-offset:2px}
.ajc-review-notice a:hover{color:var(--ajc-accent);text-decoration-thickness:2px}

/* ---------- confirmation pages (/thanks/, /enquiry-received/) ---------------
   Owner 2026-08-09: "the design is looking off". Both were duplicated from the
   same template as /review/, so both ran their confirmation copy in a
   6-column with a Showcase gallery beside it. Content is now single-column
   (see SWITCHOVER.md); this gives it the same centred, boxed treatment the
   review and contact forms use, so the whole form flow — enquire, confirm,
   review, confirm — looks like one thing rather than four.

   No max-width on the card itself: these are three short paragraphs, and a
   680px measure is about right for reading. */
@media (min-width:779px){
  .page-id-1713 .wpb_column:has(.wpb_text_column) > .vc_column-inner > .wpb_wrapper,
  .page-id-1796 .wpb_column:has(.wpb_text_column) > .vc_column-inner > .wpb_wrapper{
    max-width:680px;margin-inline:auto;
  }
}
.page-id-1713 .wpb_text_column,
.page-id-1796 .wpb_text_column{
  background:#fff;border:1px solid var(--ajc-line);
  padding:1.9rem 1.8rem;box-sizing:border-box;
}
.page-id-1713 .wpb_text_column h2,
.page-id-1796 .wpb_text_column h2{margin-top:0}
@media (max-width:778px){
  .page-id-1713 .wpb_text_column,
  .page-id-1796 .wpb_text_column{padding:1.4rem 1.2rem}
}

/* ---------- /customerreviews/ layout ----------------------------------------
   An improvement on live, by request 2026-08-09. The page was copied from
   another template, so the reviews sit in a 6-column and the right-hand half
   holds a "Showcase" gallery that duplicates /home/showcase/. The consequence
   is measurable: the grid gets 550px, and `repeat(auto-fill,minmax(320px,1fr))`
   can only fit ONE card per row — so twelve reviews become a single tall
   column, paginated at ten, on the page whose entire job is showing reviews.

   Give the reviews the full 1150px (three cards per row) and put the showcase
   underneath, three across instead of two. No content is removed and nothing
   is edited in the database, so the live site is untouched.

   ⚠️ Scoped by page id, NOT by the vc_custom_ hash: this page was duplicated
   from about/review/thanks/enquiry-received and all five share the same
   generated classes. Selectors verified with el.matches() in the browser. */
@media (min-width:779px){
  .page-id-1811 .wpb_column:has(.wsm-reviews-grid),
  .page-id-1811 .wpb_column:has(.wsm-reviews-grid) + .wpb_column{
    width:100% !important;float:none !important;
  }
  .page-id-1811 .wpb_column:has(.wsm-reviews-grid) + .wpb_column{margin-top:2.5rem}
  /* The inner row is already display:flex with six 50% children; at full width
     that would render them enormous. */
  .page-id-1811 .wpb_column:has(.wsm-reviews-grid) + .wpb_column .vc_inner > .wpb_column{
    flex:0 0 calc(33.333% - 14px);max-width:calc(33.333% - 14px);
  }
}

/* Cards take their natural height rather than stretching to the tallest in the
   row. In one column that never showed; in three it does, and "Good job well
   done" was being padded out to the height of a 200-word review with its photo
   stranded in the middle. `flex-grow:1` on the body was what pushed the footer
   down, so that goes too.

   ⚠️ Overrides live in the theme, NOT in the WPCode snippet, so the live site
   keeps its current rendering until switchover. The snippet prints its CSS in
   an inline <style> in the BODY, which beats the stylesheet at equal
   specificity — both of these are deliberately one class more specific than
   the rule they replace. */
.wsm-reviews-wrap .wsm-reviews-grid{align-items:start}
.wsm-review-card .wsm-review-body{flex-grow:0}
/* Reviews vary from one line to two hundred words, so a row-aligned grid leaves
   a ragged band of white under every short card. CSS columns give a true
   masonry wall with no JS — cards flow into the shortest column and the gaps
   close. Reading order becomes column-wise, which is fine for a review wall
   where no card depends on the one before it.
   Below 779px the grid is already a single column, so this only applies up. */
@media (min-width:779px){
  .wsm-reviews-wrap .wsm-reviews-grid{
    display:block;columns:3;column-gap:24px;
  }
  .wsm-reviews-wrap .wsm-review-card{break-inside:avoid;margin-bottom:24px}
}

/* An improvement on live, by request 2026-08-09. /services/ has its title mode
   set to `disabled`, so it has no fancy-header — its banner is the first
   content row instead, and that row's 90px/80px padding is fixed at every
   width. Result: a 232px banner on a phone, where the seven child service
   pages drop their fancy-header to 70px. Live does the same; the owner asked
   for the child pages' proportions.

   16px either side of the 42px heading lands at 74px, against the child pages'
   70px. Desktop is untouched — 232px there is correct and signed off.

   ⚠️ Two classes, both load-bearing. The hash is unique to this row on this
   page (checked), and `.page-content` is needed because WPBakery prints
   `.vc_custom_1778377875667{padding:90px 0 80px !important}` INLINE IN THE
   BODY — an equally specific rule loses on order, so this must out-specify it
   rather than repeat it. */
@media (max-width:778px){
  .page-content .vc_custom_1778377875667{
    padding-top:16px !important;padding-bottom:16px !important;
  }
  /* ⚠️ The last 20px is the heading's OWN margin-bottom, collapsing out through
     .wpb_wrapper, .vc_column-inner and .wpb_column to land on the row — which
     is why the column measures 42px while contributing 62px, and why the title
     sat above centre in the band. Nothing in the chain reports a margin;
     getComputedStyle on each wrapper says 0. Found by zeroing every descendant
     margin-bottom in the browser and watching 94 drop to 74.
     Three guesses missed it first: the clearfix pseudo-elements, an
     inline-block baseline gap, and a wrapper margin. */
  .page-content .vc_custom_1778377875667 h2{margin-bottom:0 !important}
}

/* An improvement on live, by request 2026-08-09. Where the brand bar is the
   LAST row on a page, The7's `#main{padding:80px 0}` leaves an 80px white band
   between the bar and the footer. Most pages never show it because their
   per-page the7_fancy_title_css overrides #main's padding to 0; the two
   showcase pages have no such override, so on live the band is visible there.
   Only those two match this selector — checked all eight pages carrying the
   bar, and on the rest it sits mid-page. `:has()` takes the specificity of its
   argument, so this clears #main (1,0,0) without !important. */
#main:has(.wpb-content-wrapper > .vc_custom_1770143135639:last-child),
#main:has(.wpb-content-wrapper > .ajc-brands:last-child){padding-bottom:0}

/* ---------- brand / accreditation bar ---------------------------------------
   Owner request 2026-08-05: stop porting this row and build it. Same content and
   the same light band as live — weber, Tobermore, K Rend, Gas Safe on #f4f4f4 —
   but laid out as a flex strip instead of four floated quarter-columns.

   Why it is built this way:
   - the logos are sized by HEIGHT, not by a box. All four PNGs share a 429x180
     canvas with the artwork inset, so a common height cap makes them optically
     even without touching the files, and nothing can crop them.
   - no fixed-ratio box anywhere in the chain, so there is no height for a
     stretched ancestor to hand down. This is the row the owner saw magnified 16x.
   - it wraps to 2-up rather than four-in-a-row on tablets and stays 2-up on
     phones, where live stacks all four into a very long strip.

   Hook: the WPBakery-generated class on that row, which is identical on all
   eight pages that carry it. If the row is ever re-saved in the builder the hash
   changes and it falls back to the plain four-column layout — correct, just not
   this treatment. `.ajc-brands` is an alias for marking it by hand later.
-------------------------------------------------------------------------- */
.ajc-brands,
.vc_custom_1770143135639{
  display:flex;flex-wrap:wrap;align-items:center;align-content:center;justify-content:center;
  --ajc-brand-gap:clamp(24px,2.4vw,32px);
  gap:var(--ajc-brand-gap);
  margin:0 !important;
  box-sizing:border-box;
}
/* WPBakery's generated .vc_custom_… rule (padding-top:25px !important) is
   printed in the body, so it wins on order against an equally specific selector
   — this has to out-specify it, not just repeat it. */
/* Live's row measures padding-top:25px, padding-bottom:0 — the symmetric 34px
   here added 43px of dead space and pushed the bar below the fold. */
.page-content .ajc-brands,
.page-content .vc_custom_1770143135639{padding:25px 25px 0 !important}
/* flex-basis 250px, not auto: a flex item's auto basis is its max-content size,
   and the wrapper's max-content is the image's INTRINSIC 429px — a percentage
   max-width doesn't constrain intrinsic sizing. That plus the column's 25px
   gutters made each item 479 wide, so four no longer fit on a 1150 row and it
   broke into 2x2 on desktop. */
/* ⚠️ A FIXED 240px basis wraps as soon as the row is narrower than
   4x240 + 3xgap = 1056px, i.e. below roughly a 1160px viewport — which is a
   perfectly ordinary laptop window, and it broke to 3+1 there. Live never wraps
   because its four floated columns are 25% each. So make the basis
   proportional the same way and keep 240px only as a cap: four items plus three
   gaps must total 100%, so basis = 25% - gap*3/4. */
.ajc-brands > .wpb_column,
.vc_custom_1770143135639 > .wpb_column{
  flex:0 1 calc(25% - (var(--ajc-brand-gap) * 3 / 4));
  max-width:240px;padding:0;margin:0;
}
/* ⚠️ Belt and braces, and deliberately blunt. The owner's browser reported a
   1500px-tall box in this chain twice — first magnifying the logo to fill it,
   then, once the logo could no longer stretch, as ~1500px of empty band. It does
   not reproduce in Chromium at any width, DPI or zoom, and their UA carries no
   `Chrome/`, so it is an engine difference I cannot drive here. Rather than keep
   guessing which rule hands down a height, forbid ALL of them: nothing between
   the column and the logo may take a height from anything but the logo. The
   column keeps its own flex-basis — resetting that would put the item back on
   the image's intrinsic 429px max-content size (see above). */
.ajc-brands > .wpb_column,
.vc_custom_1770143135639 > .wpb_column{height:auto !important;min-height:0 !important}
.ajc-brands > .wpb_column *,
.vc_custom_1770143135639 > .wpb_column *{
  height:auto !important;min-height:0 !important;max-height:none !important;
  flex:0 0 auto !important;align-self:auto !important;
}
/* .page-content .vc_column_container > .vc_column-inner (the gutter rule above)
   is 0,3,0 — this has to match it and win on order. */
.ajc-brands > .wpb_column > .vc_column-inner,
.vc_custom_1770143135639 > .wpb_column > .vc_column-inner{padding:0}
.ajc-brands .wpb_wrapper,
.vc_custom_1770143135639 .wpb_wrapper{display:block}
/* The7's clearfix ::before/::after (content:" ";display:table) become FLEX ITEMS
   here, and the ::after wrapped onto a second line — adding a phantom row-gap
   below the logos and leaving them looking 32px too high in the band.
   !important because js_composer's stylesheet is enqueued AFTER this file, so an
   equally specific rule loses on order. Verified: removing them takes the band
   from 200.7px to 168.7px and the bottom gap from 66 to 34. */
.ajc-brands::before,.ajc-brands::after,
.vc_custom_1770143135639::before,.vc_custom_1770143135639::after{display:none !important}
/* the 32px vc_empty_space after each logo is the row's spacing on live; the band
   supplies its own padding, so it would only push the logos off centre. */
.ajc-brands .vc_empty_space,
.vc_custom_1770143135639 .vc_empty_space{display:none}
/* Sized by WIDTH, matching live's 250px: the artwork is inset in the 429x180
   canvas, so a height cap shrinks the visible logo well below the live size. */
.ajc-brands .shortcode-single-image-wrap,
.vc_custom_1770143135639 .shortcode-single-image-wrap{
  width:100%;max-width:240px;margin-inline:auto;
}
.ajc-brands .fancy-media-wrap,
.vc_custom_1770143135639 .fancy-media-wrap{overflow:visible;line-height:0}
/* All four logos share one 429x180 canvas, so one declared ratio fits them all.
   Declaring it means the height is computed from the width alone — never from
   the image's intrinsic size, which is exactly what went wrong: at the owner's
   1.25 device ratio the browser serves the 300x126 rendition rather than the
   full file, and with no declared ratio Chrome 151 resolved the height to
   1500px. With this, the box is 240x100.7 before a single byte of image has
   loaded, in any browser. */
.ajc-brands img,
.vc_custom_1770143135639 img{
  width:100%;height:auto;
  aspect-ratio:429 / 180;object-fit:contain;
}
/* ⚠️ These must carry the `.page-content` prefix. The desktop padding above is
   `.page-content .vc_custom_…{padding:34px 25px !important}` (0,2,0 + important),
   so a bare `.ajc-brands{…!important}` (0,1,0) LOSES and the mobile padding
   silently never applied — measured: the band still had the desktop 25px inset
   at 414px.
   ⚠️ And the basis subtracts HALF the column-gap, not all of it: two items plus
   one gap must total 100%, so basis = 50% - gap/2. Subtracting the whole gap
   left 24px of slack and made each logo 138px where 155px fits. */
@media (max-width:900px){
  .page-content .ajc-brands,
  .page-content .vc_custom_1770143135639{gap:34px 46px;padding:32px 20px !important}
  .ajc-brands > .wpb_column,
  .vc_custom_1770143135639 > .wpb_column{flex:0 1 calc(50% - 23px)}
}
@media (max-width:480px){
  .page-content .ajc-brands,
  .page-content .vc_custom_1770143135639{gap:26px 24px;padding:26px 20px !important}
  .ajc-brands > .wpb_column,
  .vc_custom_1770143135639 > .wpb_column{flex:0 1 calc(50% - 12px)}
}
