/* Andersens flooring category pages (v1.1)
   Shared by every redesigned product-category archive — carpet (term 23),
   engineered timber (term 24), and the hybrid/vinyl pages to follow.
   Deploy to child theme css/flooring-category.css.

   The .acp prefix is "Andersens category page". Nothing in here is specific to
   one category.

   Conventions deliberately mirror css/store-page.css and css/store-finder.css so
   the redesign pages stay consistent: same palette vars, same full-bleed trick,
   same defensive !important overrides where OceanWP/Elementor fight us, same
   1200/960/640 breakpoints. Display face is Instrument Serif (Brand Guidelines V4) to match the
   Homepage Redesign build (page 17442) and the store page.

   NOTE ON SOURCE: the shared Figma prototype link covers only the
   "Find a Store + Individual Store" flow — it contains no product-category
   frame. Tokens here are lifted verbatim from store-page.css (which WAS built
   to that Figma); the category module layouts are extensions of that system
   and are flagged for design review. */

.acp {
	--acp-cream: #f6f5ef;
	--acp-offwhite: #fbfaf6;
	--acp-panel: #f1f0ea;
	--acp-green: #00833f;
	--acp-green-dark: #0f5230;
	--acp-mint: #2bde81;
	--acp-gold: #ffa400;
	--acp-ink: #000000;
	--acp-muted: #5c5c56;
	--acp-line: #e6e2d6;
	--acp-ph: #dedcd4;          /* placeholder image grey */
	--acp-ph-ink: #8d8b81;
	--acp-serif: var(--and-display);

	/* Full-bleed band — escapes the boxed page container. --acp-vw is set by
	   flooring-category.js to the real viewport width (clientWidth, i.e. minus the
	   scrollbar) so the bleed never overshoots; 100vw is the pre-JS fallback. */
	width: var(--acp-vw, 100vw);
	margin-left: calc(50% - (var(--acp-vw, 100vw) / 2));
	background: var(--acp-offwhite);
	color: var(--acp-ink);
	/* Figma body copy is 14/1.5 (29:879 desktop, 29:953). Was 16/1.6. */
	font-size: 14px;
	line-height: 1.5;
	text-align: left; /* theme centres text at mobile widths — design is left-aligned */
}

/* The 100vw breakout can add ~15px of horizontal scroll unless the page clips it. */
body:has(.acp) { overflow-x: clip; }

/* -------------------------------------------------------------------------
   ELEMENTOR CONTAINER RESET
   Rewritten 20 August 2026 after two failed attempts. Read the note before
   changing it, because the specificity here is load-bearing.

   Elementor styles containers through CSS variables consumed by TWO-class
   selectors:

       .e-con.e-flex                    { --flex-direction: column }
       .e-con-full.e-flex               { flex-direction: var(--flex-direction) }
       .elementor-element:where(...)    { flex-direction: var(--flex-direction) }

   Two classes beats one, so NO single-class .acp rule can win, whatever the
   load order. That is why .acp-rail{display:flex} kept coming out as a column
   and stacked six 300px cards into a 3386px tower.

   What actually works is to accept Elementor's model and set the variables at
   matching-or-higher specificity. Which is easier than it sounds, because
   Elementor's default of flex-direction:column reproduces exactly what a plain
   block div did: children stacked in order, full width. That is why most of the
   page was already correct. Only the handful of containers that need a
   horizontal row are wrong, and those are listed at the end of this file.

   So this block is deliberately small. It does NOT force display:block, and it
   does NOT set flex-direction globally. Both were earlier mistakes:

     - forcing display:block fought Elementor's per-element --display:flex,
       which is written into the page's own stylesheet at three-class
       specificity and cannot be beaten from here;
     - forcing flex-direction:row turned every stacked section into a row.
   ---------------------------------------------------------------------- */

/* Elementor's 20px inter-widget gap is not part of this design. Set on the
   variables, at two classes, so it beats .e-con.e-flex's own defaults. */
.acp .e-con.e-flex,
.acp .e-con-full.e-flex {
	--gap: 0px;
	--row-gap: 0px;
	--column-gap: 0px;
}

/* Elementor's container max-width would cap a full-bleed band. */
:where(.acp) .e-con { max-width: none; }

/* NOT display:contents on .elementor-widget-container.
   It looked like harmless scaffolding removal, but Elementor's tabs widget
   needs that box to size its grid: with it flattened, the content column
   resolved to 0px and one panel ballooned to 9085px as every line wrapped.
   The image and heading mirrors below use descendant selectors, so they never
   needed the wrapper flattened in the first place. */
:where(.acp) .elementor-widget-container { min-width: 0; }

/* A card that became a linked container keeps card styling, not link styling. */
:where(.acp) a.e-con { text-decoration: none; color: inherit; }

.acp-wrap {
	max-width: 1560px;
	margin: 0 auto;
	padding: 0 30px;
}
.acp-wrap-narrow { max-width: 980px; }

/* Shared type -------------------------------------------------------------- */

.acp .acp-eyebrow {
	color: var(--acp-gold);
	font-family: inherit;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	margin: 0 0 14px;
	line-height: 0.95;
}

.acp h1.acp-h1,
.acp h2.acp-h2 {
	font-family: var(--acp-serif);
	/* Instrument Serif ships in 400 only; 600 was faux-bolding every heading.
	   Figma (7 Sep 2026) specifies Regular, 0.95 leading and no tracking. */
	font-weight: 400;
	color: var(--acp-green);
	line-height: 0.95;
	letter-spacing: 0;
	margin: 0;
	text-transform: none;
}
.acp h1.acp-h1 { font-size: clamp(52px, calc(45.7126px + 1.56403vw), 68px); /* 52@402 -> 68@1425 */ }
/* H2 is its OWN ramp. Figma draws section headings at 48 (29:878) and 36 on
   mobile (58:1464) with 1.05 leading - not the H1's 68/0.95. Sharing the H1
   clamp made every section heading the same size as the page title.
   36 at 402 -> 48 at 1425. 1425 not 1440: vw resolves against the layout
   width once the scrollbar is out (same reason as the about-band ramp). */
.acp h2.acp-h2 { font-size: clamp(36px, calc(31.2844px + 1.17302vw), 48px); line-height: 1.05; }
.acp .acp-h1 em,
.acp .acp-h2 em { font-style: normal; color: var(--acp-mint); }

.acp h3.acp-h3 {
	font-family: var(--acp-serif);
	font-weight: 400;
	font-size: 32px;
	line-height: 1.4;
	letter-spacing: -0.03em;
	color: var(--acp-green);
	margin: 0 0 12px;
	text-transform: none;
}
.acp h4.acp-h4 {
	/* Explicit, not `inherit`: on a converted page an Elementor ancestor supplies
	   the serif, and h4 at 700 then faux-bolds a face that only ships 400. */
	font-family: var(--and-text);
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
	color: var(--acp-green);
	margin: 0 0 8px;
	text-transform: none;
	letter-spacing: 0;
}

/* <h3 class="acp-h4"> never matches `.acp h4.acp-h4` above, so these headings
   were taking the theme's #333, which is in no palette. The base rule already
   says green; this is what makes it land, whatever the tag. */
.acp .acp-h4 { color: var(--acp-green); }
/* ...and on the green grounds they invert, exactly as .acp-h2/.acp-h3 do. */
.acp .acp-green-card .acp-h4,
.acp .acp-final-card .acp-h4,
.acp .acp-on-green .acp-h4 { color: #fff; }
.acp .acp-green-card .acp-h4 em,
.acp .acp-final-card .acp-h4 em,
.acp .acp-on-green .acp-h4 em { color: var(--acp-mint); }

.acp .acp-lede { color: var(--acp-ink); margin: 0; }
.acp .acp-lede-lg { font-size: 14px; }
.acp .acp-hero-lede { line-height: 1.2; } /* Figma 29:757 */
/* NOTE: `.acp p` is (0,1,1) and `.acp .acp-lede` is (0,2,0). Both outrank a bare
   single class, so any paragraph modifier below that sets its own margin must be
   written as `.acp .modifier` or it will silently lose. */
.acp p { margin: 0 0 16px; }
.acp p:last-child { margin-bottom: 0; }

/* Section heads */
.acp-head { max-width: 780px; margin: 0 0 48px; }
.acp-head .acp-lede { margin-top: 22px; }
.acp-head-centre { margin-left: auto; margin-right: auto; text-align: center; }
.acp .acp-head-centre .acp-eyebrow,
.acp .acp-head-centre .acp-h2,
.acp .acp-head-centre .acp-lede { text-align: center !important; }

/* Buttons ------------------------------------------------------------------ */
/* Pill CTAs. Exactly one solid green button per section — the CTA hierarchy is
   primary (solid) / secondary (outline) / supporting (arrow link). */

.acp .acp-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	/* Figma 29:881/29:895/29:925/29:928 are all 37 tall, pad 10/20, Inter 600 14.
	   NOTE: 37px is BELOW the 44px WCAG 2.5.5 target size that the old 52px met.
	   Adopted at Bron's explicit direction, 9 September 2026, after the trade-off
	   was put to them. Revisit if an accessibility audit flags it. */
	min-height: 37px;
	/* Figma labels are whitespace-nowrap; without flex:none the 320px cap on
	   .acp-hero .acp-actions shrinks these to min-content and wraps the label. */
	flex: 0 0 auto;
	white-space: nowrap;
	padding: 10px 20px;
	border-radius: 999px;
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	text-align: center;
	text-decoration: none;
	border: 1.5px solid var(--acp-green);
	background: var(--acp-green);
	color: #fff;
	cursor: pointer;
	transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.acp .acp-btn:hover,
.acp .acp-btn:focus-visible { background: var(--acp-green-dark); border-color: var(--acp-green-dark); color: #fff; }

.acp .acp-btn-outline { background: transparent; color: var(--acp-green); }
.acp .acp-btn-outline:hover,
.acp .acp-btn-outline:focus-visible { background: var(--acp-green); color: #fff; }

/* On the green CTA band the outline button has to invert. */
.acp .acp-on-green .acp-btn { background: #fff; border-color: #fff; color: var(--acp-green); }
.acp .acp-on-green .acp-btn:hover,
.acp .acp-on-green .acp-btn:focus-visible { background: var(--acp-cream); border-color: var(--acp-cream); color: var(--acp-green-dark); }
.acp .acp-on-green .acp-btn-outline { background: transparent; border-color: #fff; color: #fff; }
.acp .acp-on-green .acp-btn-outline:hover,
.acp .acp-on-green .acp-btn-outline:focus-visible { background: #fff; color: var(--acp-green); }

/* Arrow link */
.acp .acp-arrow {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	/* 24px floor for WCAG 2.2 (2.5.8): at 12px with `normal` leading the text
	   box is only ~15px, so the min-height is what keeps the target legal. */
	min-height: 24px;
	color: var(--acp-green);
	/* Figma 29:937 / 29:824: Inter SemiBold 12, leading normal. */
	font-size: 12px;
	font-weight: 600;
	line-height: normal;
	text-decoration: none;
	border-bottom: 1px solid currentColor;
	padding-bottom: 2px;
}
.acp .acp-arrow:hover { color: var(--acp-green-dark); }
.acp .acp-arrow svg { flex: none; width: 18px; height: auto; } /* Figma icon frame is 18px */

.acp-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; }

/* Visible keyboard focus everywhere — OceanWP suppresses outlines. */
.acp a:focus-visible,
.acp button:focus-visible,
.acp summary:focus-visible,
.acp [tabindex]:focus-visible {
	outline: 3px solid var(--acp-mint) !important;
	outline-offset: 2px;
	border-radius: 4px;
}

/* Placeholder images ------------------------------------------------------- */
/* Grey boxes stand in for photography until real assets are supplied. Marked
   aria-hidden in the markup so screen readers skip them. */
.acp-ph {
	background: var(--acp-ph);
	border-radius: 14px;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 6px;
	text-align: center;
	padding: 20px;
	color: var(--acp-ph-ink);
	overflow: hidden;
}
.acp-ph b {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	line-height: 1.5;
}
.acp-ph span { font-size: 11px; letter-spacing: 0.06em; opacity: 0.85; }


/* Real imagery -------------------------------------------------------------- */
/* .acp-media is the drop-in replacement for a grey .acp-ph once a real asset
   exists. It takes the same box from the sizing rules above, and the <img>
   fills it with object-fit so a supplied photo is never stretched, whatever its
   native aspect ratio. object-position can be tuned per slot if a crop lands
   badly, which is cheaper than re-exporting the asset. */
.acp-media {
	position: relative;
	overflow: hidden;
	border-radius: 14px;
	background: var(--acp-ph);
}
/* Specificity note: the curtains block lower down styles bare `.acp-img`
   elements with explicit per-context heights, e.g. `.acp-tile img.acp-img`
   at (0,2,1). A plain `.acp-media .acp-img` is (0,2,0) and loses to it, which
   left tile images 290px tall inside a 370px wrapper between 641 and 960px.
   `.acp .acp-media > .acp-img` is (0,3,1) and wins, so a wrapped image always
   takes its size from the wrapper and the two mechanisms can coexist. */
.acp .acp-media > .acp-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center center;
}

/* 1. Breadcrumbs ----------------------------------------------------------- */

.acp-crumbs { background: var(--acp-cream); padding: 22px 0 0; }
.acp-crumbs ol {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: 13px;
	color: var(--acp-muted);
}
.acp-crumbs li { display: flex; align-items: center; gap: 8px; }
.acp-crumbs li + li::before { content: '/'; color: var(--acp-line); }
/* Vertical padding lifts the crumb links to a 24px hit area without changing
   the visual rhythm of the trail. */
.acp-crumbs a,
.acp-crumbs [aria-current='page'] { display: inline-flex; align-items: center; min-height: 24px; }
.acp-crumbs a { color: var(--acp-green); text-decoration: none; border-bottom: 1px solid transparent; }
.acp-crumbs a:hover { border-bottom-color: currentColor; }
.acp-crumbs [aria-current='page'] { color: var(--acp-muted); }

/* 2. Hero ------------------------------------------------------------------ */

.acp-hero { background: var(--acp-cream); padding: 40px 0 90px; }
.acp-hero-grid {
	display: grid;
	grid-template-columns: minmax(0, 480px) minmax(0, 1fr);
	gap: 54px;
	align-items: center;
}
.acp-hero-copy { display: flex; flex-direction: column; }
.acp .acp-hero-lede { margin: 26px 0 0; max-width: 34em; }
/* The three hero actions need 733px and the copy column is 480px, so they always
   wrap. Left to itself the wrap put the tertiary arrow link on the same line as
   the secondary pill, where it read as a third button and broke the intended
   solid > outline > text-link hierarchy. Stacking the two pills at a common
   width gives a tidy left edge and keeps the priority order unmistakable. */
.acp-hero .acp-actions {
	flex-direction: column;
	align-items: stretch;
	gap: 14px;
	margin-top: 34px;
	max-width: 320px;
}

/* Tertiary action and catalogue size sit together below the pills, so the count
   reads as context for "View Carpet Range" rather than dangling off the
   showroom button. */
.acp-hero-meta {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px 18px;
	margin-top: 24px;
}
.acp-hero-media .acp-ph,
.acp-hero-media .acp-media,
.acp-hero-media img {
	display: block;
	width: 100%;
	height: 100%;
	min-height: 560px;
	border-radius: 15px;
	object-fit: cover;
}
/* Needs the .acp prefix to win: `.acp p` is (0,1,1) and outranks a bare class,
   which was silently zeroing the margin on this line. */
.acp .acp-hero-count {
	margin: 0;
	/* Eyebrow furniture: Figma 29:880. */
	font-size: 10px;
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--acp-gold);
}

/* 3. Decision pathways ---------------------------------------------------- */

.acp-paths { background: var(--acp-offwhite); padding: 78px 0 20px; }

/* Rails bleed to the right edge like the design; scroll-snap does the paging. */
.acp-rail {
	display: flex;
	gap: 22px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
	padding: 4px 30px 4px 0;
	margin: 0;
	list-style: none;
}
.acp-rail::-webkit-scrollbar { display: none; }
.acp-rail > li { scroll-snap-align: start; flex: 0 0 auto; }

.acp-tile { width: 300px; position: relative; display: block; text-decoration: none; }
.acp-tile .acp-ph,
.acp-tile .acp-media { height: 370px; border-radius: 14px; }
/* Notched white corner carrying the label, matching the store page's room device. */
.acp-tile-label {
	position: absolute;
	top: 0;
	right: 0;
	background: var(--acp-offwhite);
	border-bottom-left-radius: 18px;
	border-top-right-radius: 14px;
	padding: 6px 10px 12px 18px;
	font-family: var(--acp-serif);
	font-weight: 400;
	font-size: 27px;
	line-height: 1.1;
	color: var(--acp-green);
	max-width: 82%;
}
.acp-tile-note {
	margin: 14px 0 0;
	font-size: 14px;
	color: var(--acp-muted);
	line-height: 1.5;
}
.acp-tile:hover .acp-tile-label { color: var(--acp-green-dark); }

/* Carousel controls (shared by every rail) */
/* js/flooring-category.js sets foot.hidden when the rail fits entirely, but a
   bare [hidden] loses to the .acp-rail-foot display rule below, so the foot
   kept rendering as an empty dot strip and two disabled arrows. This restores
   the documented auto-hide. It can only apply where the JS has already decided
   the controls are not worth showing. */
.acp-rail-foot[hidden] { display: none; }

.acp-rail-foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
	margin: 24px 0 0;
}
.acp-dots { display: flex; align-items: center; gap: 8px; }
/* The design's progress indicator is a 4px dash, which on its own is far below
   the WCAG 2.2 (2.5.8) 24px minimum target size. The button is therefore 24px
   tall with a transparent background and the dash drawn as a pseudo-element, so
   the hit area is compliant while the visual matches the design. */
.acp-dot {
	width: 22px;
	height: 24px;
	border: 0;
	padding: 0;
	background: none;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	transition: width 0.2s ease;
}
.acp-dot::before {
	content: '';
	display: block;
	width: 100%;
	height: 4px;
	border-radius: 999px;
	background: #2f2f2b;
	opacity: 0.55;
	transition: background 0.2s ease, opacity 0.2s ease;
}
.acp-dot[aria-current='true'] { width: 66px; }
.acp-dot[aria-current='true']::before { background: var(--acp-mint); opacity: 1; }

.acp-navs { display: flex; gap: 12px; }
.acp-nav {
	width: 58px;
	height: 38px;
	border: 1.5px solid var(--acp-green);
	border-radius: 999px;
	background: transparent;
	color: var(--acp-green);
	display: inline-flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	padding: 0;
}
.acp-nav:hover { background: var(--acp-green); color: #fff; }
.acp-nav[disabled] { opacity: 0.35; cursor: default; }
.acp-nav[disabled]:hover { background: transparent; color: var(--acp-green); }

/* 4. Product range wrapper ------------------------------------------------- */
/* The archive itself is rendered by the existing Unlimited Elements widgets in
   the Elementor template. This only supplies the band, the heading and a light
   restyle of the widgets' own chrome — the widgets are NOT rebuilt. */

.acp-range { background: var(--acp-offwhite); padding: 84px 0 40px; scroll-margin-top: 90px; }

/* 5. Why choose <category> ---------------------------------------------------- */

.acp-why { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
	gap: 54px;
	align-items: center;
}
.acp-split-media .acp-ph,
.acp-split-media .acp-media { min-height: 520px; border-radius: 15px; }
.acp-benefits { list-style: none; margin: 30px 0 0; padding: 0; }
.acp-benefits li {
	padding: 20px 0;
	border-top: 1px solid var(--acp-line);
}
.acp-benefits li:last-child { border-bottom: 1px solid var(--acp-line); }
.acp-benefits p { margin: 0; font-size: 14px; color: var(--acp-ink); } /* Figma 29:879: 14 / black */

/* Contextual CTA strip */
.acp-cta-strip {
	background: var(--acp-panel);
	border-radius: 16px;
	padding: 34px 38px;
	margin: 54px 0 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}
.acp .acp-cta-strip .acp-h3 { margin: 0; }

/* 6. Rooms (tabs) --------------------------------------------------------- */

.acp-rooms { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-tabs { display: grid; grid-template-columns: minmax(0, 280px) minmax(0, 1fr); gap: 46px; align-items: start; }
.acp-tablist { display: flex; flex-direction: column; gap: 4px; }
.acp-tab {
	appearance: none;
	border: 0;
	background: transparent;
	text-align: left;
	font-family: var(--acp-serif);
	font-size: 22px;
	font-weight: 400;
	line-height: 1.2;
	color: var(--acp-green);
	padding: 13px 16px;
	border-radius: 12px;
	cursor: pointer;
	min-height: 48px;
	/* Selected state carries a left bar as well as a background, so it never
	   depends on colour alone. */
	border-left: 3px solid transparent;
}
.acp-tab:hover { background: rgba(20, 104, 62, 0.06); }
.acp-tab[aria-selected='true'] {
	background: #fff;
	border-left-color: var(--acp-mint);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
.acp-panel {
	background: #fff;
	border-radius: 18px;
	padding: 38px 40px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
.acp-panel[hidden] { display: none; }
.acp-panel-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 30px; margin: 0 0 24px; }
/* Follows the eyebrow (Figma 29:880): 10px, 2px tracking. 0.2em of 10px IS 2px. */
.acp .acp-meta-label {
	font-size: 10px;
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--acp-gold);
	margin: 0 0 8px;
}
.acp-tip {
	background: var(--acp-panel);
	border-radius: 12px;
	padding: 18px 20px;
	font-size: 15px;
}
.acp-tip p { margin: 0; }

/* Wet-area caution callout */
.acp-caution {
	margin: 34px 0 0;
	background: #fff;
	border-radius: 16px;
	border-left: 4px solid var(--acp-gold);
	padding: 24px 28px;
	font-size: 15px;
}
.acp-caution p { margin: 0; }

/* 7. Styles / 8. Fibres --------------------------------------------------- */

.acp-styles { background: var(--acp-offwhite); padding: 90px 0 30px; }
.acp-style-card { width: 320px; }
.acp-style-card .acp-ph,
.acp-style-card .acp-media { height: 240px; border-radius: 14px; margin: 0 0 18px; }
.acp-style-card p { font-size: 15px; color: var(--acp-muted); }
.acp-chip {
	display: inline-block;
	background: var(--acp-panel);
	border-radius: 999px;
	padding: 5px 13px;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--acp-green);
	margin: 0 6px 6px 0;
}

.acp-fibres { background: var(--acp-offwhite); padding: 80px 0 100px; }

/* Tables ------------------------------------------------------------------ */
/* OceanWP restyles tables hard, hence the !important resets. Both tables become
   stacked definition blocks under 960px rather than scrolling sideways. */

.acp-table-scroll { overflow-x: auto; }
.acp table.acp-table {
	width: 100%;
	border-collapse: collapse;
	margin: 0;
	font-size: 15px;
	background: none !important;
	border: 0 !important;
}
.acp .acp-table caption {
	caption-side: top;
	text-align: left;
	font-size: 13px;
	color: var(--acp-muted);
	padding: 0 0 14px;
}
.acp .acp-table th,
.acp .acp-table td {
	background: none !important;
	border: 0 !important;
	border-bottom: 1px solid var(--acp-line) !important;
	padding: 16px 18px !important;
	text-align: left;
	vertical-align: top;
	color: var(--acp-ink);
}
.acp .acp-table thead th {
	font-family: var(--acp-serif);
	font-size: 21px;
	font-weight: 400;
	color: var(--acp-green);
	border-bottom: 1.5px solid var(--acp-green) !important;
	white-space: nowrap;
}
.acp .acp-table tbody th {
	font-family: inherit;
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--acp-muted);
	width: 190px;
}
.acp .acp-table tbody tr:last-child th,
.acp .acp-table tbody tr:last-child td { border-bottom: 0 !important; }

/* 9. Cost + underlay ------------------------------------------------------ */

.acp-cost { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px 46px; }
.acp-ticks { list-style: none; margin: 0; padding: 0; }
.acp-ticks li {
	position: relative;
	padding: 0 0 12px 26px;
	/* Figma body 29:879: 14 / 150%. */
	font-size: 14px;
}
.acp-ticks li::before {
	content: '';
	position: absolute;
	left: 0;
	top: 8px;
	width: 8px;
	height: 8px;
	border-radius: 999px;
	background: var(--acp-mint);
}
.acp-inset {
	background: #fff;
	border-radius: 18px;
	padding: 34px 36px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	margin: 40px 0 0;
}

/* 10. Comparison ---------------------------------------------------------- */

.acp-compare { background: var(--acp-offwhite); padding: 90px 0 100px; }

/* 11. Process ------------------------------------------------------------- */

.acp-process { background: var(--acp-panel); padding: 90px 0 100px; }
.acp-steps {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 26px;
}
.acp-step {
	background: var(--acp-offwhite);
	border-radius: 15px;
	padding: 26px 24px 24px;
}
.acp-step-n {
	font-family: var(--acp-serif);
	font-size: 40px;
	font-weight: 400;
	line-height: 1;
	color: var(--acp-mint);
	display: block;
	margin: 0 0 12px;
}
.acp-step p { margin: 0; font-size: 14px; color: var(--acp-ink); } /* Figma 29:879 */
.acp .acp-note { margin: 30px 0 0; font-size: 14px; color: var(--acp-ink); max-width: 62em; }

/* 12. Care ---------------------------------------------------------------- */

.acp-care { background: var(--acp-offwhite); padding: 90px 0 100px; }

/* 13. Why Andersens ------------------------------------------------------- */

.acp-trust { background: var(--acp-offwhite); padding: 20px 0 100px; }
.acp-feature-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 26px;
	align-items: start;
}
/* The cards used to step down the page. Flattened to a single row on
   16 September 2026 at Bron's direction, across every section that uses
   this grid. */
.acp-feature-grid > *:nth-child(2),
.acp-feature-grid > *:nth-child(3) { margin-top: 0; }
.acp-feature {
	/* Figma 29:818 and 29:933 are white at 90%, as the homepage cards are. */
	background: rgba(255, 255, 255, 0.9);
	/* Figma 29:818: radius 15, 10px mount around the picture. */
	border-radius: 15px;
	padding: 10px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
.acp-feature .acp-ph,
.acp-feature .acp-media { height: 260px; border-radius: 10px; }
/* 10 card + 15 = Figma's 25px copy inset (29:823 at x520 in a card at x495). */
.acp-feature-body { padding: 20px 15px 14px; }
.acp-feature-body p { margin: 0 0 18px; font-size: 14px; line-height: 1.4; color: var(--acp-ink); } /* Figma 29:935 */

/* 14. Local ---------------------------------------------------------------- */

.acp-local { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-local-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 430px); gap: 40px; align-items: center; }
.acp-green-card {
	background: var(--acp-green);
	border-radius: 15px; /* Figma 29:883 */
	padding: 40px 38px;
	color: #fff;
}
.acp .acp-green-card .acp-eyebrow { color: #fff; }
.acp .acp-green-card .acp-h2,
.acp .acp-green-card .acp-h3 { color: #fff; }
.acp .acp-green-card .acp-h2 em,
.acp .acp-green-card .acp-h3 em { color: var(--acp-mint); }
.acp .acp-green-card p { color: #fff; }
.acp-green-card .acp-actions { margin-top: 28px; }

/* 15. FAQs ---------------------------------------------------------------- */
/* <details>/<summary> so every answer is in the rendered HTML and keyboard
   operable with no JS. */

.acp-faq { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-faq-list { border-top: 1px solid var(--acp-line); }
.acp-faq details { border-bottom: 1px solid var(--acp-line); }
.acp-faq summary {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 20px;
	cursor: pointer;
	padding: 24px 4px;
	list-style: none;
	font-family: var(--acp-serif);
	/* Figma's serif scale is 68/48/32 - 24 was not one of them. This is the
	   32px step, same as .acp-h3, which is flat at every width. */
	font-size: 32px;
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: -0.03em;
	color: var(--acp-green);
	min-height: 48px;
}
.acp-faq summary::-webkit-details-marker { display: none; }
.acp-faq summary::after {
	content: '';
	flex: none;
	width: 13px;
	height: 13px;
	margin-top: 8px;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
	transition: transform 0.2s ease;
}
.acp-faq details[open] summary::after { transform: rotate(-135deg); }
.acp-faq .acp-faq-a { padding: 0 4px 26px; max-width: 72em; font-size: 14px; } /* Figma body 29:879 */
.acp-faq .acp-faq-a p:last-child { margin-bottom: 0; }

/* 16. Guides -------------------------------------------------------------- */

.acp-guides { background: var(--acp-offwhite); padding: 20px 0 100px; }
.acp-guide-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 26px; }
.acp-guide {
	display: block;
	background: rgba(255, 255, 255, 0.9);
	/* Figma 29:818: radius 15, 10px mount around the picture. */
	border-radius: 15px;
	padding: 10px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	text-decoration: none;
}
.acp-guide .acp-ph,
.acp-guide .acp-media { height: 190px; border-radius: 10px; }
/* 10 card + 15 = Figma's 25px copy inset. */
.acp-guide-body { padding: 18px 15px 12px; }
.acp-guide p { margin: 0; font-size: 14px; line-height: 1.4; color: var(--acp-ink); } /* Figma 29:935 */

/* 17. Final CTA ----------------------------------------------------------- */

.acp-final { background: var(--acp-offwhite); padding: 0 0 90px; }
.acp-final-card {
	background: var(--acp-green);
	border-radius: 15px; /* Figma 29:883 */
	padding: 78px 40px 82px;
	text-align: center;
	color: #fff;
}
.acp .acp-final-card .acp-eyebrow,
.acp .acp-final-card .acp-h2,
.acp .acp-final-card p { color: #fff; text-align: center !important; }
.acp .acp-final-card .acp-h2 em { color: var(--acp-mint); }
.acp-final-card p { margin: 24px auto 0; max-width: 46em; }
.acp-final-card .acp-actions { justify-content: center; margin-top: 34px; }

/* Theme/Elementor centre headings and paragraphs at narrow widths, and OceanWP
   restyles tables — pin the elements the design needs left-aligned. */
.acp .acp-eyebrow,
.acp .acp-h1,
.acp .acp-h2,
.acp .acp-h3,
.acp .acp-h4,
.acp .acp-lede,
.acp .acp-tile-label,
.acp .acp-tile-note,
.acp .acp-meta-label,
.acp .acp-benefits p,
.acp .acp-step p,
.acp .acp-feature-body p,
.acp .acp-faq summary,
.acp .acp-faq-a,
.acp .acp-guide p,
.acp .acp-ticks li,
.acp .acp-tip p,
.acp .acp-caution p { text-align: left !important; }
.acp .acp-head-centre .acp-eyebrow,
.acp .acp-head-centre .acp-h2,
.acp .acp-head-centre .acp-lede,
.acp .acp-final-card .acp-h2,
.acp .acp-final-card p { text-align: center !important; }

/* Reduced motion ---------------------------------------------------------- */

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

/* Responsive -------------------------------------------------------------- */

@media (max-width: 1200px) {
	.acp-hero-grid { grid-template-columns: minmax(0, 380px) minmax(0, 1fr); gap: 36px; }
	.acp-split { gap: 36px; }
	.acp-tabs { grid-template-columns: minmax(0, 240px) minmax(0, 1fr); gap: 30px; }
	.acp-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.acp-feature-grid > *:nth-child(2),
	.acp-feature-grid > *:nth-child(3) { margin-top: 0; }
	.acp-local-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 380px); }
}

@media (max-width: 960px) {
	.acp-wrap { padding: 0 20px; }

	.acp-hero { padding: 26px 0 60px; }
	.acp-hero-grid { grid-template-columns: 1fr; gap: 28px; }
	.acp-hero-media { order: -1; }
	.acp-hero-media .acp-ph,
	.acp-hero-media .acp-media,
	.acp-hero-media img { min-height: 260px; }
	.acp-hero .acp-actions { margin-top: 26px; }

	.acp-paths { padding: 60px 0 10px; }
	.acp-range { padding: 60px 0 30px; }
	.acp-why,
	.acp-rooms,
	.acp-cost,
	.acp-compare,
	.acp-process,
	.acp-care,
	.acp-local,
	.acp-faq { padding: 60px 0 70px; }
	.acp-styles { padding: 60px 0 20px; }
	.acp-fibres { padding: 50px 0 70px; }
	.acp-trust,
	.acp-guides { padding: 10px 0 70px; }

	.acp-rail { padding-right: 20px; }
	.acp-split { grid-template-columns: 1fr; }
	.acp-split-media { order: -1; }
	.acp-split-media .acp-ph,
	.acp-split-media .acp-media { min-height: 280px; }
	.acp-cols { grid-template-columns: 1fr; gap: 0; }
	.acp-cta-strip { padding: 26px 24px; }
	.acp-inset { padding: 26px 24px; }

	/* A 240px vertical rail plus a panel does not fit. The tablist becomes a
	   horizontal snap rail of chips above the panel — still a real tablist, so
	   the ARIA wiring and arrow-key behaviour are unchanged. */
	.acp-tabs { grid-template-columns: 1fr; gap: 18px; }
	.acp-tablist {
		flex-direction: row;
		gap: 10px;
		overflow-x: auto;
		scroll-snap-type: x mandatory;
		scrollbar-width: none;
		padding: 2px 20px 2px 0;
		margin-right: -20px;
	}
	.acp-tablist::-webkit-scrollbar { display: none; }
	.acp-tab {
		flex: 0 0 auto;
		scroll-snap-align: start;
		background: #fff;
		border-radius: 999px;
		border-left: 0;
		border-bottom: 3px solid transparent;
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
		font-size: 18px;
		padding: 11px 20px;
	}
	.acp-tab[aria-selected='true'] { border-left-color: transparent; border-bottom-color: var(--acp-mint); }
	.acp-panel { padding: 26px 22px; border-radius: 14px; }
	.acp-panel-grid { grid-template-columns: 1fr; gap: 20px; margin-bottom: 20px; }

	.acp-steps { grid-template-columns: 1fr; gap: 14px; }
	.acp-feature-grid { grid-template-columns: 1fr; gap: 20px; }
	.acp-feature-grid > *:nth-child(2),
	.acp-feature-grid > *:nth-child(3) { margin-top: 0; }
	.acp-guide-grid { grid-template-columns: 1fr; }
	.acp-local-grid { grid-template-columns: 1fr; gap: 26px; }
	.acp-green-card { padding: 30px 26px; }
	.acp-final-card { padding: 56px 24px 60px; }

	/* Stacked tables. Each row becomes a labelled block; the header row is
	   dropped and re-exposed per cell via data-label. */
	.acp-table-stack thead { display: none; }
	.acp-table-stack tbody,
	.acp-table-stack tr,
	.acp-table-stack th,
	.acp-table-stack td { display: block; width: auto !important; }
	/* The table itself must keep full width. Shrink-wrapping it collapses the
	   caption to min-content — a one-word-per-line sliver down the left edge. */
	.acp-table-stack { display: block; width: 100% !important; }
	.acp .acp-table-stack caption { display: block; width: 100%; padding-bottom: 18px; }
	.acp-table-stack tr {
		background: #fff;
		border-radius: 14px;
		padding: 6px 18px 14px;
		margin: 0 0 14px;
		box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	}
	.acp .acp-table-stack th,
	.acp .acp-table-stack td { border-bottom: 0 !important; padding: 10px 0 !important; }
	.acp .acp-table-stack tbody th {
		width: auto;
		padding-top: 14px !important;
		color: var(--acp-green);
		font-size: 12px;
	}
	.acp .acp-table-stack td::before {
		content: attr(data-label);
		display: block;
		font-size: 11px;
		font-weight: 700;
		letter-spacing: 0.16em;
		text-transform: uppercase;
		color: var(--acp-gold);
		margin: 0 0 4px;
	}
}

@media (max-width: 640px) {
	.acp { font-size: 15px; }
	.acp-tile { width: 240px; }
	.acp-tile .acp-ph,
	.acp-tile .acp-media { height: 290px; }
	.acp-tile-label { font-size: 22px; }
	.acp-style-card { width: 258px; }
	/* js/flooring-category.js sets foot.hidden when the rail fits entirely, but a
   bare [hidden] loses to the .acp-rail-foot display rule below, so the foot
   kept rendering as an empty dot strip and two disabled arrows. This restores
   the documented auto-hide. It can only apply where the JS has already decided
   the controls are not worth showing. */
.acp-rail-foot[hidden] { display: none; }

.acp-rail-foot { flex-direction: column; align-items: flex-start; gap: 16px; }
	.acp-cta-strip { flex-direction: column; align-items: flex-start; }
	.acp-actions { width: 100%; }
	.acp .acp-btn { width: 100%; }
	/* Let the stacked hero pills use the full column rather than the 320px cap. */
	.acp-hero .acp-actions { max-width: none; }
	.acp-final-card { padding: 44px 20px 48px; }
}

/* =========================================================================
   Free measure and quote (page 16203)
   =========================================================================
   The conversion page for the site's primary CTA, rebuilt on this same design
   layer rather than in a second style. It reuses the hero, split, process,
   ticks, green card, feature grid, FAQ, guide and final-CTA components above;
   the only new work is the booking band and the Gravity Forms restyle.

   THE FORM IS NOT TOUCHED. Gravity Form 10 and its Elementor widget keep every
   setting they have, including the widget's own orange button and grey inset
   inputs. Those are overridden here, from the page, which is why the visual
   properties below carry !important: the widget's Custom CSS
   (div.gform_wrapper input:not(...), 0-2-2) and Elementor's generated
   per-element rules both outrank a plain two-class selector. Same defensive
   convention as the OceanWP table overrides further up this file. */

/* The supporting arrow link has to invert on green as well as the buttons. */
.acp .acp-on-green .acp-arrow { color: #fff; }
.acp .acp-on-green .acp-arrow:hover,
.acp .acp-on-green .acp-arrow:focus-visible { color: var(--acp-cream); }

/* Hero and booking band are both cream and run together as one field, so the
   hero does not need its usual 90px foot. */
.acp-fmq .acp-hero { padding-bottom: 56px; }

/* .acp-local is cream and .acp-trust is built to follow another offwhite
   section, so its 20px top would butt the two bands together here. */
.acp-fmq .acp-trust { padding-top: 90px; }

/* Anchor targets clear the sticky header. */
.acp-fmq .acp-formband,
.acp-fmq .acp-process { scroll-margin-top: 90px; }

/* Booking band -------------------------------------------------------------
   Split across two elements: .acp-formband carries the heading inside the
   shortcode's .acp block, and .acp-formhost is the Elementor container holding
   the form widget between the two shortcodes. Same cream, so the join is
   invisible and the band reads as one. */

.acp-fmq .acp-formband { background: var(--acp-cream); padding: 72px 0 34px; }
.acp-fmq .acp-formband .acp-head { max-width: none; margin-bottom: 0; }

/* .acp-formhost is an Elementor container, so it sits outside the .acp tree and
   cannot inherit the tokens. Only the ones the form needs are repeated. */
.acp-formhost {
	--acp-cream: #f6f5ef;
	--acp-green: #00833f;
	--acp-green-dark: #0f5230;
	--acp-mint: #2bde81;
	--acp-gold: #ffa400;
	--acp-ink: #000000;
	--acp-muted: #5c5c56;
	--acp-line: #e6e2d6;
	/* Not a brand token. There is no error colour in the palette and a failed
	   field has to be unmistakable, so this is the one addition. */
	--acp-error: #b3261e;

	background: var(--acp-cream);
	/* !important because this is an Elementor container and `.e-con` sets its
	   padding from --padding-* custom properties, which beat a plain class.
	   Without it the card runs edge to edge at mobile with no cream gutter. */
	padding: 0 30px 100px !important;
}

/* The form card ------------------------------------------------------------ */

.acp-formhost .gform_wrapper,
.acp-formhost .gform_confirmation_wrapper {
	max-width: 980px;
	margin: 0 auto !important;
	background: #fff;
	border-radius: 18px;
	padding: 44px 46px 40px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	font-size: 16px;
	color: var(--acp-ink);
	text-align: left;
}

/* The widget pads itself 50px left and right; the card supplies the padding. */
.acp-formhost > .elementor-widget-oew-gravity-forms,
.acp-formhost .elementor-widget-container { padding: 0 !important; }

.acp-formhost .gform_fields {
	/* The 23 August preview card set the layout the client approved: two
	   columns, wide rows for anything that needs the width. Matched here. */
	/* The widget CSS forces display:flex on the list at equal specificity,
	   so the grid has to insist. */
	display: grid !important;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 20px 24px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.acp-formhost .gfield {
	margin: 0 !important;
	padding: 0 !important;
	list-style: none;
	width: auto !important;
	max-width: none !important;
	float: none !important;
}
/* Rows that need the full width: the message box and any choice-heavy field.
   Hidden fields take no grid cell, so the visible four pair up naturally. */
.acp-formhost .gfield--type-textarea,
.acp-formhost .gfield--type-multiselect,
.acp-formhost .gfield--type-checkbox,
.acp-formhost .gfield--type-address,
.acp-formhost #field_10_18 { grid-column: 1 / -1; }

/* The honeypot must stay hidden no matter what the rules above do. */
.acp-formhost .gform_validation_container,
.acp-formhost .gfield--type-honeypot { display: none !important; }

/* Labels. The widget's Custom CSS sets uppercase Open Sans 500 at 15px with
   !important, which shouts at a nine-word label, so this overrides it. */
.acp-formhost .gfield_label,
.acp-formhost .gform-field-label {
	display: block;
	/* Eyebrow furniture, matching .acp-formph-flag (Figma 29:880). */
	font-family: inherit !important;
	font-size: 10px !important;
	font-weight: 700 !important;
	line-height: 1.4;
	letter-spacing: 0.2em;
	text-transform: uppercase !important;
	color: var(--acp-gold) !important;
	margin: 0 0 8px;
}
.acp-formhost .gfield_required,
.acp-formhost .gfield_required_asterisk {
	/* Deep red, not the error red: a flag, not an error state. */
	color: #8c2f26 !important;
	text-decoration: none;
	font-weight: 700;
}
.acp-formhost .gfield_description {
	margin: 6px 0 0;
	font-size: 13px;
	color: var(--acp-muted);
}

/* Inputs */
.acp-formhost input[type='text'],
.acp-formhost input[type='email'],
.acp-formhost input[type='tel'],
.acp-formhost input[type='url'],
.acp-formhost input[type='number'],
.acp-formhost textarea,
.acp-formhost select {
	width: 100% !important;
	box-sizing: border-box;
	min-height: 52px;
	padding: 14px 16px !important;
	background: var(--acp-offwhite, #faf9f4) !important;
	background-color: var(--acp-offwhite, #faf9f4) !important;
	border: 1px solid var(--acp-line) !important;
	border-radius: 10px !important;
	box-shadow: none !important;
	font-family: inherit;
	font-size: 15px;
	line-height: 1.5;
	color: var(--acp-ink) !important;
	-webkit-appearance: none;
	appearance: none;
}
.acp-formhost textarea { min-height: 132px; resize: vertical; }
.acp-formhost select {
	/* Native arrow is lost with appearance:none, so it is drawn back on. */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%2314683e' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") !important;
	background-repeat: no-repeat !important;
	background-position: right 16px center !important;
	padding-right: 44px !important;
}
.acp-formhost select[multiple] {
	background-image: none !important;
	padding-right: 16px !important;
	min-height: 150px;
}
.acp-formhost input::placeholder,
.acp-formhost textarea::placeholder { color: var(--acp-muted); opacity: 1; }

.acp-formhost input:hover,
.acp-formhost textarea:hover,
.acp-formhost select:hover { border-color: #cfcaba !important; }

/* OceanWP suppresses outlines, and a form is the one place that cannot happen. */
.acp-formhost input:focus,
.acp-formhost textarea:focus,
.acp-formhost select:focus,
.acp-formhost button:focus,
.acp-formhost input:focus-visible,
.acp-formhost textarea:focus-visible,
.acp-formhost select:focus-visible,
.acp-formhost button:focus-visible {
	outline: 3px solid var(--acp-mint) !important;
	outline-offset: 2px;
	border-color: var(--acp-green) !important;
}

/* Complex fields: address subfields and choice lists sit two up. */
.acp-formhost .ginput_complex {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 16px 20px;
	margin: 0;
}
.acp-formhost .ginput_complex > span { display: block; margin: 0; padding: 0; width: auto !important; }
.acp-formhost .ginput_complex .ginput_full { grid-column: 1 / -1; }
.acp-formhost .gform-field-label--type-sub {
	font-size: 12px !important;
	font-weight: 600 !important;
	color: var(--acp-muted) !important;
	margin: 6px 0 0 !important;
}
.acp-formhost .gf_clear,
.acp-formhost .gf_clear_complex { display: none !important; }

.acp-formhost .gfield_checkbox,
.acp-formhost .gfield_radio {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 4px 20px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.acp-formhost .gchoice {
	display: flex;
	align-items: center;
	gap: 10px;
	/* 32px keeps the whole row a comfortable target, well over the 24px floor. */
	min-height: 32px;
	margin: 0;
}
.acp-formhost .gchoice input {
	width: 20px !important;
	height: 20px;
	min-height: 0;
	padding: 0 !important;
	margin: 0;
	border-radius: 4px !important;
	accent-color: var(--acp-green);
}
.acp-formhost .gchoice label {
	margin: 0;
	font-size: 15px !important;
	font-weight: 400 !important;
	letter-spacing: 0 !important;
	color: var(--acp-ink) !important;
}

/* Chosen, which functions.php loads for the multiselects. */
.acp-formhost .chosen-container { width: 100% !important; font-family: inherit; }
.acp-formhost .chosen-container-multi .chosen-choices {
	min-height: 52px;
	padding: 8px 12px !important;
	background: #fff !important;
	border: 1px solid var(--acp-line) !important;
	border-radius: 12px !important;
	box-shadow: none !important;
}
.acp-formhost .chosen-container-multi .chosen-choices li.search-choice {
	background: var(--acp-cream) !important;
	border: 1px solid var(--acp-line) !important;
	border-radius: 999px !important;
	box-shadow: none !important;
	padding: 5px 24px 5px 13px !important;
	margin: 3px 6px 3px 0 !important;
	font-size: 13px;
	color: var(--acp-green);
}
.acp-formhost .chosen-container .chosen-drop {
	border-color: var(--acp-line) !important;
	border-radius: 0 0 12px 12px;
}
.acp-formhost .chosen-container .active-result.highlighted { background: var(--acp-green) !important; }

/* Submit. The widget styles it orange and full width; the design calls for the
   green pill used everywhere else on the site. */
.acp-formhost .gform_footer {
	margin: 30px 0 0 !important;
	padding: 0 !important;
}
.acp-formhost .gform_button,
.acp-formhost input[type='submit'] {
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	width: auto !important;
	min-width: 0;
	min-height: 40px;
	padding: 9px 24px !important;
	border: 1.5px solid var(--acp-green) !important;
	border-radius: 999px !important;
	background: var(--acp-green) !important;
	background-color: var(--acp-green) !important;
	color: #fff !important;
	font-family: inherit;
	font-size: 14px !important;
	font-weight: 600;
	line-height: 1.2;
	text-transform: none;
	box-shadow: none !important;
	cursor: pointer;
	transition: background 0.18s ease, border-color 0.18s ease;
}
.acp-formhost .gform_button:hover,
.acp-formhost input[type='submit']:hover {
	background: var(--acp-green-dark) !important;
	background-color: var(--acp-green-dark) !important;
	border-color: var(--acp-green-dark) !important;
}
.acp-formhost .gform_ajax_spinner { margin-left: 14px; vertical-align: middle; }

/* Validation */
.acp-formhost .gform_validation_errors {
	background: #fff !important;
	border: 0 !important;
	border-left: 4px solid var(--acp-error) !important;
	border-radius: 12px;
	box-shadow: none !important;
	padding: 18px 22px !important;
	margin: 0 0 26px !important;
}
.acp-formhost .gform_validation_errors > h2 {
	font-family: inherit !important;
	font-size: 15px !important;
	font-weight: 700;
	color: var(--acp-error) !important;
	margin: 0;
	text-transform: none;
}
.acp-formhost .gfield_error input,
.acp-formhost .gfield_error select,
.acp-formhost .gfield_error textarea { border-color: var(--acp-error) !important; }
.acp-formhost .gfield_error .gfield_label { color: var(--acp-error) !important; }
.acp-formhost .validation_message {
	background: none !important;
	border: 0 !important;
	padding: 6px 0 0 !important;
	margin: 0 !important;
	font-size: 13px;
	font-weight: 600;
	color: var(--acp-error) !important;
}

/* The AJAX confirmation replaces the form in place, so it has to be dressed. */
.acp-formhost .gform_confirmation_message {
	max-width: 980px;
	margin: 0 auto;
	background: #fff;
	border-radius: 18px;
	border-left: 4px solid var(--acp-mint);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	padding: 44px 46px;
	font-size: 17px;
	line-height: 1.6;
	color: var(--acp-ink);
}

@media (max-width: 960px) {
	.acp-fmq .acp-hero { padding-bottom: 52px; }
	.acp-fmq .acp-formband { padding: 60px 0 26px; }
	.acp-fmq .acp-trust { padding-top: 60px; }

	.acp-formhost { padding: 0 20px 60px !important; }
	.acp-formhost .gform_wrapper,
	.acp-formhost .gform_confirmation_wrapper,
	.acp-formhost .gform_confirmation_message {
		padding: 28px 22px 26px;
		border-radius: 14px;
	}
	.acp-formhost .ginput_complex,
	.acp-formhost .gfield_checkbox,
	.acp-formhost .gfield_radio { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
	.acp-formhost .gform_button,
	.acp-formhost input[type='submit'] { width: 100% !important; min-width: 0; }
}

/* =========================================================================
   Curtains (page 14433)

   The curtains page is a standalone page rather than a product archive, so it
   has no catalogue to read and no product grid to bracket. The one thing it
   does have that the flooring pages do not is real photography already in the
   media library, so these rules give an <img> the same box the grey .acp-ph
   placeholder device already occupies in each slot. Both are used on the page:
   photographs where the picture supports what the card says, placeholders where
   the label would be a claim the photograph cannot make.

   No token, component or breakpoint is introduced here. Nothing above this
   block is edited.
   ========================================================================= */

.acp img.acp-img {
	display: block;
	width: 100%;
	object-fit: cover;
	border-radius: 14px;
}

/* `.acp img.acp-img` is (0,2,1) and outranks the hero's own `.acp-hero-media img`
   at (0,1,1), so the hero radius is restated here rather than silently lost. */
.acp-hero-media img.acp-img { border-radius: 15px; }

.acp-split-media img.acp-img {
	min-height: 520px;
	height: 100%;
	border-radius: 15px;
}
.acp-tile img.acp-img { height: 370px; }
.acp-style-card img.acp-img { height: 240px; margin: 0 0 18px; }
.acp-feature img.acp-img { height: 260px; border-radius: 10px; }
.acp-guide img.acp-img { height: 190px; border-radius: 10px; }

/* Four related links rather than the usual three, so the row does not leave a
   single orphan card on the second line. */
.acp-curtains .acp-guide-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1200px) {
	.acp-curtains .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-split-media img.acp-img { min-height: 280px; }
	.acp-tile img.acp-img { height: 290px; }
	.acp-curtains .acp-guide-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   Tiles (product_cat term 29)

   The tiles page uses the shared components unchanged. The one thing it needs
   that the flooring pages do not is a four-up related-reading row, because two
   real Andersens tile articles exist on the site (choosing a ceramic bathroom
   tile, and how to re-grout tiles) and they sit alongside the usual two links.
   Three cards would leave one of them off; four fills the row.

   This mirrors the curtains rule above rather than editing it, so neither page
   can change the other. No token, component or breakpoint is introduced.
   ========================================================================= */

.acp-tiles .acp-guide-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1200px) {
	.acp-tiles .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-tiles .acp-guide-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   Plantation shutters (page 7290)

   The shutters page uses the shared components unchanged. Like curtains and
   tiles it needs a four-up related-reading row, because two real Andersens
   shutter articles exist on the site (the key benefits of interior shutters,
   and how to clean your window coverings) and they sit alongside the blinds and
   curtains links. Three cards would leave one of them off; four fills the row.

   This mirrors the curtains and tiles rules above rather than editing either, so
   no page can change another. No token, component or breakpoint is introduced.
   ========================================================================= */

.acp-shutters .acp-guide-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1200px) {
	.acp-shutters .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-shutters .acp-guide-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   ELEMENTOR COMPATIBILITY LAYER
   Added 19 August 2026, when the framework pages were rebuilt as native
   Elementor content so they can be edited in the builder.

   Nothing above this block is edited. Every selector here needs an Elementor
   class to match, so a page still running the shortcodes is untouched by all
   of it, and the two can coexist while the twelve pages are converted one at
   a time.

   Three things move when a page is converted:
     1. Elementor containers arrive with their own flex defaults.
     2. A widget's custom class lands on the WRAPPER, not the element, so
        h2.acp-h2 and img.acp-img stop matching.
     3. The FAQ and the room tabs become widgets with their own markup.
   ========================================================================= */

/* 2. Buttons -------------------------------------------------------------
   .acp-btn is on the widget wrapper now; the real anchor inside is
   .elementor-button. The wrapper must not stretch the pill to full width. */
/* The hero deliberately stacks its two pills at a common width, so the wrapper
   is stretched by .acp-hero .acp-actions and the anchor inside has to fill it.
   Without the width the anchor shrink-wraps and "Book a Free Measure & Quote"
   wraps onto a second line, which the original never did. */
/* A widget's custom class lands on its WRAPPER, so any component class that
   carries box styling gets applied twice: once to the wrapper Elementor makes,
   once to the real element inside. The wrapper has to be stripped back.
   Same trap as .acp-tabs, and .acp-faq below. */
.acp .acp-btn.elementor-widget {
	display: block;
	padding: 0;
	border: 0;
	background: none;
	min-height: 0;
	border-radius: 0;
}
.acp .acp-btn .elementor-widget-container { display: block; }
.acp .acp-btn .elementor-button { width: 100%; }
.acp .acp-btn .elementor-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: 37px;   /* see the anchor variant above for the WCAG note */
	flex: 0 0 auto;
	white-space: nowrap;
	padding: 10px 20px;
	border-radius: 999px;
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	text-align: center;
	text-decoration: none;
	border: 1.5px solid var(--acp-green);
	background: var(--acp-green);
	color: #fff;
	cursor: pointer;
	transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.acp .acp-btn .elementor-button:hover,
.acp .acp-btn .elementor-button:focus-visible {
	background: var(--acp-green-dark);
	border-color: var(--acp-green-dark);
	color: #fff;
}
.acp .acp-btn-outline .elementor-button { background: transparent; color: var(--acp-green); }
.acp .acp-btn-outline .elementor-button:hover,
.acp .acp-btn-outline .elementor-button:focus-visible { background: var(--acp-green); color: #fff; }
.acp .acp-on-green .acp-btn .elementor-button { background: #fff; border-color: #fff; color: var(--acp-green); }
.acp .acp-on-green .acp-btn .elementor-button:hover,
.acp .acp-on-green .acp-btn .elementor-button:focus-visible { background: var(--acp-cream); border-color: var(--acp-cream); color: var(--acp-green-dark); }
.acp .acp-on-green .acp-btn-outline .elementor-button { background: transparent; border-color: #fff; color: #fff; }
.acp .acp-on-green .acp-btn-outline .elementor-button:hover,
.acp .acp-on-green .acp-btn-outline .elementor-button:focus-visible { background: #fff; color: var(--acp-green); }

/* 3. Image widget --------------------------------------------------------
   .acp-img is on the wrapper, the <img> sits inside it. The generated block
   below carries the real dimensions, mirrored rule for rule from the source
   so the two can never drift. These two just flatten the wrapper. */
.acp .acp-img,
.acp .acp-img .elementor-widget-container { display: block; height: 100%; }
.acp .acp-style-card .acp-img { height: auto; }
.acp .acp-h1 .elementor-heading-title, .acp .acp-h2 .elementor-heading-title {
	font-family: var(--acp-serif);
	/* Instrument Serif ships in 400 only; 600 was faux-bolding every heading.
	   Figma (7 Sep 2026) specifies Regular, 0.95 leading and no tracking. */
	font-weight: 400;
	color: var(--acp-green);
	line-height: 0.95;
	letter-spacing: 0;
	margin: 0;
	text-transform: none;
}
.acp .acp-h1 .elementor-heading-title {
	font-size: clamp(52px, calc(45.7126px + 1.56403vw), 68px); /* 52@402 -> 68@1425 */
}
/* Mirrors `.acp h2.acp-h2` above: Figma section headings are 48 (29:878) and
   36 on mobile (58:1464) at 1.05 leading, NOT the H1's 68/0.95. */
.acp .acp-h2 .elementor-heading-title {
	font-size: clamp(36px, calc(31.2844px + 1.17302vw), 48px);
	line-height: 1.05;
}
.acp .acp-h3 .elementor-heading-title {
	font-family: var(--acp-serif);
	font-weight: 400;
	font-size: 32px;
	line-height: 1.4;
	letter-spacing: -0.03em;
	color: var(--acp-green);
	margin: 0 0 12px;
	text-transform: none;
}
/* Card titles carry the Figma card-title style (29:823 / 29:936): Instrument
   Serif 32, green, -0.96 tracking. The :has(.acp-media) test is on the GRID,
   not the card: a card family is consistent per row, and Window Furnishings
   has one card with no photograph beside three that have one. Rows with no
   photography at all are excluded by construction. !important because these are <h3 class="acp-h4">, which
   `.acp h4.acp-h4` never matched, and .acp-window overrides to 17px. */
.acp .acp-feature-grid:has(.acp-media) .acp-feature .acp-h4,
.acp .acp-guide-grid:has(.acp-media) .acp-guide .acp-h4,
.acp .acp-feature-grid:has(.acp-media) .acp-feature .acp-h4 .elementor-heading-title,
.acp .acp-guide-grid:has(.acp-media) .acp-guide .acp-h4 .elementor-heading-title {
	font-family: var(--acp-serif) !important;
	font-size: 32px !important;
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: -0.03em;
	color: var(--acp-green);
	margin: 0 0 12px;
}
.acp .acp-h4 .elementor-heading-title {
	/* Explicit, not `inherit`: on a converted page an Elementor ancestor supplies
	   the serif, and h4 at 700 then faux-bolds a face that only ships 400. */
	font-family: var(--and-text) !important; /* beats the Brand V4 heading rollout in style.css */
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
	color: var(--acp-green);
	margin: 0 0 8px;
	text-transform: none;
	letter-spacing: 0;
}
.acp .acp-table-holder table.acp-table {
	width: 100%;
	border-collapse: collapse;
	margin: 0;
	font-size: 15px;
	background: none !important;
	border: 0 !important;
}
.acp .acp-img img {
	display: block;
	width: 100%;
	object-fit: cover;
	border-radius: 14px;
}
.acp-hero-media .acp-img img {
	border-radius: 15px;
}
.acp-split-media .acp-img img {
	min-height: 520px;
	height: 100%;
	border-radius: 15px;
}
.acp-tile .acp-img img {
	height: 370px;
}
.acp-style-card .acp-img img {
	height: 240px;
	margin: 0 0 18px;
}
.acp-feature .acp-img img {
	height: 260px;
	border-radius: 10px;
}
.acp-guide .acp-img img {
	height: 190px;
	border-radius: 10px;
}
/* Converted pages hang the image wrapper straight off the card rather than
   wrapping it in .acp-media. Direct child only: on a shortcode page .acp-img
   is the <img> inside .acp-media and already has its radius above. */
.acp-guide > .acp-img { border-radius: 10px; }
@media (max-width: 960px) {
	.acp-split-media .acp-img img {
		min-height: 280px;
	}
	.acp-tile .acp-img img {
		height: 290px;
	}
}

/* 4. FAQ -----------------------------------------------------------------
   uael-faq replaces <details>/<summary> and emits FAQPage schema itself, so
   the framework's own FAQ schema is switched off for converted pages rather
   than both firing. Question and answer styling is ported here. */
/* .acp-faq is a SECTION class, and it also lands on the FAQ widget, which was
   giving the widget the section's own 90px/100px padding and background on top
   of the section's. Strip the wrapper back to nothing. */
.acp .acp-faq.elementor-widget { padding: 0; background: none; }

.acp .acp-faq .uael-faq-wrapper { border-top: 1px solid var(--acp-line); }
.acp .acp-faq .uael-accordion-heading,
.acp .acp-faq .uael-faq-accordion { border-bottom: 1px solid var(--acp-line); }
.acp .acp-faq .uael-question-span {
	font-family: var(--acp-serif);
	font-size: 24px;
	font-weight: 400;
	line-height: 1.2;
	color: var(--acp-green);
}
.acp .acp-faq .uael-accordion-heading {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 20px;
	cursor: pointer;
	padding: 24px 4px;
	min-height: 48px;
}
.acp .acp-faq .uael-accordion-content {
	padding: 0 4px 26px;
	max-width: 72em;
	font-size: 15px;
}
.acp .acp-faq .uael-accordion-content p:last-child { margin-bottom: 0; }

/* 5. Room tabs -----------------------------------------------------------
   The .acp-tabs class lands on the WIDGET WRAPPER, so the original
   .acp-tabs{display:grid} turned the wrapper into the two-column grid and the
   real .elementor-tabs inside it got stuck in the 280px first column. Its own
   content column then resolved to 0px and one panel ballooned to 9085px.
   The wrapper has to be a plain block; the grid belongs on .elementor-tabs. */
.acp .acp-tabs.elementor-widget { display: block; }

/* The grid, the rail and the selected treatment: a left bar as well as a
   background, so the state never depends on colour alone. */
.acp .acp-tabs .elementor-tabs {
	display: grid;
	grid-template-columns: minmax(0, 280px) minmax(0, 1fr);
	gap: 46px;
	align-items: start;
}
.acp .acp-tabs .elementor-tabs-wrapper { display: flex; flex-direction: column; gap: 4px; }
.acp .acp-tabs .elementor-tab-title {
	border: 0;
	border-left: 3px solid transparent;
	background: transparent;
	text-align: left;
	font-family: var(--acp-serif);
	font-size: 22px;
	font-weight: 400;
	line-height: 1.2;
	color: var(--acp-green);
	padding: 13px 16px;
	border-radius: 12px;
	cursor: pointer;
	min-height: 48px;
}
.acp .acp-tabs .elementor-tab-title:hover { background: rgba(20, 104, 62, 0.06); }
.acp .acp-tabs .elementor-tab-title.elementor-active {
	background: #fff;
	border-left-color: var(--acp-mint);
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}
.acp .acp-tabs .elementor-tabs-content-wrapper { border: 0; }
.acp .acp-tabs .elementor-tab-content { border: 0; padding: 0; }
/* Elementor prints the titles twice, once for the desktop rail and once as
   mobile accordion headers. Only one set should ever be visible. */
.acp .acp-tabs .elementor-tab-mobile-title { display: none; }

@media (max-width: 960px) {
	.acp .acp-tabs .elementor-tabs { grid-template-columns: 1fr; gap: 22px; }
	.acp .acp-tabs .elementor-tabs-wrapper { flex-direction: row; overflow-x: auto; gap: 8px; }
	.acp .acp-tabs .elementor-tab-title { white-space: nowrap; font-size: 18px; }
}

/* 6. Rail items ----------------------------------------------------------
   .acp-rail > li { scroll-snap-align: start; flex: 0 0 auto; } stops matching,
   because each <li> becomes a container div. Without flex:0 0 auto the items
   stretch to the full rail width and the horizontal rail collapses into a very
   tall vertical stack: the pathways section went from about 600px to 3386px.
   This is the one genuinely tag-dependent structural selector in the sheet.
   The prose lists are unaffected, because those stay real <li> inside a text
   editor. */
.acp .acp-rail > .e-con {
	flex: 0 0 auto;
	width: auto;
	scroll-snap-align: start;
}

/* 7. The containers that need a horizontal row ---------------------------
   Everything else is left on Elementor's flex-column default, which stacks
   children exactly as the original block divs did. These are the exceptions,
   set through the variables at three classes so they clear Elementor's own
   two-class rules. Values mirrored from the source rules above. */
.acp .acp-actions.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 16px; --row-gap: 16px; --column-gap: 16px;
}
/* The hero stacks its two pills at a common width on purpose. */
.acp .acp-hero .acp-actions.e-flex {
	--flex-direction: column;
	--align-items: stretch;
	--gap: 14px; --row-gap: 14px; --column-gap: 14px;
}
.acp .acp-rail.e-flex {
	--flex-direction: row;
	--align-items: normal;
	--gap: 22px; --row-gap: 22px; --column-gap: 22px;
}
.acp .acp-rail-foot.e-flex {
	--flex-direction: row;
	--align-items: center;
	--justify-content: space-between;
	--gap: 20px; --row-gap: 20px; --column-gap: 20px;
}
.acp .acp-dots.e-flex {
	--flex-direction: row;
	--align-items: center;
	--gap: 8px; --row-gap: 8px; --column-gap: 8px;
}
.acp .acp-navs.e-flex {
	--flex-direction: row;
	--gap: 12px; --row-gap: 12px; --column-gap: 12px;
}

/* =========================================================================
   Payment options (page 121, /services/payment-options/)
   Added 20 August 2026 with the payment options redesign.

   Five rules and one media query. Nothing above this block is edited, no token
   is introduced, and every selector is scoped to .acp-payment so no other page
   can be reached by any of it.

   Note on the scoping: .acp-payment sits on the SAME element as .acp (the root
   is <div class="acp acp-top acp-payment">), so a descendant selector reads
   `.acp-payment .thing`, and where it has to outrank an existing `.acp .thing`
   rule it is written `.acp.acp-payment .thing` to add the extra class.
   ====================================================================== */

/* The band the tabs sit in. Cream, matching .acp-rooms, which is the same
   component in the same position on the category pages. */
.acp-payment .acp-ways { background: var(--acp-cream); padding: 90px 0 100px; }

/* The availability qualifier sits BETWEEN the section head and the tabs, so its
   margin runs the other way to the wet-area callout this class was written for.
   (0,2,0) against the base rule's (0,1,0). */
.acp-payment .acp-caution { margin: 0 0 34px; }

/* The white panel card, post-conversion.
   Before conversion the panel is <div class="acp-panel"> and .acp-panel already
   draws the card. Elementor's tabs widget replaces that div with its own
   .elementor-tab-content, and `.acp .acp-tabs .elementor-tab-content` further up
   this sheet strips it back to `border: 0; padding: 0` for the room tabs on the
   category pages. That rule is (0,3,0), so this one carries the extra class to
   reach (0,4,0) rather than being reordered. The category pages are untouched:
   they do not carry .acp-payment. */
.acp.acp-payment .acp-tabs .elementor-tab-content {
	background: #fff;
	border-radius: 18px;
	padding: 38px 40px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
}

/* .acp h4.acp-h4 sets a bottom margin only, which is right where a heading opens
   a block. Inside a panel these are the provider's questions arriving after a
   paragraph, so they need air above them too. Matches pre- and post-conversion:
   .acp-tabs is the panel wrapper in one and the widget wrapper in the other. */
.acp-payment .acp-tabs h4.acp-h4 { margin-top: 26px; }
.acp-payment .acp-tabs h3.acp-h3 + p { margin-top: 0; }

/* The humm logo. NOT in an .acp-media box: that crops to fill with object-fit
   cover, which slices a wide logo on a white field. */
.acp-payment .acp-pay-logo {
	display: block;
	width: auto;
	max-width: 240px;
	height: auto;
	margin: 0 0 6px;
	border-radius: 0;
}

/* The Latitude terms and conditions. Fine print, set as fine print, and ruled
   off from the copy above it so it reads as the separate block it is.
   `.acp-payment .acp-terms p` is (0,2,1) and outranks `.acp p` at (0,1,1). */
.acp-payment .acp-terms {
	margin-top: 30px;
	padding-top: 26px;
	border-top: 1px solid var(--acp-line);
}
.acp-payment .acp-terms p { font-size: 14px; color: var(--acp-muted); }

@media (max-width: 960px) {
	.acp-payment .acp-ways { padding: 56px 0 64px; }
	.acp.acp-payment .acp-tabs .elementor-tab-content { padding: 26px 22px; border-radius: 14px; }
}

/* =========================================================================
   Membership discounts (page 119)

   The page publishes two member offers and nothing else, so it reuses the
   shared components as they are. No token, component or breakpoint is
   introduced. This block mirrors the curtains, tiles and shutters blocks above
   rather than editing any of them, so no page can change another.

   NOTE ON THE SELECTORS: the page root is <div class="acp acp-top
   acp-memberships">, so .acp and .acp-memberships are the SAME element.
   ".acp .acp-memberships" would need an ancestor and would never match, which
   is why the compound ".acp.acp-memberships" is used wherever extra weight is
   needed over a shared (0,2,0) rule.
   ========================================================================= */

/* The offers band. Same vertical rhythm as every other offwhite section. */
.acp-memberships .acp-offers { background: var(--acp-offwhite); padding: 90px 0 100px; }

/* .acp-inset carries a 40px top margin for sitting after prose. Here the two
   cards ARE the grid content, so that margin only pushes the row down. Equal
   heights keep the cards level when one terms list runs longer than the other. */
.acp.acp-memberships .acp-inset { margin: 0; height: 100%; }

/* The published terms. Numbered because the source terms are numbered, and
   muted so the offer itself stays the loudest thing in the card. */
.acp.acp-memberships .acp-terms-label { margin: 26px 0 10px; }
.acp.acp-memberships .acp-terms {
	margin: 0;
	padding: 0 0 0 20px;
	font-size: 15px;
	color: var(--acp-muted);
}
.acp.acp-memberships .acp-terms li { padding: 0 0 10px; }
.acp.acp-memberships .acp-terms li:last-child { padding-bottom: 0; }

/* Three claim steps, not the four the shared grid assumes. */
.acp-memberships .acp-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* `.acp h4.acp-h4` needs the h4 TAG, so an <h3 class="acp-h4"> never matches it
   and falls back to the theme's h3 (18px, #333). The step headings are h3 so
   the heading order under the section h2 stays correct, so the label styling is
   restated for them here. The same mismatch exists on the blinds, awnings and
   shutters step grids; fixing it globally is a separate call, because lowering
   the shared rule to `.acp .acp-h4` changes four live pages at once. */
.acp.acp-memberships .acp-step h3.acp-h4 {
	/* Explicit, not `inherit`: on a converted page an Elementor ancestor supplies
	   the serif, and h4 at 700 then faux-bolds a face that only ships 400. */
	font-family: var(--and-text) !important; /* beats the Brand V4 heading rollout in style.css */
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
	color: var(--acp-green);
	margin: 0 0 8px;
	text-transform: none;
	letter-spacing: 0;
}

/* The tertiary hero row. Post-conversion .acp-hero-meta is an Elementor
   container, and Elementor's own two-class rules default it to a CENTRED COLUMN,
   so the arrow link and the RACQ/NRMA/APOD line stacked and centred instead of
   sitting on one left-aligned row. Set through the variables at three classes to
   clear those, mirroring the row containers at the end of this file.

   Scoped to this page deliberately. The same gap affects the blinds, curtains,
   shutters and awnings heroes, so adding .acp-hero-meta to the shared row list
   would fix all four, but that changes four other live pages and is Bron's call,
   not a side effect of this one. */
.acp.acp-memberships .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}

/* The arrow link becomes a container too, so it picks up .e-con's width:100%
   and its 1px bottom border ran the full width of the column like a rule. */
.acp.acp-memberships .acp-hero-meta > .acp-arrow.e-con {
	width: auto;
	flex: 0 0 auto;
}

/* The final card's heading, post-conversion.
   `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget WRAPPER,
   but the compatibility layer's mirror `.acp .acp-h2 .elementor-heading-title`
   sets the green heading colour on the real element inside it, and a direct rule
   beats an inherited one. So the heading rendered GREEN ON GREEN and was
   invisible: "Bring your card" disappeared and only the mint <em> showed.
   Restated for the real element at (0,5,0) against the mirror's (0,3,0).

   Same caveat as the hero row above: every converted page with a final CTA card
   or a green card has this, blinds included, so the shared fix belongs in the
   compatibility layer. Scoped here so this page does not quietly restyle others. */
.acp.acp-memberships .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-memberships .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* Breakpoints are restated because a (0,2,0) page selector outranks the shared
   (0,1,0) rules even inside their own media queries. */
@media (max-width: 1200px) {
	.acp-memberships .acp-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-memberships .acp-offers { padding: 60px 0 70px; }
	.acp-memberships .acp-steps { grid-template-columns: 1fr; }
}

/* The final band heading, post-conversion. A real bug, not a nicety.
   `.acp .acp-final-card .acp-h2 { color: #fff }` colours the widget WRAPPER; the
   real <h2> inside is .elementor-heading-title and its own mirror rule above sets
   color: var(--acp-green) at the same (0,3,0) and later in the file, so the heading
   rendered green on a green card. Only the <em> was visible.
   Same bug is live on blinds 7253, curtains 14433, shutters 7290 and awnings 13771.
   Scoped to this page; the unscoped fix is in the deploy notes for approval.
   NOTE 20 August 2026: this block was appended once and lost to a concurrent write
   from the memberships build. If it goes missing again, that is why. */
.acp.acp-payment .acp-final-card .acp-eyebrow .elementor-heading-title,
.acp.acp-payment .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-payment .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* =========================================================================
   In home service (page 123, /services/in-home-service/)
   Added 20 August 2026 with the in home service redesign.

   Six rules and two media queries. Nothing above this block is edited, no
   token, component or breakpoint is introduced, and every selector is scoped to
   .acp-inhome so no other page can be reached by any of it.

   NOTE ON THE SELECTORS: the page root is <div class="acp acp-top acp-inhome">,
   so .acp and .acp-inhome are the SAME element. ".acp .acp-inhome" would need an
   ancestor and would never match, which is why the compound ".acp.acp-inhome"
   is used wherever extra weight is needed over a shared rule.
   ====================================================================== */

/* The two editorial bands, alternating offwhite then cream, which is the rhythm
   .acp-why and .acp-rooms set on every category page. Same 90/100 vertical
   rhythm as every other section in the sheet. */
.acp-inhome .acp-ihs-day { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-inhome .acp-ihs-process { background: var(--acp-cream); padding: 90px 0 100px; }

/* The hero's tertiary link jumps to the appointment band, so the band needs to
   clear the sticky header when it lands. Mirrors .acp-fmq .acp-process. */
.acp-inhome .acp-ihs-day { scroll-margin-top: 90px; }

/* The process band leads with its image so the two bands alternate. The media
   div is FIRST in the DOM, so grid auto-placement puts it in column one and no
   `order` is needed. The shared .acp-split is copy 1fr / media 1.05fr; flipped,
   the wider column has to move with it, or the image column comes out narrower
   than the one above it and the two bands stop lining up.
   (0,2,0) against the shared rule's (0,1,0). */
.acp-inhome .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }

/* The final card's heading and eyebrow, post-conversion.
   `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget WRAPPER,
   but the compatibility layer's mirror `.acp .acp-h2 .elementor-heading-title`
   paints the real element green, and a direct rule always beats an inherited
   one, so the heading renders green on the green card and only the mint <em>
   shows. Restated for the real elements at (0,5,0) against the mirror's (0,3,0).

   Same fix, same caveat, as the .acp-payment and .acp-memberships blocks above:
   every converted page with a green card has this, so the unscoped fix belongs
   in the compatibility layer and is Bron's call, not a side effect of this
   page. Scoped here so this page cannot restyle the other fourteen. */
.acp.acp-inhome .acp-final-card .acp-eyebrow .elementor-heading-title,
.acp.acp-inhome .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-inhome .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* Inline links inside prose.
   The design layer styles breadcrumb links, buttons and .acp-arrow, and nothing
   else: no page before this one had a plain <a> inside a paragraph, so a prose
   link falls through to the theme's own link colour, #00833f. Two consequences
   on this page, one of them a real defect:

     - the phone number on the final card rendered #00833f ON the green card,
       which is green on green and all but unreadable;
     - the payment options link in the process copy rendered the theme green
       rather than the design's --acp-green, so it did not match the page.

   Both are set here in the crumbs' idiom, a transparent bottom border that
   fills in on hover, so an inline link reads as a link without the theme's
   heavier underline. Scoped like everything else in this block: the shared
   version of the .acp-on-green rule belongs in the compatibility layer and is
   Bron's call. */
.acp.acp-inhome .acp-split-copy a {
	color: var(--acp-green);
	text-decoration: none;
	border-bottom: 1px solid currentColor;
}
.acp.acp-inhome .acp-split-copy a:hover,
.acp.acp-inhome .acp-split-copy a:focus-visible { color: var(--acp-green-dark); }

.acp.acp-inhome .acp-final-card a {
	color: #fff;
	text-decoration: none;
	border-bottom: 1px solid currentColor;
}
.acp.acp-inhome .acp-final-card a:hover,
.acp.acp-inhome .acp-final-card a:focus-visible { color: var(--acp-cream); }

/* Breakpoints are restated because a (0,2,0) page selector outranks the shared
   (0,1,0) rules even inside their own media queries. Without the second one the
   flipped split keeps its two columns on a phone. */
@media (max-width: 1200px) {
	.acp-inhome .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
}

@media (max-width: 960px) {
	.acp-inhome .acp-ihs-day,
	.acp-inhome .acp-ihs-process { padding: 56px 0 64px; }
	.acp-inhome .acp-split-flip { grid-template-columns: 1fr; }
}

/* =========================================================================
   INSTALLATION PAGE  (page 129, /services/installation/)   20 August 2026
   -------------------------------------------------------------------------
   Appended, nothing above edited. Every selector carries .acp-install, which
   only page 129 uses, so no other page can be affected by anything here.

   NOTE ON THE SELECTORS: the page root is <div class="acp acp-top
   acp-install">, so .acp and .acp-install are the SAME element.
   ".acp .acp-install" would need an ancestor and would never match, which is
   why the compound ".acp.acp-install" is used wherever extra weight is needed
   over a shared (0,2,0) rule.
   ========================================================================= */

/* Band rhythm: cream hero, offwhite planning, panel steps, offwhite videos.
   Same 90/100 vertical rhythm as every other section in the framework. */
.acp-install .acp-before { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-install .acp-videos { background: var(--acp-offwhite); padding: 90px 0 100px; }

/* .acp-faq paints itself offwhite, which would put three offwhite bands in a
   row. The steps accordion takes the panel tone instead, so the page alternates
   the way the category pages do. */
.acp-install .acp-install-steps { background: var(--acp-panel); }

/* .acp-inset carries a 40px top margin for sitting after prose. Here the two
   planning cards ARE the grid content, so that margin only pushes the row down.
   Equal heights keep them level when one card's copy runs longer. */
.acp.acp-install .acp-inset { margin: 0; height: 100%; }
.acp.acp-install .acp-inset .acp-h3 { margin-top: 0; }

/* The store-variation qualifier sits directly under the section head rather
   than after prose, so it loses the shared 34px top margin. */
.acp.acp-install .acp-caution { margin: 0 0 34px; }

/* ---- Installation videos -----------------------------------------------
   Five YouTube clips from Andersens' own channel. A plain grid, not a snap
   rail: five items fit in two rows at every breakpoint, and a rail would need
   the .acp-nav controls, which acp-converter.php turns from <button> into a
   div and so lose their button semantics.
   ---------------------------------------------------------------------- */

.acp-video-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 26px;
	margin: 44px 0 0;
}

/* The class lands on the <div> when the page renders from the shortcode, and on
   the text-editor widget's WRAPPER once converted. Radius plus overflow clips
   the player either way, so one rule covers both DOMs. */
.acp-video-frame {
	border-radius: 14px;
	overflow: hidden;
	background: #0b0b0b;
}

/* The iframe carries its own 16:9 box. Descendant, not child: post-conversion
   the iframe sits inside Elementor's .elementor-widget-container rather than
   directly in .acp-video-frame. Nothing else lives in this box, so the looser
   selector cannot catch anything it should not. */
.acp .acp-video-frame iframe {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	border: 0;
}

/* wpautop wraps a lone iframe in a <p> inside the text-editor widget, and that
   <p> then picks up `.acp p`'s bottom margin and opens a gap under the player
   inside the clipped box. */
.acp .acp-video-frame p { margin: 0; }

/* The caption. (0,2,0) so it outranks the shared `.acp p` at (0,1,1); the
   converter leaves this <p> inside its text editor with the class intact, so no
   wrapper mirror is needed. */
.acp .acp-video-title {
	margin: 14px 0 0;
	font-size: 15px;
	font-weight: 600;
	color: var(--acp-green);
}

/* ---- Post-conversion compatibility ------------------------------------
   Both of these are the known gaps documented in
   flooring-redesign/elementor-convert/README.md, not new faults. Scoped to
   this page deliberately: the same two affect blinds 7253, curtains 14433,
   shutters 7290, awnings 13771, memberships 119 and payment options 121, so
   the unscoped fix belongs in the shared compatibility layer and is Bron's
   call, not a side effect of this page.
   ---------------------------------------------------------------------- */

/* 1. .acp-hero-meta becomes an Elementor container, and Elementor's two-class
      rules default it to a centred column, so the arrow link stacks and its 1px
      underline runs the full column width like a horizontal rule. */
.acp.acp-install .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
.acp.acp-install .acp-hero-meta > .acp-arrow.e-con {
	width: auto;
	flex: 0 0 auto;
}

/* 2. `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget
      WRAPPER, but the compatibility layer's mirror
      `.acp .acp-h2 .elementor-heading-title` paints the real element green, and
      a direct rule beats an inherited one. Without this the final band heading
      renders green on green and only the mint <em> is visible. */
.acp.acp-install .acp-final-card .acp-eyebrow .elementor-heading-title,
.acp.acp-install .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-install .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* Breakpoints are restated because a (0,2,0) page selector outranks the shared
   (0,1,0) rules even inside their own media queries. */
@media (max-width: 960px) {
	.acp-install .acp-before,
	.acp-install .acp-videos { padding: 60px 0 70px; }
	.acp-video-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; margin-top: 32px; }
}

@media (max-width: 640px) {
	.acp-video-grid { grid-template-columns: 1fr; }
}

/* Elementor gives every container a default 10px padding, and on .acp-video-frame
   that shows as a dark band inside the clipped box, because this is the one
   converted container on the page that paints its own background. Neutralised at
   (0,2,0) so it outranks .e-con's own padding.
   The same stray 10px sits on every unpadded converted container across all
   thirteen .acp pages (.acp-hero-grid, .acp-head, .acp-actions and the rest). It
   is invisible wherever nothing is painted behind it, which is why only the three
   video containers are corrected here rather than the shared layer. */
.acp .acp-video-grid,
.acp .acp-video,
.acp .acp-video-frame { padding: 0; }

/* END .acp-install block (page 129) */

/* =========================================================================
   Carpet cleaning (page 131, /services/carpet-cleaning/)
   Added 20 August 2026 with the carpet cleaning redesign.

   Nothing above this block is edited, no token is introduced, no breakpoint is
   added, and every selector is scoped to .acp-cleaning so no other page can be
   reached by any of it.

   Note on the scoping: .acp-cleaning sits on the SAME element as .acp (the page
   root is <div class="acp acp-top acp-cleaning">), so a descendant selector
   reads `.acp-cleaning .thing`, and where it has to outrank an existing
   `.acp .thing` rule it is written `.acp.acp-cleaning .thing` for the extra
   class. This mirrors the payment options and memberships blocks above.
   ====================================================================== */

/* Band rhythm: hero cream, services offwhite, why cream, contact offwhite,
   final offwhite. .acp-why and .acp-local keep their shared padding, including
   inside the shared media queries, because only the background is restated. */
.acp-cleaning .acp-services { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-cleaning .acp-why { background: var(--acp-cream); }
.acp-cleaning .acp-local { background: var(--acp-offwhite); }

/* The availability callout sits between the section head and the service cards.
   .acp-caution carries a 34px top margin for sitting after prose, which on top
   of .acp-head's 48px bottom margin left an 82px hole. */
.acp.acp-cleaning .acp-caution { margin: 0 0 30px; }

/* .acp-inset also carries a 40px top margin for sitting after prose. Here the
   two cards ARE the grid content, so that margin only pushes the row down.
   Equal heights keep them level when one list runs longer than the other. */
.acp.acp-cleaning .acp-inset { margin: 0; height: 100%; }
.acp.acp-cleaning .acp-inset .acp-ticks { margin-top: 20px; }

/* The peace-of-mind split runs two paragraphs, where every other page on this
   design runs a lede plus a .acp-benefits list. `.acp .acp-lede` sets margin: 0
   at (0,2,0) and `.acp p` only sets a BOTTOM margin, so the lede sat hard
   against both the h2 above it and the paragraph below it. */
.acp.acp-cleaning .acp-split-copy .acp-lede { margin: 22px 0 18px; }

/* The peace-of-mind image is the page's own, and it is only 590x400. The shared
   520px media box would upscale it about 1.3x on a 740px column, so the box is
   made shorter and the column narrower for this page: roughly 700x440, about
   1.2x. Three selectors because the media box has three forms: the raw wrapper,
   the pre-conversion <img class="acp-img">, and the post-conversion Elementor
   image widget whose wrapper carries the class. */
.acp.acp-cleaning .acp-split { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); }
.acp.acp-cleaning .acp-split-media .acp-media,
.acp.acp-cleaning .acp-split-media img.acp-img,
.acp.acp-cleaning .acp-split-media .acp-img img { min-height: 440px; }

/* Contact card and map, side by side. The card's copy is short and the map is
   440px, so centring them left the card floating against a much taller
   neighbour. Stretch both to the same height and centre the card's content
   inside it instead. */
.acp-cleaning .acp-local-grid { align-items: stretch; }
.acp.acp-cleaning .acp-green-card {
	display: flex;
	flex-direction: column;
	justify-content: center;
}

/* Contact card. The two phone numbers and the email are inline links on a green
   field, and nothing in the shared layer colours a plain <a> there, so they
   would fall back to the theme's link colour against #14683e. */
.acp.acp-cleaning .acp-green-card p a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.acp.acp-cleaning .acp-green-card p a:hover,
.acp.acp-cleaning .acp-green-card p a:focus-visible { color: var(--acp-mint); }

/* The Google map embed the page already carried, in the 430px column beside the
   contact card. The panel colour shows while the iframe loads.

   The iframe is positioned rather than sized at 100%: a percentage height only
   resolves against a definite one, and post-conversion the map div gains an
   Elementor widget wrapper between it and the iframe, which has no height of
   its own. Absolute positioning is indifferent to what sits in between. */
.acp-cleaning .acp-map {
	position: relative;
	height: 100%;
	min-height: 380px;
	border-radius: 16px;
	overflow: hidden;
	background: var(--acp-panel);
}
.acp-cleaning .acp-map iframe {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	border: 0;
}

/* The tertiary line under the final band's two pills, for anyone who landed
   here wanting new flooring rather than a clean. Quieter than the body copy so
   it cannot compete with the buttons above it.

   .acp-final-card is in the selector for weight, not for scoping: the shared
   `.acp .acp-final-card p { color: #fff }` is (0,2,1) and would beat a plain
   `.acp.acp-cleaning .acp-final-alt` at (0,2,0), so the muted colour would
   silently lose. Three classes clears it. */
.acp.acp-cleaning .acp-final-card .acp-final-alt {
	margin: 26px auto 0;
	font-size: 14px;
	color: rgba(255, 255, 255, 0.82);
}
.acp.acp-cleaning .acp-final-card .acp-final-alt a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.acp.acp-cleaning .acp-final-card .acp-final-alt a:hover,
.acp.acp-cleaning .acp-final-card .acp-final-alt a:focus-visible { color: var(--acp-mint); }

/* ---- Elementor compatibility, post-conversion ---------------------------
   The three gaps documented on the memberships block above hit this page too.
   Restated here rather than promoted into the shared layer, because the shared
   fix changes every converted page at once and that is Bron's call. */

/* 1. The tertiary hero row. Post-conversion .acp-hero-meta is an Elementor
      container and Elementor's two-class rules default it to a CENTRED COLUMN,
      so the arrow link and the service-area line stack and centre, and the
      arrow's 1px underline runs the full column width like a horizontal rule. */
.acp.acp-cleaning .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
.acp.acp-cleaning .acp-hero-meta > .acp-arrow.e-con {
	width: auto;
	flex: 0 0 auto;
}

/* 2. Headings on green render green on green. `.acp .acp-final-card .acp-h2 {
      color: #fff }` lands on the widget WRAPPER, while the compatibility
      layer's mirror `.acp .acp-h2 .elementor-heading-title` paints the real
      element green, and a direct rule beats an inherited one. Restated for the
      real element at (0,5,0) against the mirror's (0,3,0). The contact card's
      h3 needs the same treatment, which the memberships page did not surface
      because it has no green card. */
.acp.acp-cleaning .acp-final-card .acp-eyebrow .elementor-heading-title,
.acp.acp-cleaning .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-cleaning .acp-green-card .acp-h3 .elementor-heading-title { color: #fff; }
.acp.acp-cleaning .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-cleaning .acp-green-card .acp-h3 .elementor-heading-title em { color: var(--acp-mint); }

/* Breakpoints are restated because a (0,2,0) page selector outranks the shared
   (0,1,0) rules even inside their own media queries. */
@media (max-width: 960px) {
	.acp-cleaning .acp-services { padding: 60px 0 70px; }
	.acp-cleaning .acp-map { min-height: 300px; }
	.acp.acp-cleaning .acp-split { grid-template-columns: 1fr; }
	.acp.acp-cleaning .acp-split-media .acp-media,
	.acp.acp-cleaning .acp-split-media img.acp-img,
	.acp.acp-cleaning .acp-split-media .acp-img img { min-height: 260px; }
}

/* -------------------------------------------------------------------------
 * Company profile, page 107, /about-us/company-profile/
 *
 * Appended 21 August 2026. Four band classes and one padding correction, all
 * scoped to .acp-company so nothing here can reach another page.
 *
 * The page reuses .acp-hero, .acp-paths, .acp-guides, .acp-local, .acp-faq and
 * .acp-final as they stand. It needs four more bands, and rather than borrow a
 * class whose name says something else (.acp-rooms for a service section,
 * .acp-cost for a range section) each one is named for what it holds. The
 * values are the framework's own: 90px/100px desktop, 60px/70px under 960px,
 * alternating cream and offwhite.
 *
 * .acp-story takes 20px of top padding rather than 90px because it follows
 * .acp-paths, which closes on 20px, exactly as .acp-range does on the category
 * pages. .acp-guides is the reverse case: its 20px top assumes it follows
 * another offwhite band, and here it follows cream .acp-after, so it is
 * restored to a full 90px.
 * ---------------------------------------------------------------------- */

.acp-company .acp-story { background: var(--acp-offwhite); padding: 20px 0 100px; }
.acp-company .acp-service { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-company .acp-ranges { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-company .acp-after { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-company .acp-guides { padding: 90px 0 100px; }

/* Anchor targets, so a jump link does not park the heading under the sticky
   header. Same 90px the category pages use on .acp-range. */
.acp-company .acp-story,
.acp-company .acp-service,
.acp-company .acp-ranges,
.acp-company .acp-after { scroll-margin-top: 90px; }

/* The two browse panels are lists of links with a count chip. The chip is a
   sibling of the anchor rather than inside it, so it needs the small left gap
   the inline chips elsewhere get from surrounding text. */
.acp-company .acp-ticks li .acp-chip { margin-left: 8px; }

@media (max-width: 960px) {
	.acp-company .acp-story { padding: 10px 0 70px; }
	.acp-company .acp-service,
	.acp-company .acp-ranges,
	.acp-company .acp-after,
	.acp-company .acp-guides { padding: 60px 0 70px; }
}

/* WCAG 2.2 2.5.8. The two browse panels on page 107 are lists of standalone
   links, not links inside a sentence, so the 24px minimum target size applies
   to them. The text line box is 18px, so the anchor is given a minimum height
   rather than padding, which would push the list items apart. Every label is
   at least 34px wide, so only the height needed fixing. */
.acp-company .acp-ticks li a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
}

/* ===== ANDERSENS OUR-PRODUCTS / JOIN-OUR-TEAM BLOCK: START =====
   Everything between this sentinel and the matching END sentinel is written by
   flooring-redesign/our-products-join-team/update-css-block.php. Anything
   appended AFTER the END sentinel is preserved by that script, which is the
   whole reason the sentinels exist: on 21 August 2026 a headerless
   .acp-company rule was appended below this block and a truncate-to-marker
   update silently removed it. Do not hand-edit between the sentinels; edit
   css-block.css in the repo and re-run the script.
   ============================================================== */
/* =========================================================================
   Our Products (page 109, /about-us/our-products/)
   Added 21 August 2026 with the Our Products redesign.

   Nothing above this block is edited, no token is introduced, no breakpoint is
   added, and every selector is scoped to .acp-ourproducts so no other page can
   be reached by any of it.

   Note on the scoping: .acp-ourproducts sits on the SAME element as .acp (the
   page root is <div class="acp acp-top acp-ourproducts">), so a descendant
   selector reads `.acp-ourproducts .thing`, and where it has to outrank an
   existing `.acp .thing` rule it is written `.acp.acp-ourproducts .thing` for
   the extra class. This mirrors the carpet cleaning, payment options and
   memberships blocks above.
   ====================================================================== */

/* Band rhythm: hero cream, flooring offwhite, windows cream, choosing
   offwhite, final offwhite. The two range bands are the page, so they get the
   full 90/100 section rhythm rather than .acp-range's own 84/40, which is short
   at the bottom because on an archive the product grid follows it. */
.acp-ourproducts .acp-range-flooring { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-ourproducts .acp-range-windows { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-ourproducts .acp-why { background: var(--acp-offwhite); }

/* The hero photograph is the only portrait frame on any of these pages
   (1708x2560), and the shared hero media box is `height: 100%; min-height:
   560px`, which on an auto-height grid row resolves to the image's intrinsic
   ratio. At an 831px column that made it 1246px tall and the hero 1376px, where
   every other page's hero is around 700px, and it pushed the range grid off the
   first screen entirely.

   So the box gets an explicit height and the frame is cropped rather than
   letterboxed. 700px sits just under the hero copy column's own height, and
   34% from the top is measured, not guessed: it is the offset that keeps both
   roller blinds, the sofa, the rug and the carpet edge inside the crop, which
   is the whole reason this frame was chosen for a page about floors AND window
   furnishings. Three selectors because the media box has three forms: the raw
   wrapper, the pre-conversion <img class="acp-img">, and the post-conversion
   Elementor image widget whose wrapper carries the class. */
.acp.acp-ourproducts .acp-hero-media .acp-media,
.acp.acp-ourproducts .acp-hero-media img.acp-img,
.acp.acp-ourproducts .acp-hero-media .acp-img img {
	height: 700px;
	min-height: 0;
	object-position: 50% 34%;
}

/* Ten flooring cards divide into two clean rows of five. A four-up grid would
   leave a lonely pair on a third row, which is the exact problem the curtains,
   tiles and shutters rules above were written to avoid. Windows is four
   standalone pages, so four up fills its row exactly.

   `display: grid` is restated rather than inherited: post-conversion these are
   Elementor containers, and `.e-con { display: var(--display) }` is (0,1,0),
   the same weight as the shared `.acp-guide-grid`. Restating it at (0,2,0)
   means the grid cannot depend on stylesheet order. */
.acp-ourproducts .acp-range-flooring .acp-guide-grid {
	display: grid;
	grid-template-columns: repeat(5, minmax(0, 1fr));
}
.acp-ourproducts .acp-range-windows .acp-guide-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* A five-up card is about 250px wide at 1440, and the shared 27px card heading
   is too big for it. 22px is the card scale used here. Both forms are needed:
   the h3 pre-conversion, the widget's inner element after it. */
.acp.acp-ourproducts .acp-range h3.acp-h3,
.acp.acp-ourproducts .acp-range .acp-h3 .elementor-heading-title { font-size: 22px; }

/* "Engineered Timber" and "Vinyl Plank" still take two lines in a 250px card
   while "Carpet" and "Cork" take one, so the descriptions started at different
   heights right across the row. Reserving two lines on the flooring grid's
   headings lines every description up. Measured, not guessed: 22px at
   line-height 1.15 is 25.3px a line, so two lines plus the shared 12px bottom
   margin is 2.3em.

   Only the flooring grid. The four window and outdoor labels are all single
   words in a 320px card, so the same rule there would just add a blank line. */
.acp.acp-ourproducts .acp-range-flooring h3.acp-h3,
.acp.acp-ourproducts .acp-range-flooring .acp-h3 .elementor-heading-title { min-height: 2.3em; }

/* The choosing list carries a heading, a paragraph and an arrow link per item,
   where every other page on this design carries a heading and a paragraph.
   `.acp .acp-benefits p` sets margin: 0 at (0,2,1), so the arrow link sat hard
   against the paragraph above it. */
.acp.acp-ourproducts .acp-benefits li p + p { margin-top: 12px; }

/* `.acp .acp-lede` sets margin: 0 at (0,2,0) and `.acp p` only sets a BOTTOM
   margin, so the split's lede sat hard against the h2 above it. Same fix as
   the carpet cleaning block. */
.acp.acp-ourproducts .acp-split-copy .acp-lede { margin: 22px 0 0; }

/* The tertiary line under the final band's two pills. .acp-final-card is in the
   selector for weight, not for scoping: the shared `.acp .acp-final-card p`
   is (0,2,1) and would beat a plain `.acp.acp-ourproducts .acp-final-alt` at
   (0,2,0), so the muted colour would silently lose. Three classes clears it. */
.acp.acp-ourproducts .acp-final-card .acp-final-alt {
	margin: 26px auto 0;
	font-size: 14px;
	color: rgba(255, 255, 255, 0.82);
}
.acp.acp-ourproducts .acp-final-card .acp-final-alt a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.acp.acp-ourproducts .acp-final-card .acp-final-alt a:hover,
.acp.acp-ourproducts .acp-final-card .acp-final-alt a:focus-visible { color: var(--acp-mint); }

/* ---- Elementor compatibility, post-conversion ---------------------------
   The two gaps documented on the memberships, installation and carpet cleaning
   blocks above hit this page too. Restated here rather than promoted into the
   shared layer, because the shared fix changes every converted page at once and
   that is Bron's call. */

/* 1. The tertiary hero row. Post-conversion .acp-hero-meta is an Elementor
      container and Elementor's two-class rules default it to a CENTRED COLUMN,
      so the arrow link and the count line stack and centre, and the arrow's 1px
      underline runs the full column width like a horizontal rule. */
.acp.acp-ourproducts .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
.acp.acp-ourproducts .acp-hero-meta > .acp-arrow.e-con {
	width: auto;
	flex: 0 0 auto;
}

/* 2. Headings on green render green on green. `.acp .acp-final-card .acp-h2 {
      color: #fff }` lands on the widget WRAPPER, while the compatibility
      layer's mirror `.acp .acp-h2 .elementor-heading-title` paints the real
      element green, and a direct rule beats an inherited one. Restated for the
      real element at (0,5,0) against the mirror's (0,3,0). */
.acp.acp-ourproducts .acp-final-card .acp-eyebrow .elementor-heading-title,
.acp.acp-ourproducts .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-ourproducts .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* Breakpoints are restated because a (0,2,0) page selector outranks the shared
   (0,1,0) rules even inside their own media queries. Five up drops to three
   before it drops to one, so a 280px card never has to squeeze below about
   280px on the way down. */
@media (max-width: 1200px) {
	.acp-ourproducts .acp-range-flooring .acp-guide-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
	.acp-ourproducts .acp-range-windows .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-ourproducts .acp-range-flooring { padding: 60px 0 70px; }
	.acp-ourproducts .acp-range-windows { padding: 60px 0 70px; }
	/* The hero stacks here, so the media box is a banner rather than a column
	   and 700px is far too tall for it. */
	.acp.acp-ourproducts .acp-hero-media .acp-media,
	.acp.acp-ourproducts .acp-hero-media img.acp-img,
	.acp.acp-ourproducts .acp-hero-media .acp-img img { height: 360px; }
	.acp-ourproducts .acp-range-flooring .acp-guide-grid,
	.acp-ourproducts .acp-range-windows .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
	.acp-ourproducts .acp-range-flooring .acp-guide-grid,
	.acp-ourproducts .acp-range-windows .acp-guide-grid { grid-template-columns: 1fr; }
}

/* =========================================================================
   Join Our Team (page 111, /about-us/join-our-team/)
   Added 21 August 2026 with the Join Our Team redesign.

   Same scoping discipline as the block above: everything is under
   .acp-jointeam, which sits on the same element as .acp, and anything that has
   to outrank a shared `.acp .thing` rule is written `.acp.acp-jointeam .thing`.

   This page has one thing none of the others do: a third-party plugin's markup
   in the middle of the design. The Job Openings plugin's [awsmjobs] listing has
   to stay a live shortcode, because the page is converted to static Elementor
   content and a frozen jobs list would keep advertising closed roles. So the
   shortcode widget is wrapped in a container carrying `acp acp-jointeam
   acp-jobs` (all three on the SAME element, so its own band rule is written
   `.acp.acp-jobs`, not `.acp-jointeam .acp-jobs`), and the plugin's own classes
   are restyled from here. Only
   .awsm-* selectors under .acp-jobs are touched, so the plugin's output
   anywhere else on the site is untouched.
   ====================================================================== */

/* Band rhythm: hero cream, about offwhite, culture cream, openings offwhite,
   final offwhite. */
.acp-jointeam .acp-why { background: var(--acp-offwhite); }
.acp-jointeam .acp-culture { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-jointeam .acp-openings { background: var(--acp-offwhite); padding: 90px 0 0; scroll-margin-top: 90px; }
.acp.acp-jobs { background: var(--acp-offwhite); padding: 0 0 100px; }

/* `.acp .acp-lede` sets margin: 0 at (0,2,0) and `.acp p` only sets a BOTTOM
   margin, so the about split's lede sat hard against the h2 above it and
   against the paragraph below it. Same fix as the carpet cleaning block. */
.acp.acp-jointeam .acp-split-copy .acp-lede { margin: 22px 0 18px; }

/* Culture: two stacked panels beside one image. .acp-panel-grid is a two-column
   grid by default, which would put both panels in the left half of an already
   half-width column, so it is flattened to one column here. */
.acp-jointeam .acp-culture-grid {
	display: grid;
	grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
	gap: 44px;
	/* stretch, not start: the two panels stack about 580px tall and the image's
	   own 420px min-height left an 85px ragged edge below it. Stretching makes
	   the photograph finish level with the second panel. */
	align-items: stretch;
}
.acp.acp-jointeam .acp-culture-grid .acp-panel-grid {
	grid-template-columns: minmax(0, 1fr);
	gap: 24px;
	margin: 0;
}

/* .acp-inset carries a 40px top margin for sitting after prose. Here the panels
   ARE the grid content, so that margin only pushes the first one out of line
   with the image beside it. */
.acp.acp-jointeam .acp-culture-grid .acp-inset { margin: 0; }

/* The culture image is 1280x601, a wide frame in a roughly 600px column, so it
   is given a shorter box than the shared 520px split media and left to crop.
   Three selectors because the media box has three forms: the raw wrapper, the
   pre-conversion <img class="acp-img">, and the post-conversion Elementor image
   widget whose wrapper carries the class. */
.acp-jointeam .acp-culture-media .acp-media,
.acp.acp-jointeam .acp-culture-media img.acp-img,
.acp.acp-jointeam .acp-culture-media .acp-img img {
	min-height: 420px;
	height: 100%;
	border-radius: 16px;
}

/* ---- The Job Openings plugin listing ------------------------------------
   The plugin ships its own grid, cards and typography. Everything below only
   brings those into the design's card, radius, shadow and colour language. No
   markup is altered and no plugin behaviour is changed. */

.acp-jobs .awsm-job-wrap { margin: 0; }

/* The plugin's three-up grid is a float/flex hybrid with its own gutters.
   Replaced with the design's own grid so the cards line up with the two card
   grids on the Our Products page. */
.acp-jobs .awsm-job-listings.awsm-row {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 26px;
	margin: 0;
}
.acp-jobs .awsm-job-listing-item.awsm-grid-item {
	width: auto;
	max-width: none;
	margin: 0;
	padding: 0;
	float: none;
}

/* The card itself. One shadow, 16px radius, the same as .acp-guide. */
.acp-jobs .awsm-job-item {
	display: block;
	height: 100%;
	background: rgba(255, 255, 255, 0.9);
	border: 0;
	/* Figma 29:818: radius 15, 10px mount around the picture. */
	border-radius: 15px;
	padding: 10px 10px 18px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	text-decoration: none;
	color: var(--acp-ink);
	transition: box-shadow 0.18s ease;
}
.acp-jobs .awsm-job-item:hover,
.acp-jobs .awsm-job-item:focus-visible { box-shadow: 0 6px 18px rgba(0, 0, 0, 0.08); }

.acp-jobs .awsm-job-featured-image { margin: 0; }
.acp-jobs .awsm-job-featured-image img {
	display: block;
	width: 100%;
	height: 190px;
	object-fit: cover;
	border-radius: 10px;
}

/* The plugin renders the role name as an h2. The heading LEVEL is the plugin's
   and is left alone; only its appearance is brought into the design. */
.acp-jobs h2.awsm-job-post-title {
	font-family: var(--acp-serif);
	font-weight: 400;
	font-size: 22px;
	line-height: 1.15;
	color: var(--acp-green);
	margin: 18px 14px 0;
	padding: 0;
	text-transform: none;
	letter-spacing: 0;
}

/* Job type chips, on the design's pill. */
.acp-jobs .awsm-job-specification-wrapper {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 14px 14px 0;
}
.acp-jobs .awsm-job-specification-item { margin: 0; }
.acp-jobs .awsm-job-specification-term {
	display: inline-flex;
	align-items: center;
	min-height: 26px;
	padding: 4px 12px;
	border: 1px solid var(--acp-line);
	border-radius: 999px;
	background: var(--acp-offwhite);
	font-size: 13px;
	line-height: 1.3;
	color: var(--acp-muted);
}

/* "More Details" as the design's arrow link. The plugin draws its own chevron
   in an empty <span>, which is kept: replacing it would mean editing plugin
   markup. */
.acp-jobs .awsm-job-more-container { margin: 16px 14px 0; }
.acp-jobs .awsm-job-more {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 24px;
	font-size: 14px;
	font-weight: 700;
	color: var(--acp-green);
	border-bottom: 1px solid currentColor;
	padding-bottom: 2px;
}
.acp-jobs .awsm-job-item:hover .awsm-job-more { color: var(--acp-green-dark); }

/* The plugin's pagination and its "no jobs" notice. */
.acp-jobs .awsm-jobs-pagination { margin: 34px 0 0; }
.acp-jobs .awsm-job-no-results,
.acp-jobs .awsm-jobs-none-container { margin: 0; color: var(--acp-muted); }

/* ---- Elementor compatibility, post-conversion ---------------------------
   The same two gaps as the block above. Restated rather than promoted into the
   shared layer, because the shared fix changes every converted page at once. */

.acp.acp-jointeam .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
.acp.acp-jointeam .acp-hero-meta > .acp-arrow.e-con {
	width: auto;
	flex: 0 0 auto;
}

.acp.acp-jointeam .acp-final-card .acp-eyebrow .elementor-heading-title,
.acp.acp-jointeam .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-jointeam .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* The culture grid and the panel grid both become Elementor containers, and
   `.e-con { display: var(--display) }` is (0,1,0), the same weight as a single
   .acp class, so both grids are restated at two classes. */
.acp-jointeam .acp-culture-grid.e-con { display: grid; }
.acp.acp-jointeam .acp-culture-grid .acp-panel-grid.e-con { display: grid; }

/* Breakpoints are restated because a (0,2,0) page selector outranks the shared
   (0,1,0) rules even inside their own media queries. */
@media (max-width: 1200px) {
	.acp-jobs .awsm-job-listings.awsm-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-jointeam .acp-culture { padding: 60px 0 70px; }
	.acp-jointeam .acp-openings { padding: 60px 0 0; }
	.acp.acp-jobs { padding: 0 0 70px; }
	.acp-jointeam .acp-culture-grid { grid-template-columns: 1fr; gap: 30px; }
	.acp-jointeam .acp-culture-media .acp-media,
	.acp.acp-jointeam .acp-culture-media img.acp-img,
	.acp.acp-jointeam .acp-culture-media .acp-img img { min-height: 260px; }
}

@media (max-width: 640px) {
	.acp-jobs .awsm-job-listings.awsm-row { grid-template-columns: 1fr; }
}


/* =========================================================================
   Elementor's DEFAULT container padding, zeroed on these two pages only.
   Added 21 August 2026.

   Every container Elementor creates picks up a 10px default padding from the
   kit, and the .acp design layer has no opinion about it, so nothing overrides
   it. On a converted page that lands on three nested levels at once (the page
   root, the section wrap and the head), which is why the "Current
   opportunities" heading on page 111 started at x=50 while the [awsmjobs]
   cards it introduces started at x=20: the jobs block is hand-built and
   carries its own padding rule, so it never picked the default up.

   Measured on staging, 375px: removing it aligned the two and took 859px of
   stray vertical padding off page 111.

   It is set through the VARIABLES Elementor consumes rather than as a `padding`
   declaration, deliberately. Every real padding in the design (.acp-inset's
   26px/24px, .acp-final-card's 44px/20px/48px, .acp-openings' own 60px top) is
   written as a direct `padding` property and keeps winning; only padding that
   exists solely because of the default disappears. Verified on staging: all
   three of those kept their values.

   Scoped to these two pages. The other eleven converted pages carry the same
   stray padding and promoting this into the shared compatibility layer would
   tighten all of them at once, which is Bron's call, not a side effect of this
   build. See the same reasoning on the memberships, installation and carpet
   cleaning blocks above.
   ====================================================================== */

.acp-ourproducts .e-con,
.acp-ourproducts.e-con,
.acp-jointeam .e-con,
.acp-jointeam.e-con,
.acp-jobs.e-con {
	--padding-top: 0px;
	--padding-right: 0px;
	--padding-bottom: 0px;
	--padding-left: 0px;
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-inline-start: 0px;
	--padding-inline-end: 0px;
}
/* ===== ANDERSENS OUR-PRODUCTS / JOIN-OUR-TEAM BLOCK: END ===== */
/* ===== ACP-ABOUT BLOCK: START ===== */
/* =========================================================================
   About Us (page 105, /about-us/)
   Added 21 August 2026 with the About Us redesign.

   Nothing above this block is edited, no token is introduced, no breakpoint is
   added, and every selector is scoped to .acp-about so no other page can be
   reached by any of it.

   Note on the scoping: .acp-about sits on the SAME element as .acp (the page
   root is <div class="acp acp-top acp-about">), so a descendant selector reads
   `.acp-about .thing`, and where it has to outrank an existing `.acp .thing`
   rule it is written `.acp.acp-about .thing` for the extra class. This mirrors
   the carpet cleaning, in-home service, installation, payment options and
   memberships blocks above.
   ====================================================================== */

/* Band rhythm. Eleven sections, alternating cream and offwhite, with the
   at-a-glance strip reading as part of the cream hero rather than as its own
   band. Only backgrounds and, where a section no longer follows the band it was
   designed to follow, top padding are restated. */
.acp-about .acp-advice { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-about .acp-range-links { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-about .acp-guides { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-about .acp-local { background: var(--acp-offwhite); }
.acp-about .acp-faq { background: var(--acp-cream); }
.acp-about .acp-final { background: var(--acp-cream); }

/* .acp-trust ships with `padding: 20px 0 100px` because on the category pages it
   follows another offwhite band directly. Here it follows the cream "how we
   help" band, so it needs a real opening gap. */
.acp-about .acp-trust { padding: 90px 0 100px; }

/* ---------------------------------------------------------------- at a glance

   Four facts under the hero, replacing the two unsourced animated counters the
   old page carried. Cream, so it continues the hero band, separated from it by
   the standard hairline rather than by a background change. */
.acp-about .acp-glance {
	background: var(--acp-cream);
	padding: 0 0 88px;
}
.acp-about .acp-glance .acp-wrap {
	border-top: 1px solid var(--acp-line);
	padding-top: 44px;
}
.acp.acp-about .acp-glance-h {
	margin: 0 0 26px;
	color: var(--acp-muted);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}
.acp-about .acp-glance-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 26px;
}
.acp-about .acp-glance-item { min-width: 0; }
.acp.acp-about .acp-glance-n {
	font-family: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
	font-weight: 600;
	font-size: 54px;
	line-height: 1;
	letter-spacing: -0.01em;
	color: var(--acp-green);
	margin: 0 0 10px;
}
.acp.acp-about .acp-glance-note {
	margin: 0;
	font-size: 14px;
	color: var(--acp-muted);
}

/* ------------------------------------------------------------- what we sell

   Two grouped link lists in the shared white insets. .acp-inset carries a 40px
   top margin for sitting after prose; here the two cards ARE the grid content,
   so that margin only pushes the row down. Equal heights keep them level when
   one list runs longer than the other, which it does: eight flooring ranges
   against four window ranges. Same fix as the cleaning service cards. */
.acp.acp-about .acp-panel-grid .acp-inset { margin: 0; height: 100%; }
.acp.acp-about .acp-range-list { margin: 22px 0 0; }

/* Single column for the four window ranges, so both cards are four rows deep.
   .acp-cols on the eight flooring ranges gives it its two columns. */
.acp-about .acp-range-one { display: block; }

/* The range links are the only reason to visit this section, so they get the
   green link treatment rather than inheriting body colour. The mint dot comes
   from .acp-ticks.

   inline-block plus vertical padding is what gets the tap target to 25px.
   WCAG 2.2 SC 2.5.8 wants 24px, and the exemption for links inside a run of
   prose does NOT apply here: these are twelve list items whose whole purpose is
   to be tapped, and at their natural 19px line box they were the only failure on
   the page. The dot has to move down with the text, because .acp-ticks positions
   it against the top of the li and the padding pushes the label 3px lower. */
.acp.acp-about .acp-range-list a {
	display: inline-block;
	padding: 3px 0;
	color: var(--acp-green);
	text-decoration: none;
	border-bottom: 1px solid transparent;
}
.acp.acp-about .acp-range-list li::before { top: 11px; }
.acp.acp-about .acp-range-list a:hover,
.acp.acp-about .acp-range-list a:focus-visible {
	color: var(--acp-green-dark);
	border-bottom-color: var(--acp-green-dark);
}

/* ------------------------------------------------------- text-only guide cards

   Both guide grids on this page are text cards with no photograph, because
   Andersens has not supplied per-service or per-section imagery and a grey
   placeholder in twelve card slots would swamp the page. The shared .acp-guide
   assumes an image above the body, so the body's own padding has to open the
   card out instead, and the chevron is drawn in CSS rather than being an inline
   SVG. That is deliberate: an .acp-arrow sitting directly in a div (not inside a
   <p>) is the exact shape acp-converter.php used to destroy, and a pseudo
   element cannot be recursed into at all. */
.acp-about .acp-guide {
	display: flex;
	flex-direction: column;
	padding: 0;
}
.acp-about .acp-guide-body {
	padding: 30px 30px 32px;
	display: flex;
	flex-direction: column;
	height: 100%;
}
.acp.acp-about .acp-guide-body p { margin: 0 0 22px; }

/* `.acp h4.acp-h4` needs the h4 TAG, so the <h3 class="acp-h4"> used in these
   cards never matches it and falls back to the theme's h3 (18px, #333, wrong
   face). The headings are h3 so the outline stays correct under each section's
   h2, so the label styling is restated for them. Post-conversion the shared
   mirror `.acp .acp-h4 .elementor-heading-title` already covers the real
   element; this rule is what makes the shortcode render match it. Same mismatch
   is live on the blinds, awnings, shutters and memberships step grids; lowering
   the shared rule to `.acp .acp-h4` would change five pages at once, so it is
   restated here instead. */
.acp.acp-about .acp-guide h3.acp-h4 {
	font-family: inherit;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--acp-green);
	margin: 0 0 12px;
	text-transform: none;
	letter-spacing: 0;
}
.acp.acp-about .acp-guide .acp-h4 .elementor-heading-title { font-size: 17px; }

/* The chevron. margin-top: auto pins it to the bottom of the card so a row of
   cards with unequal copy lengths still lines its affordances up. */
.acp-about .acp-guide-body::after {
	content: '';
	display: block;
	margin: auto 0 0;
	width: 26px;
	height: 10px;
	background: var(--acp-green);
	clip-path: polygon(0 42%, 62% 42%, 47% 6%, 60% 0, 100% 50%, 60% 100%, 47% 94%, 62% 58%, 0 58%);
	transition: transform 0.18s ease;
}
.acp-about .acp-guide:hover .acp-guide-body::after,
.acp-about .acp-guide:focus-visible .acp-guide-body::after { transform: translateX(5px); }

@media (prefers-reduced-motion: reduce) {
	.acp-about .acp-guide-body::after { transition: none; }
	.acp-about .acp-guide:hover .acp-guide-body::after,
	.acp-about .acp-guide:focus-visible .acp-guide-body::after { transform: none; }
}

/* ------------------------------------------------------------- find near you

   The store map sits in the shared .acp-local-grid's second column. It is a
   green-on-green PNG with its own rounded corners already baked in, so it gets
   no card, no shadow and no background: anything behind it would read as a
   double frame. Contain rather than cover, because cropping the map would cut
   store markers off. */
.acp-about .acp-about-map { min-width: 0; }
.acp.acp-about .acp-about-map .acp-media {
	background: none;
	box-shadow: none;
	border-radius: 0;
	height: auto;
}
.acp.acp-about .acp-about-map .acp-media img,
.acp.acp-about .acp-about-map img.acp-img {
	width: 100%;
	height: auto;
	object-fit: contain;
	border-radius: 14px;
}

/* ------------------------------------------------ portrait split imagery

   A FRAMEWORK GAP, not a quirk of this page. `.acp-split-media img.acp-img`
   sets `min-height: 520px` and no maximum, so the shared rule only ever
   constrains an image that would render SHORTER than 520px. Every page built on
   this framework so far used landscape sources, where the natural height at a
   611px column is about 407px and the minimum raises it to 520.

   The real-advice slot here is a 1155x2000 portrait frame, the only unclaimed
   showroom photograph left in the library. Its natural height at 611px wide is
   1058px, which is ABOVE the minimum, so nothing constrained it and the band
   rendered at 1098px against the story band's 560px. object-fit: cover was
   already applied, so a definite height is all that was missing: the image now
   centre-crops instead of growing.

   Scoped to this page. Adding a max-height to the shared rule would be the
   better fix and would let any page use a portrait source, but it touches every
   band on fifteen live pages, so it is Bron's call rather than a side effect of
   this one. */
.acp.acp-about .acp-split-media .acp-media,
.acp.acp-about .acp-split-media .acp-img img,
.acp.acp-about .acp-split-media img.acp-img {
	height: 520px;
	max-height: 520px;
	object-fit: cover;
}

/* -------------------------------------------------------- the green card h2

   Every shipped green card on this framework heads with an .acp-h3, which
   carries `margin: 0 0 12px`. This one heads with an .acp-h2 so the page's
   heading outline stays flat (an h3 here would sit under no h2 of its own), and
   `.acp h2.acp-h2` sets `margin: 0` deliberately, because on a category page the
   h2 always lives inside .acp-head and that handles the spacing. In a green card
   there is no .acp-head, so the heading sat hard against the paragraph with a
   zero gap. 20px matches the 22px .acp-head produces. The final card needs
   nothing: `.acp-final-card p` already sets a 24px top margin. */
.acp.acp-about .acp-green-card .acp-h2 { margin: 0 0 20px; }

/* ------------------------------------------------- our story / advice splits

   Both splits run three or four paragraphs, where the category pages run a lede
   plus a .acp-benefits list. `.acp .acp-lede` sets margin: 0 at (0,2,0) and
   `.acp p` only sets a BOTTOM margin, so the lede sits hard against both the h2
   above it and the paragraph below it. Same fix as the cleaning page. */
.acp.acp-about .acp-split-copy .acp-lede { margin: 22px 0 18px; }
.acp.acp-about .acp-split-copy p:last-child { margin-bottom: 0; }

/* The advice split leads with its image so the two splits alternate. The media
   div is FIRST in the DOM, so grid auto-placement puts it in column one and no
   `order` is needed, which keeps the visual order and the DOM order the same.
   The shared .acp-split is copy 1fr / media 1.05fr, so flipped, the WIDER column
   has to move with it or the image column comes out narrower than the story
   split above it and the two bands stop lining up. (0,2,0) against the shared
   rule's (0,1,0). Same shape as .acp-inhome .acp-split-flip. */
.acp-about .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }

/* ------------------------------------------------ the page root's own padding

   THE 10px STRIP. Post-conversion the page root is a top-level Elementor
   container, `<div class="acp acp-top acp-about e-con e-con-full">`, and Elementor
   gives every container a default 10px padding. The .acp layer has no opinion
   about container padding, so nothing overrode it: every full-bleed band stopped
   10px short of both viewport edges and a strip of page background ran down each
   side of every cream and offwhite section. Measured on staging at 375px, the
   bands rendered 10..365 in a 375 viewport.

   Zeroed through the CSS VARIABLES Elementor consumes, never as a `padding`
   declaration. Every real design padding on this page is a direct `padding`
   property (.acp-inset 34/36, .acp-final-card 78/40/82, .acp-guide-body 30/30/32,
   the band rhythm's 90/100), and a `padding: 0` rule at two classes would destroy
   all of them.

   Scoped to the ROOT element only, not to `.acp .e-con`, so no inner container is
   even in range. This page has no classless scaffold container to worry about,
   because convert-about.php replaces the whole tree rather than swapping a
   shortcode widget inside a scaffold, which is the variant that leaves one behind
   on pages 109 and 111. Verified: zero classless .e-con descendants, and all
   twelve .acp-wrap elements share one left edge. */
.acp.acp-about.e-con {
	--padding-top: 0px;
	--padding-right: 0px;
	--padding-bottom: 0px;
	--padding-left: 0px;
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-inline-start: 0px;
	--padding-inline-end: 0px;
}

/* ------------------------------------------------------- Elementor compat

   Three fixes that every converted .acp page needs. All three are documented in
   flooring-redesign/elementor-convert/README.md and all three are currently
   restated per page rather than living in the shared compatibility layer.
   Scoped here for the same reason the five blocks above scope theirs: promoting
   them is Bron's call, not a side effect of this page. */

/* 1. The tertiary hero row. Post-conversion .acp-hero-meta is an Elementor
      container, and Elementor's own two-class rules default it to a CENTRED
      COLUMN, so the arrow link and the store count stack and centre instead of
      sitting on one left-aligned row. Cleared through the variables at three
      classes, mirroring the row containers at the end of this file. */
.acp.acp-about .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}

/* The arrow link becomes a container too, so it picks up .e-con's width: 100%
   and its 1px bottom border runs the full width of the column like a rule. */
.acp.acp-about .acp-hero-meta > .acp-arrow.e-con {
	width: auto;
	flex: 0 0 auto;
}

/* 2. Green card and final card headings, post-conversion.
      `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget
      WRAPPER, but the compatibility layer's mirror
      `.acp .acp-h2 .elementor-heading-title` sets the green heading colour on
      the real element inside it, and a direct rule beats an inherited one. So
      the heading renders GREEN ON GREEN and is invisible, with only the mint
      <em> showing. Restated for the real element at (0,5,0) against the
      mirror's (0,3,0). This page has two of them: the find-near-you green card
      and the final band. */
.acp.acp-about .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-about .acp-green-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-about .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-about .acp-green-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* 3. The two guide grids and the glance grid are row/grid containers, so their
      item containers inherit .e-con's width: 100% and stretch. The grid itself
      keeps its display from the rules above, which win because they are (0,2,0)
      against Elementor's two-class variable rules only for `display`; the gap
      variables have to be zeroed so the grid's own `gap` is what spaces it. */
.acp.acp-about .acp-glance-grid.e-con,
.acp.acp-about .acp-guide-grid.e-con {
	--gap: 0px; --row-gap: 0px; --column-gap: 0px;
}
.acp.acp-about .acp-guide-grid > .acp-guide.e-con { width: auto; }

/* ----------------------------------------------------------------- responsive

   Breakpoints are restated rather than inherited, because a (0,2,0) page
   selector outranks the shared (0,1,0) rules even inside their own media
   queries. No new breakpoint is introduced: 1200 / 960 / 640 only. */

@media (max-width: 1200px) {
	.acp-about .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
	.acp-about .acp-glance-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 30px 26px; }
	.acp.acp-about .acp-glance-n { font-size: 46px; }
	.acp-about .acp-guide-body { padding: 26px 26px 28px; }
}

@media (max-width: 960px) {
	.acp.acp-about .acp-split-media .acp-media,
	.acp.acp-about .acp-split-media .acp-img img,
	.acp.acp-about .acp-split-media img.acp-img { height: 280px; max-height: 280px; }
	.acp-about .acp-advice,
	.acp-about .acp-range-links,
	.acp-about .acp-guides { padding: 60px 0 70px; }
	.acp-about .acp-trust { padding: 60px 0 70px; }
	.acp-about .acp-glance { padding: 0 0 58px; }
	.acp-about .acp-glance .acp-wrap { padding-top: 34px; }
	/* Without this the flipped split keeps its two columns on a phone: the
	   (0,2,0) page rule above outranks the shared (0,1,0) 960px rule. */
	.acp-about .acp-split-flip { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
	.acp-about .acp-glance-grid { grid-template-columns: 1fr; gap: 26px; }
	.acp.acp-about .acp-glance-n { font-size: 42px; }
	.acp-about .acp-guide-body { padding: 24px 22px 26px; }
}

/* ===== ACP-ABOUT BLOCK: END ===== */

/* ===== ACP-ABOUT-CHILDREN BLOCK: START ===== */
/* =========================================================================
   The three remaining About children, 21 August 2026
     Guarantees        page 113  .acp-guarantees
     In the Community  page 115  .acp-community
     Project Green     page 366  .acp-green-page

   Nothing above this block is edited, no token is introduced, no breakpoint is
   added, and every selector carries one of those three root classes, so no other
   page can be reached by anything here.

   NOTE ON THE ROOT CLASS NAME: Project Green uses `.acp-green-page`, NOT
   `.acp-green`. `.acp-green` is already the name of the GREEN COLOUR TOKEN
   (--acp-green) and appears in `.acp-green-card`, so a page root called
   `.acp-green` would collide with `.acp-green-card` in any `.acp-green *`
   selector. Named `-page` deliberately.

   Scoping shape: the page root carries .acp AND the page class on the SAME
   element, so a descendant reads `.acp-guarantees .thing`, and where it must
   outrank an existing `.acp .thing` rule it is written
   `.acp.acp-guarantees .thing` for the extra class.
   ====================================================================== */

/* -------------------------------------------------------------- band rhythm */

/* Guarantees: hero cream, guarantee list offwhite, form band cream, faq
   offwhite, guides cream, final cream. */
.acp-guarantees .acp-gtee-list { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-guarantees .acp-formband { background: var(--acp-cream); padding: 72px 0 34px; }
.acp-guarantees .acp-formband .acp-head { max-width: none; margin-bottom: 0; }
.acp-guarantees .acp-faq { background: var(--acp-offwhite); }
.acp-guarantees .acp-guides { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-guarantees .acp-final { background: var(--acp-cream); }

/* In the Community */
.acp-community .acp-ways { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-community .acp-local { background: var(--acp-cream); }
.acp-community .acp-guides { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-community .acp-final { background: var(--acp-offwhite); }

/* Project Green */
.acp-green-page .acp-why { background: var(--acp-offwhite); }
.acp-green-page .acp-pftp { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-green-page .acp-counterband { background: var(--acp-offwhite); padding: 90px 0 30px; }
.acp-green-page .acp-countfoot { background: var(--acp-offwhite); padding: 0 0 90px; }
.acp-green-page .acp-guides { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-green-page .acp-final { background: var(--acp-cream); }

/* ------------------------------------------------- the two guarantee panels

   Each guarantee is one white inset so its terms cannot be read as belonging to
   the other, which is the whole risk of putting two guarantees on one page.
   .acp-inset ships with a 40px top margin for sitting after prose; here the
   panels ARE the section content, so the first one needs no push and the pair
   need a real gap between them. */
.acp.acp-guarantees .acp-gtee { margin: 0 0 26px; }
.acp.acp-guarantees .acp-gtee:last-child { margin-bottom: 0; }
.acp.acp-guarantees .acp-gtee p { max-width: 68em; }

/* The terms list. Same treatment as the memberships page: smaller, muted, and
   visually subordinate to the guarantee body, but NOT hidden, because the terms
   are part of the guarantee rather than a footnote to skip. */
.acp.acp-guarantees .acp-terms-label { margin: 26px 0 10px; }
.acp.acp-guarantees .acp-terms {
	margin: 0;
	padding: 0 0 0 20px;
	font-size: 15px;
	color: var(--acp-muted);
	max-width: 68em;
}
.acp.acp-guarantees .acp-terms li { padding: 0 0 10px; }
.acp.acp-guarantees .acp-terms li:last-child { padding-bottom: 0; }

/* The per-guarantee claim link sits under the terms, separated by a hairline so
   it does not read as another term. */
.acp.acp-guarantees .acp-gtee-cta {
	margin: 22px 0 0;
	padding-top: 20px;
	border-top: 1px solid var(--acp-line);
}

/* ------------------------------------------------ Project Green hero sizing

   ANDERSENS HAS NO HIGH-RESOLUTION PROJECT GREEN PHOTOGRAPHY. The largest
   planting image in the whole library is 700x350, and most are 590x400. The
   shared `.acp-hero-media` box is min-height 560px at about 830px wide, so a
   700x350 source has to be upscaled about 1.6x to cover it, which is visibly
   soft.

   The box is scaled down for this page only, which brings the upscale to about
   1.2x. Same trick, same reason, as `.acp.acp-cleaning .acp-split-media`.

   Flagged for Andersens: this page wants real photography. The fix is a shoot,
   not CSS. */
.acp-green-page .acp-hero-media .acp-ph,
.acp-green-page .acp-hero-media .acp-media,
.acp-green-page .acp-hero-media img { min-height: 420px; }

/* The two small campaign images in the splits, for the same reason.
   min-height MUST be overridden, not just max-height: the shared rule
   `.acp-split-media img.acp-img { min-height: 520px }` wins over any max-height,
   because in CSS min-height always beats max-height. Setting max-height alone
   left these at 520px and looked like the rule had not applied at all. */
.acp.acp-green-page .acp-split-media .acp-media,
.acp.acp-green-page .acp-split-media .acp-img img,
.acp.acp-green-page .acp-split-media img.acp-img {
	min-height: 430px;
	height: 430px;
	max-height: 430px;
	object-fit: cover;
}

/* The Plant for the Planet section is a prose band in the narrow container, not
   a split, because no library image suits it (see the note in the page file). The
   impact panel is the only card in it, so .acp-inset's 40px top margin is the
   gap it wants and nothing else is needed. */
.acp.acp-green-page .acp-impact-panel { margin: 34px 0 0; }

/* ------------------------------------------------------------- the impact list

   `<strong>` labels the three Impact lines. The shared .acp-ticks gives the mint
   dot; the label just needs to read as a label. */
.acp.acp-green-page .acp-impact { margin: 14px 0 0; }
.acp.acp-green-page .acp-impact li { padding-bottom: 14px; }
.acp.acp-green-page .acp-impact strong { color: var(--acp-green); }

/* ---------------------------------------------------------- the tree counter

   .acp-counterhost is the Elementor container holding the live
   [counter-planting] shortcode widget, so it sits OUTSIDE the .acp tree and
   cannot be reached by a `.acp ...` selector. Styled on its own class, the same
   arrangement as .acp-formhost.

   The number is whatever the shortcode returns, so nothing here assumes a digit
   count: it is centred and clamped rather than positioned. */
.acp-counterhost {
	background: var(--acp-offwhite);
	padding: 0 0 10px;
	text-align: center;
}
.acp-counterhost .elementor-widget-container { padding: 0 !important; }
.acp-counterhost,
.acp-counterhost * {
	font-family: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
	color: var(--acp-green);
}
.acp-counterhost {
	font-size: clamp(56px, 9vw, 132px);
	font-weight: 600;
	line-height: 1;
	letter-spacing: -0.01em;
}

.acp.acp-green-page .acp-countfoot-p {
	margin: 0;
	text-align: center;
	font-size: 15px;
	color: var(--acp-muted);
}
.acp.acp-green-page .acp-countfoot-p a { color: var(--acp-green); }

/* ------------------------------------------------------- In the Community

   The Project Green band reuses .acp-local-grid, whose second column is 430px.
   The campaign image is 600x600, so it is contained rather than cropped and
   given a white card, because it is artwork with its own margins. */
.acp-community .acp-community-media { min-width: 0; }
.acp.acp-community .acp-community-media .acp-media,
.acp.acp-community .acp-community-media img.acp-img {
	height: 340px;
	max-height: 340px;
	object-fit: contain;
	background: #fff;
	border-radius: 14px;
}

/* Two panels only, so they get the room the four-up grid would not give them. */
.acp.acp-community .acp-panel-grid .acp-inset { margin: 0; height: 100%; }

/* .acp-caution carries a 34px top margin for sitting after prose; here it
   follows the panel grid, which already has a 24px bottom margin. */
.acp.acp-community .acp-caution { margin: 6px 0 0; }

/* --------------------------------------------- splits with several paragraphs

   `.acp .acp-lede` sets margin: 0 at (0,2,0) and `.acp p` only sets a BOTTOM
   margin, so a lede followed by prose sits hard against both the h2 above and
   the paragraph below. Same fix as the cleaning and About Us pages. */
.acp.acp-guarantees .acp-split-copy .acp-lede,
.acp.acp-community .acp-split-copy .acp-lede,
.acp.acp-green-page .acp-split-copy .acp-lede { margin: 22px 0 18px; }
.acp.acp-guarantees .acp-split-copy p:last-child,
.acp.acp-community .acp-split-copy p:last-child,
.acp.acp-green-page .acp-split-copy p:last-child { margin-bottom: 0; }

/* The flipped split leads with its image, so the WIDER column has to move with
   it or the image column comes out narrower than the split above and the bands
   stop lining up. (0,2,0) against the shared rule's (0,1,0). */
.acp-green-page .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }

/* ---------------------------------------------------- text-only guide cards

   All three pages use text guide cards with no photograph, because Andersens has
   not supplied per-section imagery and grey placeholders in nine card slots
   would swamp them. The shared .acp-guide assumes an image above the body, so
   the body's own padding opens the card out, and the chevron is drawn in CSS
   rather than as an inline SVG: an .acp-arrow sitting directly in a div is the
   exact shape acp-converter.php used to destroy, and a pseudo element cannot be
   recursed into at all. Same as the About Us block. */
.acp-guarantees .acp-guide,
.acp-community .acp-guide,
.acp-green-page .acp-guide { display: flex; flex-direction: column; padding: 0; }

.acp-guarantees .acp-guide-body,
.acp-community .acp-guide-body,
.acp-green-page .acp-guide-body {
	padding: 30px 30px 32px;
	display: flex;
	flex-direction: column;
	height: 100%;
}
.acp.acp-guarantees .acp-guide-body p,
.acp.acp-community .acp-guide-body p,
.acp.acp-green-page .acp-guide-body p { margin: 0 0 22px; }

/* `.acp h4.acp-h4` needs the h4 TAG, so the <h3 class="acp-h4"> in these cards
   never matches it and falls back to the theme's h3. The headings are h3 so the
   outline stays correct under each section's h2, so the label styling is
   restated. Post-conversion the shared mirror
   `.acp .acp-h4 .elementor-heading-title` covers the real element; this is what
   makes the shortcode render match it. */
.acp.acp-guarantees .acp-guide h3.acp-h4,
.acp.acp-community .acp-guide h3.acp-h4,
.acp.acp-green-page .acp-guide h3.acp-h4 {
	font-family: inherit;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--acp-green);
	margin: 0 0 12px;
	text-transform: none;
	letter-spacing: 0;
}
.acp.acp-guarantees .acp-guide .acp-h4 .elementor-heading-title,
.acp.acp-community .acp-guide .acp-h4 .elementor-heading-title,
.acp.acp-green-page .acp-guide .acp-h4 .elementor-heading-title { font-size: 17px; }

.acp-guarantees .acp-guide-body::after,
.acp-community .acp-guide-body::after,
.acp-green-page .acp-guide-body::after {
	content: '';
	display: block;
	margin: auto 0 0;
	width: 26px;
	height: 10px;
	background: var(--acp-green);
	clip-path: polygon(0 42%, 62% 42%, 47% 6%, 60% 0, 100% 50%, 60% 100%, 47% 94%, 62% 58%, 0 58%);
	transition: transform 0.18s ease;
}
.acp-guarantees .acp-guide:hover .acp-guide-body::after,
.acp-community .acp-guide:hover .acp-guide-body::after,
.acp-green-page .acp-guide:hover .acp-guide-body::after { transform: translateX(5px); }

@media (prefers-reduced-motion: reduce) {
	.acp-guarantees .acp-guide-body::after,
	.acp-community .acp-guide-body::after,
	.acp-green-page .acp-guide-body::after { transition: none; }
	.acp-guarantees .acp-guide:hover .acp-guide-body::after,
	.acp-community .acp-guide:hover .acp-guide-body::after,
	.acp-green-page .acp-guide:hover .acp-guide-body::after { transform: none; }
}

/* ------------------------------------------------------------ green card h2

   Every shipped green card heads with an .acp-h3, which carries a bottom margin.
   These head with an .acp-h2 so the heading outline stays flat, and
   `.acp h2.acp-h2` sets `margin: 0` deliberately because on a category page the
   h2 always lives inside .acp-head. In a green card there is no .acp-head, so
   the heading sits hard against the paragraph. 20px matches what .acp-head
   produces. */
.acp.acp-community .acp-green-card .acp-h2 { margin: 0 0 20px; }

/* ------------------------------------------------------------- prose links

   THE .acp DESIGN LAYER HAS NO PROSE-LINK STYLE. There is no `.acp p a` rule
   anywhere in css/flooring-category.css, so a link inside a paragraph renders as
   the browser default: rgb(0, 0, 238), underlined. Measured on all three of these
   pages before this block existed. Only .acp-crumbs a and .acp-inhome (which
   added its own) are styled.

   That matters more here than usual: these pages carry prose links in FAQ
   answers, a caution callout, the Plant for the Planet paragraph and the final
   band, and on a GREEN card default blue is close to unreadable.

   Scoped to these three pages, matching what .acp-inhome already does. A generic
   `.acp p a` in the shared layer would fix it on all twenty-two pages at once and
   is worth doing, but that changes every live page, so it is Bron's call. */
.acp.acp-guarantees .acp-split-copy a,
.acp.acp-guarantees .acp-faq-a a,
.acp.acp-guarantees .acp-gtee a:not(.acp-arrow),
.acp.acp-community .acp-split-copy a,
.acp.acp-community .acp-caution a,
.acp.acp-community .acp-inset a,
.acp.acp-green-page .acp-split-copy a {
	color: var(--acp-green);
	text-decoration: none;
	border-bottom: 1px solid currentColor;
}
.acp.acp-guarantees .acp-split-copy a:hover,
.acp.acp-guarantees .acp-faq-a a:hover,
.acp.acp-guarantees .acp-faq-a a:focus-visible,
.acp.acp-community .acp-caution a:hover,
.acp.acp-community .acp-caution a:focus-visible,
.acp.acp-green-page .acp-split-copy a:hover,
.acp.acp-green-page .acp-split-copy a:focus-visible { color: var(--acp-green-dark); }

/* On green, the link has to invert or it is unreadable. */
.acp.acp-guarantees .acp-final-card a:not(.acp-btn),
.acp.acp-community .acp-final-card a:not(.acp-btn),
.acp.acp-community .acp-green-card a:not(.acp-btn),
.acp.acp-green-page .acp-final-card a:not(.acp-btn) {
	color: #fff;
	text-decoration: none;
	border-bottom: 1px solid currentColor;
}
.acp.acp-guarantees .acp-final-card a:not(.acp-btn):hover,
.acp.acp-guarantees .acp-final-card a:not(.acp-btn):focus-visible,
.acp.acp-community .acp-final-card a:not(.acp-btn):hover,
.acp.acp-community .acp-final-card a:not(.acp-btn):focus-visible,
.acp.acp-community .acp-green-card a:not(.acp-btn):hover,
.acp.acp-community .acp-green-card a:not(.acp-btn):focus-visible,
.acp.acp-green-page .acp-final-card a:not(.acp-btn):hover,
.acp.acp-green-page .acp-final-card a:not(.acp-btn):focus-visible { color: var(--acp-cream); }

/* ------------------------------------------------------- Elementor compat

   The three fixes every converted .acp page needs. All three are documented in
   flooring-redesign/elementor-convert/README.md and all three are still
   restated per page rather than living in the shared compatibility layer.
   Promoting them is Bron's call. */

/* 1. Post-conversion .acp-hero-meta is an Elementor container, and Elementor's
      two-class rules default it to a CENTRED COLUMN, so the arrow link and any
      count stack and centre instead of sitting on one left-aligned row. */
.acp.acp-guarantees .acp-hero-meta.e-flex,
.acp.acp-community .acp-hero-meta.e-flex,
.acp.acp-green-page .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
.acp.acp-guarantees .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-community .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-green-page .acp-hero-meta > .acp-arrow.e-con { width: auto; flex: 0 0 auto; }

/* 2. `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget WRAPPER,
      but the compatibility layer's mirror `.acp .acp-h2 .elementor-heading-title`
      paints the real element green, and a direct rule beats an inherited one, so
      the heading renders GREEN ON GREEN and is invisible. Restated for the real
      element at (0,5,0) against the mirror's (0,3,0). */
.acp.acp-guarantees .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-community .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-community .acp-green-card .acp-h2 .elementor-heading-title,
.acp.acp-green-page .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-guarantees .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-community .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-community .acp-green-card .acp-h2 .elementor-heading-title em,
.acp.acp-green-page .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* 3. The converted page ROOT is a top-level Elementor container and picks up
      Elementor's default 10px padding, which stops every full-bleed band 10px
      short of both viewport edges and runs a strip of page background down each
      side. Zeroed through the VARIABLES Elementor consumes, never as a `padding`
      declaration: every real design padding here is a direct `padding` property
      and a `padding: 0` rule would destroy all of them. Scoped to the root
      element only, so no inner container is in range. */
.acp.acp-guarantees.e-con,
.acp.acp-community.e-con,
.acp.acp-green-page.e-con {
	--padding-top: 0px;
	--padding-right: 0px;
	--padding-bottom: 0px;
	--padding-left: 0px;
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-inline-start: 0px;
	--padding-inline-end: 0px;
}

/* Grid containers: zero the gap variables so the grid's own `gap` spaces it. */
.acp.acp-guarantees .acp-guide-grid.e-con,
.acp.acp-community .acp-guide-grid.e-con,
.acp.acp-green-page .acp-guide-grid.e-con {
	--gap: 0px; --row-gap: 0px; --column-gap: 0px;
}
.acp.acp-guarantees .acp-guide-grid > .acp-guide.e-con,
.acp.acp-community .acp-guide-grid > .acp-guide.e-con,
.acp.acp-green-page .acp-guide-grid > .acp-guide.e-con { width: auto; }

/* ----------------------------------------------------------------- responsive

   Breakpoints are restated rather than inherited, because a (0,2,0) page
   selector outranks the shared (0,1,0) rules even inside their own media
   queries. No new breakpoint: 1200 / 960 / 640 only. */

@media (max-width: 1200px) {
	.acp-green-page .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
	.acp-guarantees .acp-guide-body,
	.acp-community .acp-guide-body,
	.acp-green-page .acp-guide-body { padding: 26px 26px 28px; }
}

@media (max-width: 960px) {
	.acp-guarantees .acp-gtee-list,
	.acp-guarantees .acp-guides,
	.acp-community .acp-ways,
	.acp-community .acp-guides,
	.acp-green-page .acp-pftp,
	.acp-green-page .acp-guides { padding: 60px 0 70px; }
	.acp-green-page .acp-counterband { padding: 60px 0 20px; }
	.acp-green-page .acp-countfoot { padding: 0 0 60px; }
	.acp-green-page .acp-split-flip { grid-template-columns: 1fr; }
	.acp.acp-green-page .acp-split-media .acp-media,
	.acp.acp-green-page .acp-split-media .acp-img img,
	.acp.acp-green-page .acp-split-media img.acp-img { min-height: 280px; height: 280px; max-height: 280px; }
	.acp-green-page .acp-hero-media .acp-ph,
	.acp-green-page .acp-hero-media .acp-media,
	.acp-green-page .acp-hero-media img { min-height: 260px; }
	.acp.acp-community .acp-community-media .acp-media,
	.acp.acp-community .acp-community-media img.acp-img { height: 260px; max-height: 260px; }
	.acp.acp-guarantees .acp-gtee { margin-bottom: 20px; }
}

@media (max-width: 640px) {
	.acp-guarantees .acp-guide-body,
	.acp-community .acp-guide-body,
	.acp-green-page .acp-guide-body { padding: 24px 22px 26px; }
	.acp-counterhost { font-size: clamp(48px, 14vw, 84px); }
}
/* ===== ACP-ABOUT-CHILDREN BLOCK: END ===== */

/* ===== ACP-HUBS BLOCK: START ===== */
/* =========================================================================
   The two section hubs, 21 August 2026
     Services            page 117    .acp-services-hub
     Window Furnishings  page 16253  .acp-window

   Nothing above this block is edited, no token is introduced, no breakpoint is
   added, and every selector carries one of those two root classes.

   NOTE ON THE SERVICES ROOT CLASS: it is `.acp-services-hub`, NOT
   `.acp-services`. `.acp-services` is already a SECTION class used by the carpet
   cleaning page, so a page root called `.acp-services` would make every
   `.acp-services .thing` rule in this block apply to that section too.

   Scoping shape: the page root carries .acp AND the page class on the SAME
   element, so a descendant reads `.acp-window .thing`, and where it must outrank
   an existing `.acp .thing` rule it is written `.acp.acp-window .thing`.
   ====================================================================== */

/* -------------------------------------------------------------- band rhythm */

/* Services: hero cream, services offwhite, trust cream, faq offwhite, final
   offwhite. .acp-trust ships with `padding: 20px 0 100px` because on a category
   page it follows another offwhite band; here it follows the cream-free guides
   band and needs a real opening gap. */
.acp-services-hub .acp-guides { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-services-hub .acp-trust { background: var(--acp-cream); padding: 90px 0 100px; }
.acp-services-hub .acp-faq { background: var(--acp-offwhite); }
.acp-services-hub .acp-final { background: var(--acp-offwhite); }

/* Window Furnishings: hero cream, collections offwhite, why cream, faq
   offwhite, final offwhite. */
.acp-window .acp-guides { background: var(--acp-offwhite); padding: 90px 0 100px; }
.acp-window .acp-why { background: var(--acp-cream); }
.acp-window .acp-faq { background: var(--acp-offwhite); }
.acp-window .acp-final { background: var(--acp-offwhite); }

/* -------------------------------------------------- Services: six text cards

   Two rows of three, text only, matching About Us and the About children:
   Andersens has not supplied per-service imagery and six grey placeholders would
   swamp the page. The shared .acp-guide assumes an image above the body, so the
   body's own padding opens the card out, and the chevron is a CSS pseudo element
   rather than an inline SVG because an .acp-arrow sitting directly in a div is
   the exact shape acp-converter.php used to destroy. */
.acp-services-hub .acp-guide { display: flex; flex-direction: column; padding: 0; }
.acp-services-hub .acp-guide-body {
	padding: 30px 30px 32px;
	display: flex;
	flex-direction: column;
	height: 100%;
}
.acp.acp-services-hub .acp-guide-body p { margin: 0 0 22px; }

/* The card's gold stage label sits above the heading, so it needs less gap under
   it than .acp-meta-label's default. */
.acp.acp-services-hub .acp-guide .acp-meta-label { margin: 0 0 6px; }

/* `.acp h4.acp-h4` needs the h4 TAG, so the <h3 class="acp-h4"> in these cards
   never matches and falls back to the theme's h3. The headings are h3 so the
   outline stays correct under the section h2, so the label styling is restated.
   Post-conversion the shared mirror `.acp .acp-h4 .elementor-heading-title`
   covers the real element; this is what makes the shortcode render match it. */
.acp.acp-services-hub .acp-guide h3.acp-h4,
.acp.acp-window .acp-guide h3.acp-h4 {
	font-family: inherit;
	font-size: 17px;
	font-weight: 700;
	line-height: 1.35;
	color: var(--acp-green);
	margin: 0 0 12px;
	text-transform: none;
	letter-spacing: 0;
}
.acp.acp-services-hub .acp-guide .acp-h4 .elementor-heading-title,
.acp.acp-window .acp-guide .acp-h4 .elementor-heading-title { font-size: 17px; }

.acp-services-hub .acp-guide-body::after {
	content: '';
	display: block;
	margin: auto 0 0;
	width: 26px;
	height: 10px;
	background: var(--acp-green);
	clip-path: polygon(0 42%, 62% 42%, 47% 6%, 60% 0, 100% 50%, 60% 100%, 47% 94%, 62% 58%, 0 58%);
	transition: transform 0.18s ease;
}
.acp-services-hub .acp-guide:hover .acp-guide-body::after,
.acp-services-hub .acp-guide:focus-visible .acp-guide-body::after { transform: translateX(5px); }

@media (prefers-reduced-motion: reduce) {
	.acp-services-hub .acp-guide-body::after { transition: none; }
	.acp-services-hub .acp-guide:hover .acp-guide-body::after,
	.acp-services-hub .acp-guide:focus-visible .acp-guide-body::after { transform: none; }
}

/* ------------------------------------------ Window Furnishings: four cards

   Four collections, so a four-up grid rather than the shared three-up. These
   cards DO carry photographs, unlike the Services cards, because there is real
   per-collection imagery for three of the four. */
.acp-window .acp-coll-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 22px; }
.acp-window .acp-guide-body { padding: 22px 22px 24px; }
.acp.acp-window .acp-guide-body p { margin: 0; font-size: 14px; }

/* The lead line is the punchier half of the published copy, so it reads as a
   sub-heading rather than as body text. */
.acp.acp-window .acp-coll-lead {
	margin: 0 0 8px;
	font-weight: 700;
	color: var(--acp-ink);
}

/* The awnings card has NO photograph: every real awning image is claimed by page
   13771 and the only unclaimed one is a promo banner with "Exclusive Offers"
   baked in. The grey placeholder keeps the gap visible, which is what the design
   standard prescribes, and it has to match the card image height exactly or the
   fourth card sits shorter than the other three. */
.acp-window .acp-guide .acp-ph,
.acp-window .acp-guide .acp-media { height: 190px; border-radius: 10px; }

/* The sheer-curtain hero is a large PNG with a lot of window in it, so it is
   anchored to keep the curtain in frame rather than centre-cropping to glass. */
.acp.acp-window .acp-hero-media img { object-position: center 40%; }

/* The why split's image is a 2000x850 banner, far wider than the split column,
   so it is given a definite height and cropped. min-height MUST be overridden
   too: the shared `.acp-split-media img.acp-img { min-height: 520px }` beats any
   max-height, because in CSS min-height always wins. */
.acp.acp-window .acp-split-media .acp-media,
.acp.acp-window .acp-split-media .acp-img img,
.acp.acp-window .acp-split-media img.acp-img {
	min-height: 430px;
	height: 430px;
	max-height: 430px;
	object-fit: cover;
}

/* The flipped split leads with its image, so the wider column moves with it or
   the image column comes out narrower than the design intends. (0,2,0) against
   the shared rule's (0,1,0). */
.acp-window .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }

/* The four reasons, from the published icon boxes. */
.acp.acp-window .acp-window-reasons { margin: 26px 0 0; }
.acp.acp-window .acp-window-reasons li { padding-bottom: 12px; }
.acp.acp-window .acp-window-reasons strong { color: var(--acp-green); }

/* --------------------------------------------- splits with several paragraphs

   `.acp .acp-lede` sets margin: 0 at (0,2,0) and `.acp p` only sets a BOTTOM
   margin, so a lede followed by prose sits hard against both the h2 above it and
   the paragraph below. Same fix as the cleaning, About Us and About-children
   pages. */
.acp.acp-window .acp-split-copy .acp-lede { margin: 22px 0 18px; }
.acp.acp-window .acp-split-copy p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------- prose links

   The .acp design layer has NO `.acp p a` rule, so a link inside a paragraph
   renders browser-default blue, and on a green card that is close to unreadable.
   Scoped to these two pages, as .acp-inhome and the About pages already do. A
   generic rule in the shared layer would fix all twenty-four at once and is
   Bron's call. */
.acp.acp-services-hub .acp-faq-a a,
.acp.acp-services-hub .acp-feature-body a,
.acp.acp-window .acp-faq-a a,
.acp.acp-window .acp-split-copy a {
	color: var(--acp-green);
	text-decoration: none;
	border-bottom: 1px solid currentColor;
}
.acp.acp-services-hub .acp-faq-a a:hover,
.acp.acp-services-hub .acp-faq-a a:focus-visible,
.acp.acp-services-hub .acp-feature-body a:hover,
.acp.acp-services-hub .acp-feature-body a:focus-visible,
.acp.acp-window .acp-faq-a a:hover,
.acp.acp-window .acp-faq-a a:focus-visible,
.acp.acp-window .acp-split-copy a:hover,
.acp.acp-window .acp-split-copy a:focus-visible { color: var(--acp-green-dark); }

.acp.acp-services-hub .acp-final-card a:not(.acp-btn),
.acp.acp-window .acp-final-card a:not(.acp-btn) {
	color: #fff;
	text-decoration: none;
	border-bottom: 1px solid currentColor;
}
.acp.acp-services-hub .acp-final-card a:not(.acp-btn):hover,
.acp.acp-services-hub .acp-final-card a:not(.acp-btn):focus-visible,
.acp.acp-window .acp-final-card a:not(.acp-btn):hover,
.acp.acp-window .acp-final-card a:not(.acp-btn):focus-visible { color: var(--acp-cream); }

/* ------------------------------------------------------- Elementor compat

   The three fixes every converted .acp page needs, still restated per page
   rather than living in the shared compatibility layer. Promoting them is Bron's
   call. */

/* 1. Post-conversion .acp-hero-meta is an Elementor container and Elementor's
      two-class rules default it to a CENTRED COLUMN, so the arrow link and the
      count stack and centre instead of sitting on one left-aligned row. */
.acp.acp-services-hub .acp-hero-meta.e-flex,
.acp.acp-window .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
.acp.acp-services-hub .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-window .acp-hero-meta > .acp-arrow.e-con { width: auto; flex: 0 0 auto; }

/* 2. `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget WRAPPER,
      but the mirror `.acp .acp-h2 .elementor-heading-title` paints the real
      element green and a direct rule beats an inherited one, so the heading
      renders green on green and is invisible. Restated at (0,5,0). */
.acp.acp-services-hub .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-window .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-services-hub .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-window .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }

/* 3. The converted page ROOT is a top-level Elementor container and picks up
      Elementor's default 10px padding, which stops every full-bleed band 10px
      short of both viewport edges. Zeroed through the VARIABLES Elementor
      consumes, never as a `padding` declaration: every real design padding here
      is a direct `padding` property and `padding: 0` would destroy them all.
      Scoped to the root element only. */
.acp.acp-services-hub.e-con,
.acp.acp-window.e-con {
	--padding-top: 0px;
	--padding-right: 0px;
	--padding-bottom: 0px;
	--padding-left: 0px;
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-inline-start: 0px;
	--padding-inline-end: 0px;
}

.acp.acp-services-hub .acp-guide-grid.e-con,
.acp.acp-window .acp-guide-grid.e-con {
	--gap: 0px; --row-gap: 0px; --column-gap: 0px;
}
.acp.acp-services-hub .acp-guide-grid > .acp-guide.e-con,
.acp.acp-window .acp-guide-grid > .acp-guide.e-con { width: auto; }

/* ----------------------------------------------------------------- responsive

   Breakpoints restated rather than inherited, because a (0,2,0) page selector
   outranks the shared (0,1,0) rules even inside their own media queries. No new
   breakpoint: 1200 / 960 / 640 only. */

@media (max-width: 1200px) {
	.acp-window .acp-coll-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.acp-window .acp-split-flip { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); }
	.acp-services-hub .acp-guide-body { padding: 26px 26px 28px; }
}

@media (max-width: 960px) {
	.acp-services-hub .acp-guides,
	.acp-services-hub .acp-trust,
	.acp-window .acp-guides { padding: 60px 0 70px; }
	.acp-window .acp-split-flip { grid-template-columns: 1fr; }
	.acp.acp-window .acp-split-media .acp-media,
	.acp.acp-window .acp-split-media .acp-img img,
	.acp.acp-window .acp-split-media img.acp-img { min-height: 280px; height: 280px; max-height: 280px; }
}

@media (max-width: 640px) {
	.acp-window .acp-coll-grid { grid-template-columns: 1fr; }
	.acp-services-hub .acp-guide-body { padding: 24px 22px 26px; }
	.acp-window .acp-guide-body { padding: 20px 20px 22px; }
}
/* ===== ACP-HUBS BLOCK: END ===== */

/* ===== ACP-SHOP-RANGE BLOCK: START ===== */
/* Shop Range, page 149, /shop-range/. Root class .acp-shop-range.
 *
 * NAMING: the obvious root class .acp-range WAS ALREADY TAKEN. It is a section
 * class on the eight flooring category pages (offwhite background, 84px top
 * padding, scroll-margin-top) for the range strip. Using it as a page root would
 * have injected that band's padding and background into the page root and broken
 * every full-bleed section. Third time this has bitten: see .acp-green-page and
 * .acp-services-hub. Check before claiming a root class. */

/* The page root. Elementor gives a container without explicit spacing its default
 * 10px padding, so every full-bleed band stopped 10px short of both viewport
 * edges. Zeroed through the VARIABLES on the root only, never a `padding`
 * declaration, which would flatten the real design padding on inner containers. */
.acp.acp-shop-range.e-con {
	--padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
	--padding-block-start: 0px; --padding-block-end: 0px;
	--padding-inline-start: 0px; --padding-inline-end: 0px;
}

/* Sections. Alternating cream and offwhite so the two halves of the range read as
 * two lists rather than one run of thirteen cards. */
.acp-shop-range .acp-shop-floor { background: var(--acp-cream); padding: 96px 0 100px; scroll-margin-top: 90px; }
.acp-shop-range .acp-shop-window { background: var(--acp-offwhite); padding: 96px 0 100px; }

/* TEXT-ONLY GUIDE CARDS.
 * .acp-guide was built image-first: the picture supplies the top of the card and
 * .acp-guide-body only has to pad the copy below it. With no image the copy sat
 * hard against the top edge, so the body carries the full padding here. */
.acp-shop-range .acp-guide-body { padding: 26px 22px 24px; }
.acp-shop-range .acp-guide {
	border: 1px solid var(--acp-line);
	transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.acp-shop-range .acp-guide:hover,
.acp-shop-range .acp-guide:focus-visible {
	box-shadow: 0 10px 26px rgba(0, 0, 0, 0.09);
	border-color: var(--acp-green);
	transform: translateY(-2px);
}
/* Card titles are links inside an anchor, so they must not read as unstyled. */
.acp.acp-shop-range .acp-guide .acp-h4 { margin: 0 0 8px; color: var(--acp-green); }
/* Scoped with :not() rather than a bare `p`. At (0,3,1) this rule outranks the
 * shared `.acp .acp-meta-label` (0,2,0) and the count rule, so a bare selector
 * silently reset the gold uppercase label and the big figure to body size. */
.acp.acp-shop-range .acp-guide p:not(.acp-meta-label):not(.acp-shop-n) { font-size: 15px; line-height: 1.55; }

/* The live count. Set in the display face via --acp-serif (which resolves to the
 * brand token --and-display, currently Instrument Serif, NOT the Cormorant
 * Garamond named in CLAUDE.md: Brand Guidelines V4 changed it and the doc is
 * stale). Weight 600 matches .acp-h1/.acp-h2/.acp-h3, which all do the same.
 *
 * Sits above the material name so the eye can run down the column of figures and
 * compare category sizes at a glance. */
/* Three classes deliberately: `.acp.acp-shop-range .acp-guide p` above is (0,3,1) and
 * would beat a two-class rule here, rendering the count at body size. The same
 * trap as .acp-final-alt further down. */
.acp.acp-shop-range .acp-guide .acp-shop-n {
	margin: 0;
	/* !important is load bearing. style.css:1620, the Brand Guidelines V4 face
	   rollout, sets `.elementor-widget-text-editor p { font-family: var(--and-text)
	   !important }`. Post-conversion this figure IS a <p> inside a text-editor
	   widget, so on a converted page NO paragraph can carry display type without
	   !important: an inline literal font-family loses to it too. The .acp layer
	   already fights this same block twice (the .acp-formhost label rules), so
	   this is the established pattern rather than a new hack. Verified on staging:
	   without it the numeral rendered in Inter. */
	font-family: var(--acp-serif) !important;
	font-weight: 600;
	font-size: 46px;
	line-height: 1;
	color: var(--acp-green);
	letter-spacing: -0.01em;
}
.acp.acp-shop-range .acp-guide .acp-meta-label { margin: 4px 0 14px; }

/* Nine floor coverings in three columns is an exact 3x3. */
.acp-shop-range .acp-shop-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Four window furnishings, so four columns rather than 3 + 1 orphan. These cards
 * carry no count and one short line, so they take the narrower column happily. */
.acp-shop-range .acp-shop-window .acp-guide-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* The image in the "not sure where to start" band. Capped, and min-height reset
 * as well: min-height BEATS max-height, so setting max alone leaves the shared
 * 520px in force. */
.acp-shop-range .acp-shop-media .acp-media,
.acp-shop-range .acp-shop-media .acp-ph,
.acp-shop-range .acp-shop-media img {
	min-height: 0;
	max-height: 360px;
	height: 360px;
	width: 100%;
	border-radius: 18px;
	object-fit: cover;
	display: block;
}

/* The green card's heading. `.acp h2.acp-h2 { margin: 0 }` is deliberate globally,
 * because an h2 normally lives inside .acp-head which supplies the gap. In a green
 * card there is no .acp-head, so the heading collided with the paragraph. */
.acp-shop-range .acp-green-card h2.acp-h2 { margin: 0 0 20px; }
.acp-shop-range .acp-final-card h2.acp-h2 { margin: 0 0 18px; }

/* The line under the final CTA offering the picture-led alternative.
 *
 * .acp-final-card is in the selector FOR WEIGHT, not for scoping. The shared
 * `.acp .acp-final-card p { color: #fff }` is (0,2,1) and beats a two-class
 * `.acp.acp-shop-range .acp-final-alt` at (0,2,0), so the quieter colour would
 * silently lose. Three classes clears it. Same pattern as the carpet-cleaning
 * and Our Products pages, which hit this first. */
.acp.acp-shop-range .acp-final-card .acp-final-alt {
	margin: 26px auto 0;
	font-size: 14px;
	color: rgba(255, 255, 255, 0.82);
}
.acp.acp-shop-range .acp-final-card .acp-final-alt a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.acp.acp-shop-range .acp-final-card .acp-final-alt a:hover,
.acp.acp-shop-range .acp-final-card .acp-final-alt a:focus-visible { color: var(--acp-mint); }

/* Prose links. The design layer still has no shared `.acp p a` style, so every
 * page that puts a link in a paragraph restates it. Twenty-five pages deep now:
 * promoting this to the shared layer would fix them all at once and is Bron's
 * call, not something to slip in under a page build. */
.acp-shop-range .acp-lede a,
.acp-shop-range .acp-faq-a a {
	color: var(--acp-green);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}
.acp-shop-range .acp-lede a:hover,
.acp-shop-range .acp-faq-a a:hover { color: var(--acp-gold); }

/* ---- Responsive ---- */
@media (max-width: 1100px) {
	.acp-shop-range .acp-shop-floor,
	.acp-shop-range .acp-shop-window { padding: 68px 0 72px; }
	.acp-shop-range .acp-shop-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.acp-shop-range .acp-shop-window .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.acp.acp-shop-range .acp-guide .acp-shop-n { font-size: 40px; }
}
@media (max-width: 700px) {
	.acp-shop-range .acp-shop-floor,
	.acp-shop-range .acp-shop-window { padding: 52px 0 56px; }
	.acp-shop-range .acp-shop-grid,
	.acp-shop-range .acp-shop-window .acp-guide-grid { grid-template-columns: 1fr; }
	.acp-shop-range .acp-guide-body { padding: 22px 18px 20px; }
	.acp.acp-shop-range .acp-guide .acp-shop-n { font-size: 38px; }
	.acp-shop-range .acp-shop-media .acp-media,
	.acp-shop-range .acp-shop-media .acp-ph,
	.acp-shop-range .acp-shop-media img { height: 240px; max-height: 240px; }
}

/* ---- Post-conversion (Elementor) fixes ----
 * These three are now restated on roughly a dozen pages each. They belong in the
 * compatibility layer; kept page-scoped so this build cannot restyle live pages. */

/* 1. The tertiary hero row. Post-conversion .acp-hero-meta is an Elementor
 *    container and Elementor's own two-class rules default it to a centred
 *    column, so the arrow link and the count stacked and centred. */
.acp.acp-shop-range .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
/* 1b. ON THIS PAGE THE ROW FIX ABOVE IS NOT ENOUGH. The converter groups
 *     consecutive sibling paragraphs into ONE text-editor widget, so the arrow
 *     link and the count did not become two flex children of .acp-hero-meta at
 *     all: they ended up as two <p> inside a single .elementor-widget-container,
 *     which is display:block, and stacked. Measured on staging: arrow y=831,
 *     count y=872. Making that inner container the flex row puts them back on
 *     one line (verified: x=60 and x=209, same line).
 *
 *     The .e-flex rule above is kept as well, because it is what applies if a
 *     future convert DOES split them into separate widgets. */
.acp.acp-shop-range .acp-hero-meta .elementor-widget-container {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 18px;
}

/* 2. The arrow link becomes a container too and picks up .e-con's width:100%,
 *    so its bottom border ran the full column width like a rule. */
.acp.acp-shop-range .acp-hero-meta > .acp-arrow.e-con { width: auto; flex: 0 0 auto; }
/* 3. Green-on-green headings. The white rule lands on the widget WRAPPER, but the
 *    compatibility layer's `.acp .acp-h2 .elementor-heading-title` sets the green
 *    on the real element inside, and a direct rule beats an inherited one, so the
 *    heading went invisible. Restated for the real element. */
.acp.acp-shop-range .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-shop-range .acp-green-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-shop-range .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-shop-range .acp-green-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }
/* ===== ACP-SHOP-RANGE BLOCK: END ===== */

/* ===== ACP-CONTACT BLOCK: START ===== */
/* Contact Us, page 137, /contact-us/. Root class .acp-contact.
 *
 * Checked against the LIVE stylesheet before claiming: .acp-contact, .acp-reach,
 * .acp-reach-card, .acp-reach-grid and .acp-reach-alt were all free.
 * .acp-formhost and .acp-formband already exist and are REUSED, not redefined. */

/* THE PAGE HAS TWO .acp ROOTS, because a live Gravity Form sits between the two
 * shortcodes. Both need the root padding zeroed, or the bands either side of the
 * form sit 10px in from the viewport edges while the form does not.
 * Zeroed through the VARIABLES only, never a `padding` declaration, which would
 * flatten the real design padding on every inner container. */
.acp.acp-contact.e-con {
	--padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
	--padding-block-start: 0px; --padding-block-end: 0px;
	--padding-inline-start: 0px; --padding-inline-end: 0px;
}

/* The band that introduces the form. Same cream as .acp-formhost so the join
 * between the shortcode's .acp block and the Elementor container holding the form
 * is invisible and the two read as one band. Bottom padding is light because
 * .acp-formhost supplies `padding: 0 30px 100px !important` of its own.
 * Mirrors the existing .acp-fmq .acp-formband rule on the free-measure page. */
.acp-contact .acp-formband { background: var(--acp-cream); padding: 84px 0 34px; }
.acp-contact .acp-formband .acp-head { margin-bottom: 0; }

/* THE HERO IMAGE NEEDS AN EXPLICIT HEIGHT.
 *
 * The shared rule is `.acp-hero-media img { height: 100%; min-height: 560px;
 * object-fit: cover }` with NO max-height, and `min-height` BEATS `max-height`,
 * so a max alone leaves the 560px floor in force.
 *
 * This bit hard when the hero was briefly a PORTRAIT frame (1333x2000):
 * `height: 100%` of an auto-height grid item resolved to the natural aspect, so
 * the image rendered 786x1159 beside 596px of copy, and the crop cut the top 13%
 * of the photograph off, which is exactly where the subjects' heads were.
 * The hero is now a LANDSCAPE frame (2000x1333) and the crop is horizontal and
 * gentle, so the focal point can stay centred. The explicit height stays, because
 * without it any future image swap can blow the band out again.
 *
 * THREE SELECTORS, not one: `.acp img.acp-img` is (0,2,1) and outranks
 * `.acp-hero-media img`, and there is a third rule at `.acp-hero-media .acp-img
 * img`. Our Products (109) hit this first and its fix lists the same three. */
.acp.acp-contact .acp-hero-media .acp-media,
.acp.acp-contact .acp-hero-media img.acp-img,
.acp.acp-contact .acp-hero-media .acp-img img {
	min-height: 0;
	height: 600px;
	max-height: 600px;
	width: 100%;
	object-fit: cover;
	object-position: center center;
}

/* Other ways to reach us -------------------------------------------------- */

.acp-contact .acp-reach { background: var(--acp-offwhite); padding: 96px 0 40px; }
.acp-contact .acp-reach-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* These cards are NOT whole-card links, unlike every other .acp-guide: the phone
 * card wraps a tel: link and the head office card is not a link at all. So the
 * hover affordance goes on the card without implying the whole thing is clickable,
 * and the real links inside carry their own underline. */
.acp-contact .acp-reach-card {
	border: 1px solid var(--acp-line);
	cursor: default;
}
.acp-contact .acp-guide-body { padding: 26px 22px 24px; }
/* :not() rather than a bare `p`. At (0,3,1) a bare selector outranks the shared
 * `.acp .acp-meta-label` (0,2,0) and silently resets the gold uppercase label to
 * body size. Learned the hard way on Shop Range. */
.acp.acp-contact .acp-guide p:not(.acp-meta-label) { font-size: 15px; line-height: 1.55; }
.acp.acp-contact .acp-reach-card .acp-h4 { margin: 0 0 10px; color: var(--acp-green); }
.acp.acp-contact .acp-reach-card .acp-h4 a {
	color: var(--acp-green);
	text-decoration: none;
	border-bottom: 2px solid var(--acp-gold);
	padding-bottom: 2px;
}
.acp.acp-contact .acp-reach-card .acp-h4 a:hover,
.acp.acp-contact .acp-reach-card .acp-h4 a:focus-visible {
	color: var(--acp-gold);
	border-bottom-color: var(--acp-green);
}

/* The two enquiries that are not "I want flooring". Quiet, because most people do
 * not want them, but present so they do not land in a store's inbox. */
.acp-contact .acp-reach-alt {
	margin: 34px 0 0;
	padding: 20px 22px;
	background: var(--acp-panel);
	border-radius: 12px;
}
.acp.acp-contact .acp-reach-alt p { margin: 0; font-size: 15px; color: var(--acp-muted); }

/* Green cards. `.acp h2.acp-h2 { margin: 0 }` is deliberate globally because an h2
 * normally lives inside .acp-head, which supplies the gap. There is no .acp-head
 * in a final card, so the heading collided with the paragraph below it. */
.acp-contact .acp-final-card h2.acp-h2 { margin: 0 0 18px; }

/* The tertiary line under the final band's pills.
 * .acp-final-card is in the selector FOR WEIGHT, not scoping: the shared
 * `.acp .acp-final-card p { color: #fff }` is (0,2,1) and beats a two-class
 * `.acp.acp-contact .acp-final-alt` at (0,2,0), so the quieter colour would
 * silently lose. Three classes clears it. */
.acp.acp-contact .acp-final-card .acp-final-alt {
	margin: 26px auto 0;
	font-size: 14px;
	color: rgba(255, 255, 255, 0.82);
}
.acp.acp-contact .acp-final-card .acp-final-alt a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.acp.acp-contact .acp-final-card .acp-final-alt a:hover,
.acp.acp-contact .acp-final-card .acp-final-alt a:focus-visible { color: var(--acp-mint); }

/* Prose links. The design layer still has no shared `.acp p a`, so every page
 * restates it. Twenty-six pages deep now: promoting this to the shared layer
 * would fix them all at once and is Bron's call, not something to slip in under a
 * page build. */
.acp-contact .acp-lede a,
.acp-contact .acp-faq-a a,
.acp-contact .acp-reach-alt a {
	color: var(--acp-green);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}
.acp-contact .acp-lede a:hover,
.acp-contact .acp-faq-a a:hover,
.acp-contact .acp-reach-alt a:hover { color: var(--acp-gold); }

/* ---- The placeholder enquiry form (SHARED, not contact-only) -------------------------------------
 * A styled preview of the enquiry form, requested so the page can be reviewed
 * while the real Gravity Form is invisible on staging. Scoped to `.acp` rather
 * than `.acp-contact`, because the free measure and quote page uses the same
 * shared component. It contains no <form>,
 * <input> or <button>: the fields are divs, so nothing can be focused, filled or
 * submitted, and the whole block is aria-hidden.
 *
 * Everything below comes from the tokens: white raised card on the cream band,
 * the single approved shadow, 15px card radius, 10px inset fields, a 999px pill
 * at the 52px minimum, gold `.acp-meta-label` labels. */
.acp .acp-formph {
	max-width: 980px;
	margin: 40px auto 0;
	background: #fff;
	border: 1px solid var(--acp-line);
	border-radius: 15px;
	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.05);
	padding: 34px 34px 30px;
}
.acp .acp-formph-flag {
	margin: 0 0 22px;
	/* Eyebrow furniture: Figma 29:880. */
	font-size: 10px;
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--acp-gold);
}
.acp .acp-formph-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 20px 24px;
}
.acp .acp-formph-row-wide { grid-column: 1 / -1; }
.acp .acp-formph-row .acp-meta-label { margin: 0 0 8px; }

/* The field boxes. 10px, matching the footer's field (Figma 29:957). */
.acp .acp-formph-field {
	height: 52px;
	border: 1px solid var(--acp-line);
	border-radius: 10px;
	background: var(--acp-offwhite);
}
.acp .acp-formph-field-area { height: 132px; }
/* The select carries the same chevron the rest of the layer uses. */
.acp .acp-formph-field-select {
	position: relative;
	background-image: linear-gradient(45deg, transparent 50%, var(--acp-muted) 50%),
		linear-gradient(135deg, var(--acp-muted) 50%, transparent 50%);
	background-position: calc(100% - 22px) 24px, calc(100% - 16px) 24px;
	background-size: 6px 6px, 6px 6px;
	background-repeat: no-repeat;
}

.acp .acp-formph-foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 18px;
	margin: 26px 0 0;
}
/* Looks like the primary pill, but it is a span and does nothing. */
.acp .acp-formph-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* Matches the real CTA (Figma 29:881): 37px, 20px padding, Inter 600 14. */
	min-height: 37px;
	padding: 0 20px;
	border-radius: 999px;
	background: var(--acp-green);
	color: #fff;
	font-size: 14px;
	font-weight: 600;
}
.acp .acp-formph-note { margin: 0; font-size: 13px; color: var(--acp-muted); }

/* The required asterisk. Its own element so the label keeps the gold and the
 * marker reads as a marker, matching the supplied design. Deep red rather than
 * the palette's error red because this is not an error state, just a flag. */
.acp .acp-formph-req { color: #8c2f26; font-weight: 700; }

@media (max-width: 700px) {
	.acp .acp-formph { padding: 24px 20px 22px; margin-top: 28px; }
	.acp .acp-formph-grid { grid-template-columns: 1fr; }
	.acp .acp-formph-btn { width: 100%; }
}

/* ---- Responsive ---- */
@media (max-width: 1100px) {
	.acp-contact .acp-reach { padding: 68px 0 30px; }
	.acp-contact .acp-formband { padding: 60px 0 28px; }
	.acp-contact .acp-reach-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.acp.acp-contact .acp-hero-media .acp-media,
	.acp.acp-contact .acp-hero-media img.acp-img,
	.acp.acp-contact .acp-hero-media .acp-img img { height: 460px; max-height: 460px; }
}
@media (max-width: 700px) {
	.acp-contact .acp-reach { padding: 52px 0 24px; }
	.acp-contact .acp-formband { padding: 46px 0 24px; }
	.acp-contact .acp-reach-grid { grid-template-columns: 1fr; }
	.acp-contact .acp-guide-body { padding: 22px 18px 20px; }
	/* Same three selectors as the base cap, matching the shared mobile floor of
	   260px. At 340px the box was nearly square at this width and threw away 237px
	   of a 3:2 frame sideways; 260px cuts that to ~115px and still fills the band. */
	.acp.acp-contact .acp-hero-media .acp-media,
	.acp.acp-contact .acp-hero-media img.acp-img,
	.acp.acp-contact .acp-hero-media .acp-img img { height: 260px; max-height: 260px; }
}

/* ---- Post-conversion (Elementor) fixes ----
 * Restated per page rather than promoted, so this build cannot restyle the other
 * twenty-five converted pages. They belong in the compatibility layer. */

/* 1. The tertiary hero row. Post-conversion .acp-hero-meta is an Elementor
 *    container and Elementor's own two-class rules default it to a centred
 *    column, so the arrow link and the store count stacked and centred. */
.acp.acp-contact .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
/* 1b. AND the rule above is not enough on its own. The converter groups
 *     consecutive sibling paragraphs into ONE text-editor widget, so the arrow
 *     link and the count never become two flex children of .acp-hero-meta at
 *     all: they end up as two <p> inside a single .elementor-widget-container,
 *     which is display:block, and stack. Making that inner container the flex row
 *     is what actually puts them on one line. Found on Shop Range. */
.acp.acp-contact .acp-hero-meta .elementor-widget-container {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 18px;
}
/* 2. The arrow link becomes a container too and picks up .e-con's width:100%,
 *    so its bottom border ran the full column width like a rule. */
.acp.acp-contact .acp-hero-meta > .acp-arrow.e-con { width: auto; flex: 0 0 auto; }
/* 3. Green-on-green headings. The white rule lands on the widget WRAPPER, but the
 *    compatibility layer's `.acp .acp-h2 .elementor-heading-title` sets the green
 *    on the real element inside, and a direct rule beats an inherited one, so the
 *    heading went invisible. Restated for the real element. */
.acp.acp-contact .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-contact .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }
/* ===== ACP-CONTACT BLOCK: END ===== */

/* ===== ACP-IDEA-CENTRE BLOCK: START ===== */
/* The Idea Centre cluster: 133 hub, 141 blog, 143 advice, 145 inspiration,
 * 147 video library.
 *
 * Root classes .acp-ideas / .acp-icblog / .acp-icadvice / .acp-icinspo /
 * .acp-icvideos, all checked against the LIVE stylesheet before claiming, along
 * with every section and host class below. .acp-formhost, .acp-guide,
 * .acp-final-card, .acp-green-card, .acp-tip and .acp-meta-label are reused. */

/* Page roots. Elementor gives a container without explicit spacing its default
 * 10px padding, so every full-bleed band stops 10px short of both viewport edges.
 * Zeroed through the VARIABLES only, never a `padding` declaration, which would
 * flatten real design padding on inner containers.
 *
 * Each of these pages has TWO OR THREE .acp roots, because live widgets sit
 * between the shortcodes, so every root needs this or the bands either side of a
 * listing sit at different left edges. */
.acp.acp-ideas.e-con,
.acp.acp-icblog.e-con,
.acp.acp-icadvice.e-con,
.acp.acp-icinspo.e-con,
.acp.acp-icvideos.e-con {
	--padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
	--padding-block-start: 0px; --padding-block-end: 0px;
	--padding-inline-start: 0px; --padding-inline-end: 0px;
}

/* ---- Text-only hero -----------------------------------------------------
 * Four of the five pages are index pages and take a hero with no photograph, so
 * the copy column runs wider than the 480px the two-column hero grid gives it. */
.acp-hero-text { padding-bottom: 34px; }
.acp-hero-text .acp-hero-copy-wide { max-width: 780px; }
.acp-hero-text .acp-hero-copy-wide .acp-hero-lede { max-width: 62ch; }

/* ---- The heading band that introduces a listing ------------------------- */
.acp-loophead { background: var(--acp-offwhite); padding: 84px 0 26px; scroll-margin-top: 90px; }
.acp-loophead .acp-head { margin-bottom: 0; }

/* ---- WIDGET HOSTS -------------------------------------------------------
 * .acp-loophost, .acp-carouselhost and .acp-playlisthost are Elementor
 * containers holding third-party listing widgets, so they sit OUTSIDE the .acp
 * tree and cannot inherit its custom properties. Only the tokens the listings
 * need are repeated, exactly as .acp-formhost does for a Gravity Form.
 *
 * !important on padding because .e-con sets its padding from --padding-*
 * custom properties, which beat a plain class. */
.acp-loophost,
.acp-carouselhost,
.acp-playlisthost {
	--acp-cream: #f6f5ef;
	--acp-offwhite: #fbfaf6;
	--acp-panel: #f1f0ea;
	--acp-green: #00833f;
	--acp-green-dark: #0f5230;
	--acp-mint: #2bde81;
	--acp-gold: #ffa400;
	--acp-ink: #000000;
	--acp-muted: #5c5c56;
	--acp-line: #e6e2d6;

	background: var(--acp-offwhite);
	padding: 0 30px 90px !important;
}
.acp-carouselhost { background: var(--acp-cream); padding: 20px 30px 90px !important; }
.acp-playlisthost { scroll-margin-top: 90px; }

/* DO NOT RECOLOUR THE POST CARDS.
 *
 * A first pass here set `.uael-post__title { color: var(--acp-green) }` to bring
 * the listing onto the palette. That was wrong and would have been a regression.
 * The widget uses its "featured" structure: `.uael-post__content-wrap` carries the
 * post's featured image as a BACKGROUND, and the title and excerpt are white text
 * overlaid on that photograph. Measured on staging: title colour #fff, the
 * ancestor that paints is `.uael-post__content-wrap` with a background image.
 * Green text on a photograph would have been less legible, not more.
 *
 * So the card internals are left alone entirely. Only the range headings around
 * the carousels and playlist are brought onto the display face, because those are
 * ordinary headings on a flat background. */
/* The range headings above the carousels, and the playlist's own heading.
 *
 * !important on colour is load bearing. Elementor writes a per-element rule for
 * each widget's own colour setting, at three classes
 * (`.elementor-145 .elementor-element-xxx .elementor-heading-title`), which beats
 * a two-class rule here. Measured on staging: the headings stayed #00833F, the
 * OLD green, while the font-family DID apply because the widgets set no family.
 * So the family needs no !important and the colour does. */
.acp-carouselhost .elementor-heading-title,
.acp-playlisthost .elementor-heading-title {
	font-family: var(--acp-serif);
	color: var(--acp-green) !important;
}

/* The playlist widget sets its video titles in Poppins
 * (`title_typography_font_family`), which is the pre-V4 brand face. `inherit`
 * rather than naming a face, so it follows whatever the brand tokens set for body
 * copy and cannot go stale if the brand changes again. Titles and durations only;
 * the widget's sizes and weights are left alone. */
.acp-playlisthost .e-tab-title,
.acp-playlisthost [class*='playlist'] [class*='title'],
.acp-playlisthost [class*='duration'] {
	font-family: inherit !important;
}

/* Accessibility, not styling: the category links under each card render at 17px
 * tall, which fails WCAG 2.2 target size, and they are not inline in a sentence
 * so the inline exemption does not apply. Padding only, no colour change. */
.acp-loophost .uael-listing__terms-link,
.acp-loophost .uael-post__terms a {
	display: inline-block;
	padding: 4px 0;
}

/* THE OLD ORANGE. The taxonomy-blocks widget sets its "View All" buttons to
 * #FFA400 (`term_post_loop_background_color`) with a #02833E hover; neither is a
 * brand colour. Overridden in CSS rather than by editing the widget.
 *
 * The class is `.ae-term-button`. A first pass guessed `.ae-post-block-btn` and
 * `.uael-post__read-more` and changed nothing: measured on staging, 22 buttons
 * were still rgb(255,164,0). Check the rendered class name, do not infer it. */
.acp-loophost .ae-term-button,
.acp-loophost a.ae-term-button {
	background-color: var(--acp-green) !important;
	color: #fff !important;
	border-radius: 999px;
}
.acp-loophost .ae-term-button:hover,
.acp-loophost a.ae-term-button:hover,
.acp-loophost .ae-term-button:focus-visible {
	background-color: var(--acp-green-dark) !important;
	color: #fff !important;
}
.acp-playlisthost .elementor-video-playlist .e-tabs-header,
.acp-playlisthost .e-tab-title.e-active { border-color: var(--acp-green); }

/* ---- Browse by topic (hub) ---------------------------------------------- */
.acp-topics { margin: 30px 0 0; }
.acp.acp-ideas .acp-topics .acp-meta-label { margin: 0 0 12px; }
.acp-topic-list {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}
.acp-topic-list li { margin: 0; }

/* THE PILL ROW, POST-CONVERSION. Two separate Elementor defaults break it and
 * BOTH have to be undone; fixing either one alone leaves it broken.
 *
 * 1. The <ul> becomes an Elementor container and Elementor sets
 *    `--flex-direction: column` on it, so the pills stacked vertically. Setting
 *    `display: flex` on the class does nothing, because .e-con reads its
 *    direction from that variable. Same trap as .acp-hero-meta.
 * 2. Each <li> and each <a> also become containers carrying `--width: 100%`, so
 *    even once the row was horizontal every pill stretched the full column.
 *
 * Measured on staging before the fix: each pill 1300x78 and the row 624px tall.
 * After: pills hug their labels (99px, 120px, 88px...) and the row is 98px. */
.acp.acp-ideas .acp-topic-list.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--justify-content: flex-start;
	--gap: 10px; --row-gap: 10px; --column-gap: 10px;
}
.acp.acp-ideas .acp-topic-list > .e-con,
.acp.acp-ideas .acp-topic-list > .e-con > a.e-con,
.acp.acp-ideas .acp-topic-list a.e-con {
	--width: auto;
	width: auto;
	flex: 0 0 auto;
}
/* Zero the wrapper container's default padding so the pill's own padding is what
   sets its size, through the variables only, never a `padding` declaration. */
.acp.acp-ideas .acp-topic-list > .e-con {
	--padding-top: 0px; --padding-right: 0px; --padding-bottom: 0px; --padding-left: 0px;
	--padding-block-start: 0px; --padding-block-end: 0px;
	--padding-inline-start: 0px; --padding-inline-end: 0px;
}
.acp.acp-ideas .acp-topic-list a {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	/* 44px tall, so these clear the 24px minimum target with room to spare. */
	min-height: 44px;
	padding: 10px 18px;
	background: #fff;
	border: 1px solid var(--acp-line);
	border-radius: 999px;
	color: var(--acp-green);
	font-size: 15px;
	font-weight: 600;
	text-decoration: none;
	transition: border-color 0.18s ease, background 0.18s ease;
}
.acp.acp-ideas .acp-topic-list a:hover,
.acp.acp-ideas .acp-topic-list a:focus-visible {
	border-color: var(--acp-green);
	background: var(--acp-panel);
}
.acp-topic-n {
	font-size: 12px;
	font-weight: 700;
	color: var(--acp-gold);
	letter-spacing: 0.06em;
}

/* ---- The mid-page video band on the hub --------------------------------- */
.acp-videocta { background: var(--acp-offwhite); padding: 20px 0 90px; }

/* ---- Cross-links between the five pages -------------------------------- */
.acp-icmore { padding-top: 90px; }
.acp-icmore-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.acp-ideas .acp-guide-body,
.acp-icblog .acp-guide-body,
.acp-icadvice .acp-guide-body,
.acp-icinspo .acp-guide-body,
.acp-icvideos .acp-guide-body { padding: 26px 22px 24px; }
.acp-icmore .acp-guide {
	border: 1px solid var(--acp-line);
	transition: box-shadow 0.18s ease, transform 0.18s ease, border-color 0.18s ease;
}
.acp-icmore .acp-guide:hover,
.acp-icmore .acp-guide:focus-visible {
	box-shadow: 0 10px 26px rgba(0, 0, 0, 0.09);
	border-color: var(--acp-green);
	transform: translateY(-2px);
}
.acp-icmore .acp-guide .acp-h4 { margin: 0 0 8px; color: var(--acp-green); }
/* :not() rather than a bare `p`: at (0,3,1) a bare selector outranks the shared
 * `.acp .acp-meta-label` (0,2,0) and silently resets the gold uppercase label. */
.acp.acp-ideas .acp-guide p:not(.acp-meta-label),
.acp.acp-icblog .acp-guide p:not(.acp-meta-label),
.acp.acp-icadvice .acp-guide p:not(.acp-meta-label),
.acp.acp-icinspo .acp-guide p:not(.acp-meta-label),
.acp.acp-icvideos .acp-guide p:not(.acp-meta-label) { font-size: 15px; line-height: 1.55; }

/* ---- Green cards ------------------------------------------------------- */
/* `.acp h2.acp-h2 { margin: 0 }` is deliberate globally, because an h2 normally
 * lives inside .acp-head which supplies the gap. There is no .acp-head in a card. */
.acp-ideas .acp-final-card h2.acp-h2,
.acp-icblog .acp-final-card h2.acp-h2,
.acp-icadvice .acp-final-card h2.acp-h2,
.acp-icinspo .acp-final-card h2.acp-h2,
.acp-icvideos .acp-final-card h2.acp-h2 { margin: 0 0 18px; }

/* The tertiary line under a final card's pills. .acp-final-card is in the
 * selector FOR WEIGHT: the shared `.acp .acp-final-card p { color: #fff }` is
 * (0,2,1) and beats a two-class rule, so the quieter colour would silently lose. */
.acp.acp-ideas .acp-final-card .acp-final-alt,
.acp.acp-icblog .acp-final-card .acp-final-alt,
.acp.acp-icadvice .acp-final-card .acp-final-alt,
.acp.acp-icinspo .acp-final-card .acp-final-alt,
.acp.acp-icvideos .acp-final-card .acp-final-alt {
	margin: 26px auto 0;
	font-size: 14px;
	color: rgba(255, 255, 255, 0.82);
}
.acp.acp-ideas .acp-final-card .acp-final-alt a,
.acp.acp-icblog .acp-final-card .acp-final-alt a,
.acp.acp-icadvice .acp-final-card .acp-final-alt a,
.acp.acp-icinspo .acp-final-card .acp-final-alt a,
.acp.acp-icvideos .acp-final-card .acp-final-alt a {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* ---- Prose links -------------------------------------------------------
 * The layer still has no shared `.acp p a`, so every page restates it. Thirty
 * pages deep now: promoting this into the shared layer would fix them all at
 * once and is Bron's call, not something to slip in under a page build. */
.acp-ideas .acp-lede a,      .acp-ideas .acp-faq-a a,      .acp-ideas .acp-tip a,
.acp-icblog .acp-lede a,     .acp-icblog .acp-faq-a a,     .acp-icblog .acp-tip a,
.acp-icadvice .acp-lede a,   .acp-icadvice .acp-faq-a a,   .acp-icadvice .acp-tip a,
.acp-icinspo .acp-lede a,    .acp-icinspo .acp-faq-a a,    .acp-icinspo .acp-tip a,
.acp-icvideos .acp-lede a,   .acp-icvideos .acp-faq-a a,   .acp-icvideos .acp-tip a {
	color: var(--acp-green);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}
/* A lede whose only content is a link ("See all articles.") is a standalone
 * target, so the WCAG 2.2 inline exemption does not cover it: measured at 20px
 * tall. :has() keeps the padding off links that really are mid-sentence, where
 * inline-block would stop them wrapping across lines. */
.acp-ideas .acp-lede:has(> a:only-child) a,
.acp-icblog .acp-lede:has(> a:only-child) a,
.acp-icadvice .acp-lede:has(> a:only-child) a,
.acp-icinspo .acp-lede:has(> a:only-child) a,
.acp-icvideos .acp-lede:has(> a:only-child) a {
	display: inline-block;
	padding: 4px 0;
}

.acp-ideas .acp-lede a:hover,    .acp-icblog .acp-lede a:hover,
.acp-icadvice .acp-lede a:hover, .acp-icinspo .acp-lede a:hover,
.acp-icvideos .acp-lede a:hover { color: var(--acp-gold); }

/* ---- The Inspiration hero image, capped ---------------------------------
 * min-height BEATS max-height on the shared `.acp-hero-media img`, so a max
 * alone leaves the 560px floor in force, and a portrait source would run to its
 * natural aspect and blow the band out. Three selectors because
 * `.acp img.acp-img` is (0,2,1) and outranks `.acp-hero-media img`. */
.acp.acp-icinspo .acp-hero-media .acp-media,
.acp.acp-icinspo .acp-hero-media img.acp-img,
.acp.acp-icinspo .acp-hero-media .acp-img img {
	min-height: 0;
	height: 600px;
	max-height: 600px;
	width: 100%;
	object-fit: cover;
	object-position: center center;
}

/* ---- Responsive ---- */
@media (max-width: 1100px) {
	.acp-loophead { padding: 60px 0 22px; }
	.acp-videocta { padding: 16px 0 64px; }
	.acp-icmore { padding-top: 64px; }
	.acp-icmore-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.acp-loophost,
	.acp-carouselhost,
	.acp-playlisthost { padding: 0 20px 64px !important; }
	.acp.acp-icinspo .acp-hero-media .acp-media,
	.acp.acp-icinspo .acp-hero-media img.acp-img,
	.acp.acp-icinspo .acp-hero-media .acp-img img { height: 460px; max-height: 460px; }
}
@media (max-width: 700px) {
	.acp-loophead { padding: 46px 0 18px; }
	.acp-videocta { padding: 12px 0 52px; }
	.acp-icmore { padding-top: 52px; }
	.acp-icmore-grid { grid-template-columns: 1fr; }
	.acp-loophost,
	.acp-carouselhost,
	.acp-playlisthost { padding: 0 16px 52px !important; }
	.acp.acp-icinspo .acp-hero-media .acp-media,
	.acp.acp-icinspo .acp-hero-media img.acp-img,
	.acp.acp-icinspo .acp-hero-media .acp-img img { height: 260px; max-height: 260px; }
}

/* ---- Post-conversion (Elementor) fixes ----
 * Restated per cluster rather than promoted, so this build cannot restyle the
 * other twenty-six converted pages. They belong in the compatibility layer. */

/* 1. .acp-hero-meta becomes an Elementor container and Elementor's own two-class
 *    rules default it to a centred column, so an arrow link and a count stack. */
.acp.acp-ideas .acp-hero-meta.e-flex,
.acp.acp-icblog .acp-hero-meta.e-flex,
.acp.acp-icadvice .acp-hero-meta.e-flex,
.acp.acp-icinspo .acp-hero-meta.e-flex,
.acp.acp-icvideos .acp-hero-meta.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 18px; --row-gap: 10px; --column-gap: 18px;
}
/* 1b. And that is not enough on its own: the converter groups consecutive sibling
 *     paragraphs into ONE text-editor widget, so the arrow and the count end up as
 *     two <p> inside a single display:block .elementor-widget-container and stack
 *     anyway. Making that inner container the flex row is what fixes it. */
.acp.acp-ideas .acp-hero-meta .elementor-widget-container,
.acp.acp-icblog .acp-hero-meta .elementor-widget-container,
.acp.acp-icadvice .acp-hero-meta .elementor-widget-container,
.acp.acp-icinspo .acp-hero-meta .elementor-widget-container,
.acp.acp-icvideos .acp-hero-meta .elementor-widget-container {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 18px;
}
/* 2. The arrow link becomes a container too and picks up .e-con's width:100%, so
 *    its bottom border ran the full column width like a rule. */
.acp.acp-ideas .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-icblog .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-icadvice .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-icinspo .acp-hero-meta > .acp-arrow.e-con,
.acp.acp-icvideos .acp-hero-meta > .acp-arrow.e-con { width: auto; flex: 0 0 auto; }
/* 3. Green-on-green headings. The white rule lands on the widget WRAPPER, but the
 *    compatibility layer's `.acp .acp-h2 .elementor-heading-title` sets green on
 *    the real element inside, and a direct rule beats an inherited one. */
.acp.acp-ideas .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-icblog .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-icadvice .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-icinspo .acp-final-card .acp-h2 .elementor-heading-title,
.acp.acp-icvideos .acp-final-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp.acp-ideas .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-icblog .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-icadvice .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-icinspo .acp-final-card .acp-h2 .elementor-heading-title em,
.acp.acp-icvideos .acp-final-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }
/* ===== ACP-IDEA-CENTRE BLOCK: END ===== */

/* ===== ACP-BAND-GAP BLOCK: START ===== */
/* THE 20px STRIPE BETWEEN EVERY BAND. Found 22 August 2026, reported by Bron.
 *
 * Post-conversion every `.acp` page root is an Elementor container, i.e.
 * `display: flex; flex-direction: column`, and Elementor gives a container a
 * DEFAULT `--gap: 20px 20px`. So a 20px row gap sat between every band on every
 * converted page, and the page root's own background showed through it. Wherever
 * a cream band met another cream band on an offwhite root, that read as a pale
 * stripe across the page. Measured on Contact Us: four gaps, crumbs->hero,
 * hero->formband, reach->faq, faq->final.
 *
 * This was invisible to the checks used while building those pages. Every band was
 * verified for x and width (full bleed) and never for the vertical join, so it
 * shipped on all of them.
 *
 * WHY `row-gap` AND NOT `--gap`
 * Custom properties INHERIT. Setting `--gap: 0` on the root would cascade into
 * every descendant container and collapse gaps that are meant to be there, e.g.
 * `.acp-actions` (14px between buttons) and `.acp-hero-meta` (10px/18px).
 * `row-gap` is not an inherited property, so setting it directly on the root
 * affects only the root's own children. Verified: with `row-gap: 0` the band gaps
 * go to zero while .acp-actions keeps 14px and .acp-hero-meta keeps 10px/18px.
 *
 * column-gap is deliberately left alone: a root is a single column, so it has no
 * effect there, and zeroing it would be one more thing to inherit-proof.
 *
 * Bands supply their own vertical rhythm through their own padding, so a root
 * gap is never wanted. */
.acp.e-con { row-gap: 0; }
/* ===== ACP-BAND-GAP BLOCK: END ===== */

/* ===== ACP-ARCHIVE-FIXES BLOCK: START ===== */
/* Three defects reported by Bron on the product category pages, 23 August 2026.
 * All three are PROMOTED TO THE SHARED LAYER rather than scoped to one page,
 * because Bron asked for every page in the hub and all three have one cause each
 * that is identical everywhere. */

/* 1. TILE LABELS DREW AT THE FOOT OF THE TILE, OVER THE NOTE.
 *
 * `.acp-tile-label` is `position: absolute; top: 0; right: 0` against
 * `.acp-tile`, which is `position: relative`. In shortcode markup that put the
 * notched label in the top corner. After conversion the label becomes a widget,
 * and Elementor gives every `.elementor-widget` `position: relative`, so THAT
 * wrapper becomes the containing block and the label resolved against its own
 * near-empty box at the bottom of the tile, on top of `.acp-tile-note`.
 * Measured on carpet before the fix: label 380px down a 441px tile.
 *
 * The wrapper stays in flow but collapses to nothing, because its only child is
 * out of flow, so the note does not move (verified: note stayed at y=385).
 *
 * This was previously fixed on page 107 only, scoped to `.acp-company`, to avoid
 * restyling pages that had already been reviewed. Bron has now asked for the hub,
 * so the prefix is dropped and every page gets it. */
.acp .acp-tile > .elementor-widget { position: static; }

/* 2. A STRAY 1px OUTLINE UNDER THE "WHERE IT WORKS BEST" PANELS.
 *
 * `.acp-tabs` is Elementor's native Tabs widget, and Elementor's own stylesheet
 * gives `.elementor-tab-content` a 1px border. It rendered as a dark rule down
 * the right and along the bottom of the panel in --acp-ink (#3a3a3a), which is
 * not a border the design asks for anywhere.
 *
 * Only the widget's structural borders are removed. The active-tab treatment is
 * colour, not border, so it survives untouched (verified: active tab still green
 * on white).
 *
 * !important is load bearing here. The border is not Elementor's stylesheet
 * default: it is a per-element rule written into **post-17571.css**, the archive
 * template's own CSS, from a border setting on tabs widget 8b4ba90. That selector
 * is `.elementor-17571 .elementor-element.elementor-element-8b4ba90
 * .elementor-tab-content`, which is (0,4,0) and beats a three-class rule here.
 * A first pass without !important changed nothing and the border stayed 0/1/1/1.
 *
 * Overriding in CSS rather than clearing the widget setting keeps this build out
 * of the shared archive template's data, which every category page renders
 * through. */
.acp .elementor-tabs .elementor-tab-content,
.acp .elementor-tabs .elementor-tab-title,
.acp .elementor-tabs .elementor-tab-title:before,
.acp .elementor-tabs .elementor-tab-title:after,
.acp .elementor-tabs .elementor-tabs-content-wrapper,
.acp .elementor-tabs .elementor-tabs-wrapper { border: 0 !important; }

/* 3. THE FINAL CTA HEADING WAS GREEN ON GREEN, SO ONLY THE MINT WORDS SHOWED.
 *
 * `.acp .acp-final-card .acp-h2 { color: #fff }` lands on the widget WRAPPER, but
 * the compatibility layer's mirror `.acp .acp-h2 .elementor-heading-title` sets
 * the green heading colour on the real element inside it, and a direct rule beats
 * an inherited one. Measured on the carpet archive: wrapper #fff, inner element
 * rgb(20,104,62) on a rgb(20,104,62) card, so "Ready to find the right carpet
 * for" was invisible and only the `<em>` "your home?" could be read.
 *
 * Restated for the real element at (0,4,0) against the mirror's (0,3,0). This is
 * the rule that has been copied onto roughly a dozen pages one at a time; putting
 * it in the shared layer covers the archives, which never got a copy, and makes
 * the per-page duplicates redundant. They are left in place because they are
 * identical and harmless. */
.acp .acp-final-card .acp-h2 .elementor-heading-title,
.acp .acp-green-card .acp-h2 .elementor-heading-title { color: #fff; }
.acp .acp-final-card .acp-h2 .elementor-heading-title em,
.acp .acp-green-card .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }
/* ===== ACP-ARCHIVE-FIXES BLOCK: END ===== */

/* ===== ACP-AUDIT-FIXES BLOCK: START ===== */
/* Found by a site-wide CSS audit, 23 August 2026, at Bron's request. Three real
 * defects. The gold and mint contrast findings from the same audit are NOT here:
 * those are the token palette as specified, so they are a brand decision, not a
 * bug to patch. */

/* 1. AN INVISIBLE HEADING: GREEN ON GREEN, AGAIN, THIS TIME AT h3.
 *
 * The green-card fix already in the layer covers `.acp-h2` only. A green card on
 * the product archives uses `.acp-h3` for the store-finder prompt, and that fell
 * through: measured on the carpet archive, "Search by suburb or postcode" was
 * rgb(20,104,62) on a rgb(20,104,62) card. Contrast ratio 1.00:1 — literally
 * invisible.
 *
 * Same cause as the h2 case: the white rule lands on the widget WRAPPER while the
 * compatibility layer's mirror sets the green on the real element inside, and a
 * direct rule beats an inherited one. Extended to h3 and h4 so the whole heading
 * scale is covered rather than leaving the next size to be found later. */
.acp .acp-final-card .acp-h3 .elementor-heading-title,
.acp .acp-final-card .acp-h4 .elementor-heading-title,
.acp .acp-green-card .acp-h3 .elementor-heading-title,
.acp .acp-green-card .acp-h4 .elementor-heading-title,
.acp .acp-on-green .acp-h3 .elementor-heading-title,
.acp .acp-on-green .acp-h4 .elementor-heading-title { color: #fff; }
/* And when the heading is not wrapped by a widget at all. */
.acp .acp-final-card h3.acp-h3,
.acp .acp-final-card h4.acp-h4,
.acp .acp-green-card h3.acp-h3,
.acp .acp-green-card h4.acp-h4,
.acp .acp-on-green h3.acp-h3,
.acp .acp-on-green h4.acp-h4 { color: #fff; }

/* 2. PROSE LINKS WERE RENDERING IN THE OLD BRAND GREEN.
 *
 * `style.css` still sets the site-wide link colour to #00833F, the pre-V4 green
 * that Brand Guidelines V4 replaced with #14683e. Any link inside `.acp` that is
 * not one of the named components inherited it: measured on the carpet archive,
 * the "hybrid" and "vinyl" links in body copy were rgb(0,131,63) at 4.26:1 on the
 * panel, which is both off-brand AND below the 4.5:1 minimum for body text.
 *
 * This is the missing shared prose-link style that has been restated by hand on
 * roughly thirty pages. Putting it here covers the pages that never got a copy,
 * including every product archive.
 *
 * Hover goes to green-dark, not gold. Gold on cream measures 2.22:1, so a
 * gold hover on a 15px link makes it markedly HARDER to read at the moment the
 * user is aiming at it. The per-page rules written earlier do use gold; they are
 * more specific so they still win on their own pages, and aligning them is
 * flagged for Bron rather than changed here. */
.acp p a:not(.acp-btn):not(.acp-arrow):not(.elementor-button),
.acp li a:not(.acp-btn):not(.acp-arrow):not(.elementor-button),
/* Comparison-table cells too: the first pass covered p and li only, and left the
   Hybrid / Vinyl / Timber links in the .acp-table header row on the old green. */
.acp th a:not(.acp-btn):not(.acp-arrow):not(.elementor-button),
.acp td a:not(.acp-btn):not(.acp-arrow):not(.elementor-button),
.acp dd a:not(.acp-btn):not(.acp-arrow):not(.elementor-button) {
	color: var(--acp-green);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}
.acp p a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):hover,
.acp p a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):focus-visible,
.acp li a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):hover,
.acp li a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):focus-visible,
.acp th a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):hover,
.acp th a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):focus-visible,
.acp td a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):hover,
.acp td a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):focus-visible,
.acp dd a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):hover,
.acp dd a:not(.acp-btn):not(.acp-arrow):not(.elementor-button):focus-visible {
	color: var(--acp-green-dark);
}

/* 3. THE RAIL CONTROL DOTS WERE ALSO THE OLD GREEN.
 *
 * `.acp-dot` rendered rgb(0,131,63) from the same style.css inheritance. The
 * design standard specifies the active dash as mint, so the dots are brought back
 * onto the palette. */
.acp .acp-dot { color: var(--acp-green); }
.acp .acp-dot.is-active,
.acp .acp-dot[aria-current='true'] { color: var(--acp-mint); }
/* 4. THE TILE LABELS WERE RENDERING IN THE BODY FACE.
 *
 * `.acp-tile-label` already declares `font-family: var(--acp-serif)` — the design
 * layer has always intended the display face for the notched corner label. It was
 * simply being overridden: post-conversion the label is a `<span>` inside a
 * text-editor widget, and style.css's Brand Guidelines V4 rollout sets
 * `.elementor-widget-text-editor span { font-family: var(--and-text) !important }`.
 * Measured on the carpet archive: all five labels in Inter.
 *
 * Same trap as the big count numerals on Shop Range. On a converted page nothing
 * inside a text-editor widget can carry display type without !important.
 *
 * This restores the declared intent rather than introducing a new style, so it is
 * applied to the shared class. It reaches the eight product archives Bron asked
 * about and the five other pages that use the same device (blinds, shutters,
 * curtains, awnings, company profile), which were always meant to look this way. */
.acp .acp-tile-label { font-family: var(--acp-serif) !important; }
/* ===== ACP-AUDIT-FIXES BLOCK: END ===== */

/* ===== ACP-NAV-ARROW BLOCK: START =====
   Added 23 August 2026.

   THE BUG. Every snap rail on the converted framework pages showed its prev and
   next controls as empty green pills. The controls themselves were fine: they
   are still 58x38, still bordered in --acp-green, and clicking them still
   scrolls the rail (verified on /product-category/carpet-flooring/, scrollLeft
   went 0 -> 373). What was missing was the arrow.

   THE CAUSE. The arrow was an inline <svg> in the shortcode markup. The
   Elementor conversion strips the <svg> wrapper and keeps only its children, so
   what survives in the page is a bare, orphaned

       <path d="M14 5H2M6 1L2 5l4 4" stroke="currentColor" ...></path>

   sitting inside a text-editor widget. A <path> outside an <svg> paints
   nothing, hence the empty pill. This is the same "SVG destroyed" conversion
   gap already noted against the other .acp compat fixes.

   THE FIX. Redraw the identical arrow from CSS, where the converter cannot
   reach it, using the original path as a mask so the shape is unchanged. The
   mask is filled with currentColor, so the existing .acp-nav:hover rule (which
   flips the button to a green fill and the colour to #fff) keeps inverting the
   arrow for free, and .acp-nav[disabled] keeps dimming it.

   One rule set fixes every rail on every framework page at once, so there is no
   per-page work and nothing to repeat the next time a page is converted.
   ====================================================================== */

/* Suppress whatever the button still contains so exactly one arrow is drawn.
   Two selectors because there are two possible DOMs: post-conversion the
   orphaned <path> is wrapped in Elementor containers (.elementor-element), and
   on any page still rendering straight from the shortcode the button holds a
   real inline <svg>. Either way the ::before below is the only arrow that
   paints. */
.acp .acp-nav > .elementor-element,
.acp .acp-nav > svg { display: none !important; }

/* The pill is already display:inline-flex from the base .acp-nav rule, but it
   is not positioned, so give it a containing block for the absolute arrow. */
.acp .acp-nav { position: relative; }

/* The arrow. 16x10 is the original viewBox, drawn at 1:1 so the stroke weight
   matches the rest of the rail chrome.

   background-color carries !important because the -webkit-mask shorthand used
   during testing silently swallowed a plain `currentColor` declaration; the
   longhand form below is well behaved, but the !important is kept as a cheap
   guard so a future shorthand edit cannot blank the arrow again. */
.acp .acp-nav::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: 16px;
	height: 10px;
	transform: translate(-50%, -50%);
	background-color: currentColor !important;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2010'%20fill='none'%20stroke='%23000'%20stroke-width='1.6'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%205H2M6%201L2%205l4%204'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2010'%20fill='none'%20stroke='%23000'%20stroke-width='1.6'%20stroke-linecap='round'%20stroke-linejoin='round'%3E%3Cpath%20d='M14%205H2M6%201L2%205l4%204'/%3E%3C/svg%3E");
	-webkit-mask-repeat: no-repeat;
	        mask-repeat: no-repeat;
	-webkit-mask-position: center;
	        mask-position: center;
	-webkit-mask-size: 16px 10px;
	        mask-size: 16px 10px;
}

/* The source path points left, so the next button is the same shape mirrored.
   Mirroring rather than shipping a second data URI keeps the two arrows exactly
   symmetrical. */
.acp .acp-nav-next::before { transform: translate(-50%, -50%) scaleX(-1); }

/* ===== ACP-NAV-ARROW BLOCK: END ===== */

/* ===== ANDERSENS GUTTER NORMALISE: START =====
   Added 7 September 2026.

   Elementor gives any container without explicit spacing a default 10px padding,
   and inside `.acp` those defaults STACK. Measured on the carpet archive:

       .acp.acp-top      10   (Elementor default, never set)
       .acp-wrap         30   (the real design gutter)
       .acp-hero-grid    10   (default)
       .acp-hero-copy    10   (default)
       -------------------------
       content edge      60   where the design says 30

   Zeroed through the VARIABLES, never a `padding` declaration. A `padding`
   shorthand here would flatten the genuine design padding on inner containers
   (`.acp-inset` 36px, `.acp-cta-strip` 38px, `.acp-caution` 28px), all of which
   come from real rules in this file rather than from the variables.

   Any container whose padding really WAS set in Elementor keeps it: Elementor
   writes those per element at `.elementor-{post} .elementor-element.elementor-element-{id}`,
   which is (0,3,0) and outranks this rule's (0,2,0).

   HORIZONTAL ONLY. The block/vertical variables are deliberately untouched so no
   vertical rhythm moves.

   Checked before changing: of 163 containers on the carpet archive, 103 sat on the
   10px default and NOT ONE of them directly contained a text node, so no copy can
   end up flush against an edge.

   This generalises the per-page root zeroing already written above for
   our-products, join-our-team, about and shop-range. Those blocks now do nothing
   extra but are harmless, so they stay.
   ============================================================================ */
.acp.e-con,
.acp .e-con {
	--padding-inline-start: 0px;
	--padding-inline-end: 0px;
	--padding-left: 0px;
	--padding-right: 0px;
}
/* ===== ANDERSENS GUTTER NORMALISE: END ===== */

/* === ANDERSENS PRODUCT TYPE (FIGMA) START — do not edit between sentinels === */
/* -------------------------------------------------------------------------
   SINGLE PRODUCT PAGES — Figma type ramp
   Added 9 September 2026.

   Scope: body.single-product, i.e. all 296 products, which all render through
   Elementor theme-builder template 3311 "Single Product" (include/product).
   That template was built pre-redesign and carried its own typography on every
   widget: Roboto families, 44/65/26/20/13px sizes, and weights 500/600/700 on
   Instrument Serif, which ships 400 only. Those per-widget settings have been
   stripped from _elementor_data so this block is the single owner of type, and
   each widget carries an .apr-* role class.

   THE NUMBERS BELOW ARE THE SAME RAMP AS `.acp` ABOVE and must never drift
   from it. Figma file UF4J4qKLGRiLqUhMab8bur has exactly one page, "Final
   Homepage", so there is no product-page frame; the roles are mapped onto the
   homepage ramp that the 33 .acp pages already use.
     H1  29:754 / 58:1332   68 / 52   400  0.95  0
     H2  29:878 / 58:1464   48 / 36   400  1.05  0
     H3  29:823             32        400  1.4   -0.03em (= -0.96px at 32)
     Eyebrow 29:880         10        700  0.95  0.2em (= 2px at 10)
     Body 29:879            14        400  1.5
     Card body 29:935       14        400  1.4
     Lede 29:757            14        400  1.2
     CTA 29:882             14        600
     Text link 29:937       12        600

   COLOURS ARE DELIBERATELY UNTOUCHED. The brief was fonts; the template's
   existing title/heading colours are left as they are and the deltas against
   Figma are recorded in the handover note rather than changed here.
   ---------------------------------------------------------------------- */

/* Elementor containers sit outside any .acp tree, so the tokens are repeated
   here exactly as .acp-formhost does it. Same values, no new vocabulary. */
body.single-product {
	--apr-serif: var(--and-display);
	--apr-sans: var(--and-text);
}

/* H1 — the product name -----------------------------------------------------
   Two widgets, one per breakpoint column: 6e01710 is the real <h1> (mobile)
   and f7aa277 is an <h2> (desktop). Both get the H1 ramp so the name is the
   same size whichever column is showing. */
body.single-product .apr-h1 .elementor-heading-title {
	font-family: var(--apr-serif);
	font-size: clamp(52px, calc(45.7126px + 1.56403vw), 68px); /* 52@402 -> 68@1425 */
	font-weight: 400;
	line-height: 0.95;
	letter-spacing: 0;
	text-transform: none;
}

/* H2 — section headings ----------------------------------------------------
   36 at 402 -> 48 at 1425. 1425 not 1440: vw resolves against the layout
   width once the scrollbar is out. */
body.single-product .apr-h2 .elementor-heading-title {
	font-family: var(--apr-serif);
	font-size: clamp(36px, calc(31.2844px + 1.17302vw), 48px);
	font-weight: 400;
	line-height: 1.05;
	letter-spacing: 0;
	text-transform: none;
}

/* Eyebrow — the product category name -------------------------------------
   Rendered as <div class="elementor-heading-title"> (was an <h2>), which also
   means the Brand V4 rollout in style.css hands it Inter rather than forcing
   the display face. */
body.single-product .apr-eyebrow .elementor-heading-title {
	font-family: var(--apr-sans);
	font-size: 10px;
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: 0.2em;
	text-transform: uppercase;
}

/* Body copy ---------------------------------------------------------------- */
body.single-product .apr-body,
body.single-product .apr-body p,
body.single-product .apr-body li,
body.single-product .apr-body .price,
body.single-product .apr-body .woocommerce-Price-amount {
	font-family: var(--apr-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: 0;
}
/* Inline labels in the attribute and spec lists. Figma has one body style and
   no inline-label style, so these keep the body metrics and take Inter
   semibold (an approved weight, brand guide p.33) rather than inventing one. */
body.single-product .apr-body strong,
body.single-product .apr-body b {
	font-weight: 600;
}

/* Lede — the short description --------------------------------------------- */
body.single-product .apr-lede,
body.single-product .apr-lede p {
	font-family: var(--apr-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.2;
	letter-spacing: 0;
	text-transform: none;
}
/* Same role, but drawn by a heading widget set to <h6>. h6 is outside the
   Brand V4 rollout's h1-h4 selector list, which is why this one was the only
   element on the page rendering real Roboto. */
body.single-product .apr-lede-h .elementor-heading-title {
	font-family: var(--apr-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.2;
	letter-spacing: 0;
}

/* Product description ------------------------------------------------------
   The long description, its "Specifications" <h3> and the spec list all come
   from the product's own post_content, rendered by the product-content widget.
   That widget is not .elementor-widget-heading or -text-editor, so nothing in
   style.css reaches the <h3> and it has to be named here. */
body.single-product .apr-prose,
body.single-product .apr-prose p,
body.single-product .apr-prose li {
	font-family: var(--apr-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.5;
	letter-spacing: 0;
}
body.single-product .apr-prose strong,
body.single-product .apr-prose b {
	font-weight: 600;
}
body.single-product .apr-prose h3 {
	font-family: var(--apr-serif);
	font-size: 32px;
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: -0.03em;
	text-transform: none;
}

/* Card titles and card bodies ---------------------------------------------
   The guarantee headings and the four icon boxes are h4-level. Figma has NO
   h4 equivalent — the framework recorded the same gap for `.acp-h4` and left
   it at Inter 16/700, so these follow that precedent rather than jumping to
   the 32px card title. Flagged in the handover note.
   font-family carries !important only on the real h4s, to beat the Brand V4
   rollout rule in style.css that forces the display face on every h1-h4
   inside a heading widget. Same trick, same reason, as `.acp .acp-h4`. */
body.single-product .apr-card-title .elementor-heading-title {
	font-family: var(--apr-sans) !important;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0;
	text-transform: none;
}
body.single-product .apr-card .elementor-image-box-title {
	font-family: var(--apr-sans);
	font-size: 16px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0;
	text-transform: none;
}
body.single-product .apr-card-body,
body.single-product .apr-card-body p,
body.single-product .apr-card .elementor-image-box-description {
	font-family: var(--apr-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.4;
	letter-spacing: 0;
}

/* CTAs ---------------------------------------------------------------------
   Type only. The button boxes are left exactly as they are: the .acp 37px
   pill geometry is a separate change with a live WCAG note against it, and
   the brief was fonts. */
body.single-product .apr-cta .elementor-button-text,
body.single-product .apr-cta .elementor-button,
body.single-product .apr-cta .button,
body.single-product .apr-cta .single_add_to_cart_button {
	font-family: var(--apr-sans);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0;
	text-transform: none;
}

/* Breadcrumb — the Figma text-link style (29:937/29:824). */
body.single-product .apr-crumbs,
body.single-product .apr-crumbs a,
body.single-product .apr-crumbs .woocommerce-breadcrumb,
body.single-product .apr-crumbs .woocommerce-breadcrumb a {
	font-family: var(--apr-sans);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0;
}

/* Related products grid ---------------------------------------------------
   Only the fractional size is corrected. This is a Premium Addons grid with
   its own responsive typography, and its real reference is the category-page
   product tile, which is styled inside four separate slide templates
   (17450/17454/17457/17460), not here. Restyling the tile properly is a
   separate pass — see the handover note. */
body.single-product .apr-tiles .premium-woo-product-category {
	font-size: 12px;
	font-weight: 600;
}
/* === ANDERSENS PRODUCT TYPE (FIGMA) END === */

/* === ANDERSENS IMAGE MOUNT REMOVAL START — do not edit between sentinels === */
/* -------------------------------------------------------------------------
   Photographs were drawn inside a 10px grey mount. Two causes, stacked:

     1. `.acp-media` sets `background: var(--acp-ph)` (#dedcd4) as a fallback
        ground, from the rule near the top of this file.
     2. `.acp-media` is an Elementor container, so it picks up Elementor's
        default 10px padding. The GUTTER NORMALISE block below zeroes the
        HORIZONTAL padding variables only - vertical was deliberately left
        alone so no vertical rhythm moved - so 10px top and bottom survived.

   Measured on the carpet archive: all 20 `.acp-media` wrappers carry the
   padding and the ground, but the grey only RENDERS in the two contexts whose
   image is sized at `height: 100%` of the padding box:

       .acp-hero-media     wrapper 580, photo 560   <- 10px band top and bottom
       .acp-split-media    wrapper 540, photo 520   <- same
       .acp-tile / .acp-style-card / .acp-feature / .acp-guide
                           photo height set explicitly, overflows the padding,
                           nothing showed

   Both of those are the big feature photographs, which is why it reads as a
   frame around the hero and the split band.

   The padding is zeroed on every `.acp-media` regardless, and the ground
   removed as well as asked, so a future change to an image height rule cannot
   bring the mount back.

   EFFECT, measured at 1280 wide with the layout settled: ZERO of the 20
   photographs change size. Only the two banded wrappers shrink, each by its
   own 20px (580->560 and 540->520), and the carpet archive ends up 20px
   shorter overall rather than 40, because one of the two sits in a grid row
   whose height is set by the taller copy column beside it. Nothing reflows
   sideways.

   Measure this with the layout SETTLED. An unsettled read gave 280/300 for
   those wrappers and briefly showed the hero photo changing size, which it
   does not; and `getComputedStyle` on a long-lived `.acp-media` returns a
   STALE background here (an inline `background: red !important` reads
   unchanged). Verify the ground with a freshly created element instead: a new
   `div.acp-media` reads #dedcd4 without this block and transparent with it.

   NOT touched:
     - `.acp-ph`, the real placeholder box, keeps its own grey from its own
       rule. It is a different class, so this cannot reach it. The curtains
       page still has 9 of them, deliberately.
     - `.acp-feature` and `.acp-guide` carry `rgba(255,255,255,0.9)` with 10px
       padding around an image AND a heading AND body copy. That white is the
       card itself, not an image mount, and its 10px is in the Figma
       (15/10/10). Raised with Bron separately.

   Added 9 September 2026.
   ---------------------------------------------------------------------- */
.acp .acp-media {
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-top: 0px;
	--padding-bottom: 0px;
	background: none;
}
/* === ANDERSENS IMAGE MOUNT REMOVAL END === */

/* === ANDERSENS ARCHIVE FILTER START — do not edit between sentinels === */
/* -------------------------------------------------------------------------
   PRODUCT CATEGORY ARCHIVE FILTERS
   Added 9 September 2026.

   The Unlimited Elements select filters had NEVER been styled: nothing in this
   file matched `.uc-select-filter` before this block. They rendered on the
   plugin's stock look - 1px #ddd border, square corners, 32px tall, native OS
   dropdown arrow - beside a design that is nothing like that.

   Worse, the plugin wraps each one as

       <div class="uc-select-filter" style="display:flex; gap:15px">
         <label>Filter By</label>
         <select class="uc-select-filter__select">

   and in the 285px col-25 sidebar that flex row squeezed the label to 33px, so
   "Filter By" wrapped onto two lines beside a 200px select. That is the broken
   look in the screenshot. The wrapper is restacked to label-above-field.

   These widgets sit in the Elementor archive template, OUTSIDE any `.acp`
   root, so the `--acp-*` tokens cannot be inherited. The handful needed are
   repeated here, exactly as `.acp-formhost` above does for the same reason.

   The control is deliberately styled to MATCH `.acp-formhost select` rule for
   rule - same 52px height, 12px radius, border, custom arrow, hover and focus -
   so the site has ONE select style rather than a second one. Two knowing
   deviations from that block:
     - font-size 14, not its 15, to sit on the Figma body ramp that the rest of
       the site moved onto today. The formhost's 15px is the outlier and should
       come down to 14 in its own pass.
     - the arrow SVG is drawn in %2300833f, the CURRENT green. The formhost copy
       still hardcodes %2314683e, the pre-7-September green, which no longer
       exists in the palette. That wants fixing there too.
   Radius 12 is kept for consistency with the formhost even though the Figma
   radius vocabulary is only 15/10/pill. Both should go to 10 together, not one
   at a time, or there would be three values instead of two.

   Scoped to `body.tax-product_cat`: the archive body class. Filters render only
   where the per-category ACF toggle switches them on (carpet has Fibre and
   Style; the other seven archives have all eight widgets present but toggled
   off), so this styles them wherever any category turns them on.
   ---------------------------------------------------------------------- */
body.tax-product_cat {
	--afl-line: #e6e2d6;
	--afl-green: #00833f;
	--afl-mint: #2bde81;
	--afl-ink: #000000;
	--afl-hover: #cfcaba;
}

/* Restack: label above the field, both full width.
   `!important` on display and the widths is REQUIRED, and was measured, not
   guessed: a plain `body.tax-product_cat .uc-select-filter.uc-grid-filter`
   at (0,3,0) left the computed display as `flex` and the label at 36px on two
   lines. With !important the label goes to 233x18 on one line and the select
   to the full 233px. The plugin's own rule could not be read back to confirm
   its selector (`document.styleSheets` enumerates nothing on this page, the
   same way it hides the `.acp-media` rules), so the override is empirical. */
body.tax-product_cat .uc-select-filter.uc-grid-filter {
	display: block !important;
	width: 100%;
	margin: 0 0 18px;
}

/* Label, matching `.acp-formhost .gfield_label`. */
body.tax-product_cat .uc-select-filter.uc-grid-filter > label {
	display: block !important;
	width: 100% !important;
	font-family: var(--and-text);
	font-size: 13px;
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: 0.04em;
	text-transform: none;
	color: var(--afl-green);
	margin: 0 0 8px;
}

/* The control, matching `.acp-formhost select`. */
body.tax-product_cat .uc-select-filter__select {
	width: 100% !important;
	box-sizing: border-box;
	min-height: 52px;
	padding: 14px 44px 14px 16px;
	background-color: #fff;
	border: 1px solid var(--afl-line);
	border-radius: 12px;
	box-shadow: none;
	font-family: var(--and-text);
	font-size: 14px;
	line-height: 1.5;
	color: var(--afl-ink);
	-webkit-appearance: none;
	appearance: none;
	/* Native arrow is lost with appearance:none, so it is drawn back on. */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none'%3E%3Cpath d='M1 1.5 6 6.5l5-5' stroke='%2300833f' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 16px center;
	cursor: pointer;
}
body.tax-product_cat .uc-select-filter__select:hover {
	border-color: var(--afl-hover);
}
/* OceanWP suppresses outlines, and a control cannot be left without one. */
body.tax-product_cat .uc-select-filter__select:focus,
body.tax-product_cat .uc-select-filter__select:focus-visible {
	outline: 3px solid var(--afl-mint);
	outline-offset: 2px;
	border-color: var(--afl-green);
}

/* -------------------------------------------------------------------------
   SEPARATE ISSUE, cosmetic suppression only - drop this rule if you would
   rather see it.

   Every archive renders a grey #e8e8e8 "No products found" bar, 825x67,
   customer-visible, at the top of the product area. It is NOT the product
   grid's message: the grid's own copy is correctly `display:none` while there
   are results. These two belong to the page's two
   `ucaddon_woocommerce_product_carousel` widgets, which return nothing on all
   eight archives, so each prints its empty state.

   The ROOT CAUSE is two empty carousel widgets that need either populating or
   deleting from the eight archive templates. That is a content decision and
   has NOT been made here. This rule only stops the bar reaching customers, and
   is scoped by `:has()` to the carousel containers so a genuine no-results
   message from the grid or a filter still shows.
   ---------------------------------------------------------------------- */
body.tax-product_cat .elementor-widget-container:has(.uc_overlay_image_carousel) .ue-no-posts-found {
	display: none;
}
/* === ANDERSENS ARCHIVE FILTER END === */

/* ACP-CFG-START */
/* ==========================================================================
   Product-page treatment, from Figma "Product Page (Carpet)"
   --------------------------------------------------------------------------
   NOTE, 11 September 2026: this began as a carpet-only block. Bron's direction
   is now "follow the carpet template for all product pages", so `.acp-cfg` is
   the shared PRODUCT-PAGE treatment and the carpet frame is the template for
   every product archive. Read `cfg` as "category Figma". Carpet was first,
   timber is second. The other six archives still carry the framework's own
   ramp until they are converted.
   --------------------------------------------------------------------------
   Source of truth: Figma file 4fAriJmKhougNrzoeEZLhy, page "Product Page
   (Carpet)" 2024:619 — desktop frame 2024:3571 (1440x10434) and mobile frame
   2024:4868 (402x14065). This is the FIRST Figma frame that has ever existed
   for a product-category page; before it, the .acp layer was extrapolated from
   the homepage. See the notes at the top of this file.

   EVERYTHING HERE IS SCOPED TO .acp-cfg, deliberately.

   The frame disagrees with the shared .acp ramp in two ways that would break
   the other 32 framework pages if applied globally:
     - section H2 is 68px here, where the homepage ramp (29:878) says 48px;
     - the "why people choose Andersens" H2 is 120px, a step that exists
       nowhere else on the site.
   The homepage remains the only reference for the pages that have no frame, so
   the carpet page carries its own root class rather than moving the ramp.
   If a frame later lands for the other categories, promote these rules.

   Palette is read from the .acp tokens, which are already the Figma tokens
   (Light #f6f5ef, White #fff, Yellow #ffa400, Bright #2bde81, Green #00833f).
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Type ramp deltas
   -------------------------------------------------------------------------- */

/* Body leading. The frame's body nodes (e.g. 2024:3508) are 14/1.4; the shared
   layer is 14/1.5 from the homepage's 29:879. */
.acp-cfg { line-height: 1.4; }
.acp-cfg p { line-height: 1.4; }

/* Section H2 -> 68/0.95. Written TWICE on purpose: on a shortcode-rendered
   page .acp-h2 lands on the real <h2>, on a converted page it lands on the
   Elementor widget WRAPPER and the heading is .elementor-heading-title. The
   two must never drift. */
.acp-cfg h2.acp-h2,
.acp-cfg .acp-h2 .elementor-heading-title {
	font-size: clamp(36px, calc(21.0596px + 1.05263vw), 52px);
	line-height: 0.95;
	letter-spacing: 0;
}
@media (min-width: 961px) {
	.acp-cfg h2.acp-h2,
	.acp-cfg .acp-h2 .elementor-heading-title {
		/* 68px at the 1425 layout width, not 1440: vw resolves against the
		   layout box once the scrollbar is out. */
		font-size: clamp(52px, calc(28.3368px + 2.80702vw), 68px);
	}
}

/* The one 120px step, "We'll have you feeling right at home." (2024:4831). */
.acp-cfg .acp-cfg-trust-h h2.acp-h2,
.acp-cfg .acp-cfg-trust-h .acp-h2 .elementor-heading-title {
	/* 40 at 402 -> 120 at the 1425 layout width. */
	font-size: clamp(40px, calc(8.563px + 7.8201vw), 120px);
	line-height: 0.95;
	text-align: center;
}

/* Sidebar "Carpet range" keeps the 48px step (2024:3876). */
.acp-cfg .acp-cfg-range-h h2.acp-h2,
.acp-cfg .acp-cfg-range-h .acp-h2 .elementor-heading-title {
	font-size: clamp(36px, calc(31.2844px + 1.17302vw), 48px);
	line-height: 0.95;
}

/* --------------------------------------------------------------------------
   2. Band grounds
   --------------------------------------------------------------------------
   The frame's ground is NOT a set of flat alternating bands. It is a
   continuous vertical wash between Light (#f6f5ef) and White, sampled from the
   rendered frame at x=8:

     0-772      flat  #f6f5ef
     772-1476   wash  #f6f5ef -> #ffffff
     1476-2836  flat  #ffffff
     2836-3012  wash  #ffffff -> #faf9f7
     3012-3992  flat  #faf9f7
     3992-4316  wash  #faf9f7 -> #f6f5ef
     4316-4916  flat  #f6f5ef
     4916-6032  wash  #f6f5ef -> #ffffff
     6032-6612  flat  #ffffff
     6612-6788  wash  #ffffff -> #faf9f7
     6788-7724  flat  #faf9f7
     7724-7900  wash  #faf9f7 -> #ffffff
     7900-8576  flat  #ffffff
     8576-8828  wash  #ffffff -> #faf9f7
     8828-9800  flat  #faf9f7

   Those stops are absolute, and our section heights do not match the frame's,
   so they are re-expressed per section. Where a wash crosses a section
   boundary it is split across both sections at the same two colours, which
   joins seamlessly at any height. */

.acp-cfg .acp-hero   { background: var(--acp-cream); }
.acp-cfg .acp-paths  { background: linear-gradient(180deg, var(--acp-cream) 0%, #ffffff 100%); }
.acp-cfg .acp-why    { background: linear-gradient(180deg, #ffffff 0%, #faf9f7 22%, #faf9f7 100%); }
.acp-cfg .acp-cfg-help { background: #faf9f7; }
.acp-cfg .acp-rooms  { background: linear-gradient(180deg, #faf9f7 0%, var(--acp-cream) 32%, var(--acp-cream) 74%, #fbfbf8 100%); }
.acp-cfg .acp-styles { background: linear-gradient(180deg, #fbfbf8 0%, #ffffff 100%); }
.acp-cfg .acp-fibres { background: #ffffff; }
.acp-cfg .acp-cfg-fit { background: linear-gradient(180deg, #ffffff 0%, #faf9f7 20%, #faf9f7 100%); }
.acp-cfg .acp-local  { background: #faf9f7; }
.acp-cfg .acp-guides { background: linear-gradient(180deg, #faf9f7 0%, #ffffff 58%, #ffffff 100%); }
.acp-cfg .acp-trust  { background: linear-gradient(180deg, #ffffff 0%, #faf9f7 22%, #faf9f7 100%); }

/* --------------------------------------------------------------------------
   3. Section rhythm, measured off the frame
   --------------------------------------------------------------------------
   Each top padding is the frame's gap between the previous band's last content
   and this band's first content. */

.acp-cfg .acp-hero   { padding: 60px 0 0; }
.acp-cfg .acp-paths  { padding: 100px 0 24px; }
.acp-cfg .acp-why    { padding: 168px 0 36px; }
.acp-cfg .acp-cfg-help { padding: 0 0 0; }
.acp-cfg .acp-rooms  { padding: 57px 0 0; }
.acp-cfg .acp-styles { padding: 85px 0 8px; }
.acp-cfg .acp-fibres { padding: 147px 0 100px; }
.acp-cfg .acp-cfg-fit { padding: 132px 0 0; }
.acp-cfg .acp-local  { padding: 77px 0 0; }
.acp-cfg .acp-guides { padding: 93px 0 0; }
.acp-cfg .acp-trust  { padding: 139px 0 100px; }

@media (max-width: 960px) {
	.acp-cfg .acp-hero   { padding: 34px 0 0; }
	.acp-cfg .acp-paths  { padding: 62px 0 16px; }
	.acp-cfg .acp-why    { padding: 70px 0 24px; }
	.acp-cfg .acp-rooms  { padding: 44px 0 0; }
	.acp-cfg .acp-styles { padding: 60px 0 8px; }
	.acp-cfg .acp-fibres { padding: 70px 0 62px; }
	.acp-cfg .acp-cfg-fit { padding: 66px 0 0; }
	.acp-cfg .acp-local  { padding: 54px 0 0; }
	.acp-cfg .acp-guides { padding: 58px 0 0; }
	.acp-cfg .acp-trust  { padding: 70px 0 62px; }
}

/* --------------------------------------------------------------------------
   4. Hero  (2024:3738 .. 2024:3749)
   --------------------------------------------------------------------------
   Copy column 400px at the gutter, image 915x633 right, the two vertically
   centred against each other (copy centre 475, image centre 475). */

/* Frame: copy 400 + 65 gutter + image 915, on a 1380 content width. The
   framework's own template is 480/820, which pushed the image 80px right and
   made it 95px narrower than drawn. */
.acp-cfg .acp-hero-grid {
	align-items: center;
	grid-template-columns: 400px minmax(0, 1fr);
	column-gap: 65px;
}
.acp-cfg .acp-hero-copy { max-width: 400px; }
.acp-cfg .acp-hero-media .acp-media,
.acp-cfg .acp-hero-media .acp-ph {
	border-radius: 15px;
	aspect-ratio: 915 / 633;
	height: auto;
}
/* One solid pill plus a text link, side by side (2024:3742). The shared layer
   stretches two pills to a common 320px; the frame has neither a second pill
   nor a stretched first one. */
.acp-cfg .acp-hero .acp-actions {
	max-width: none;
	align-items: center;
	column-gap: 20px;
	row-gap: 12px;
	flex-wrap: wrap;
}
.acp-cfg .acp-hero .acp-actions .acp-btn,
.acp-cfg .acp-hero .acp-actions .acp-btn a,
.acp-cfg .acp-hero .acp-actions .acp-btn .elementor-button {
	width: auto;
	flex: 0 0 auto;
	white-space: nowrap;
}
/* The hero arrow link is gold here, not green (2024:3746). */
.acp-cfg .acp-hero .acp-arrow,
.acp-cfg .acp-hero .acp-arrow a { color: var(--acp-gold); padding: 0; }

@media (max-width: 960px) {
	/* The fixed 400px first column has to be undone, or on a 402 viewport the
	   copy column takes the whole grid and the second track collapses to 0.
	   The mobile frame stacks copy above image. */
	.acp-cfg .acp-hero-grid { grid-template-columns: 1fr; row-gap: 26px; }
	.acp-cfg .acp-hero-copy { max-width: none; }
	.acp-cfg .acp-hero-media .acp-media,
	.acp-cfg .acp-hero-media .acp-ph { aspect-ratio: 362 / 277; }
}

/* --------------------------------------------------------------------------
   5. Tiles and rails  (paths rail 2024:3754.., category rail 2024:4805..)
   --------------------------------------------------------------------------
   Frame tile is 334 wide with a 300 tall image and a 15px gutter between
   tiles (x 30 / 379 / 728 / 1077 => pitch 349). The shared layer is 300 wide,
   370 tall, 22px gap. The notched label grows 27px -> 36px (2024:3757). */

.acp-cfg .acp-rail { gap: 15px; }
/* The frame fits four tiles across its 1380px content width exactly. Ours is
   1365 at a 1440 viewport once the scrollbar is out, so a hard 334px clipped
   the fourth tile by 46px AND the rail foot hid itself, because the framework
   hides the controls when it calculates that everything fits. Sizing the tile
   to a quarter of the rail keeps four across at any width and caps at the
   frame's 334px on a wider screen. */
.acp-cfg .acp-rail > .e-con { flex: 0 0 min(334px, calc((100% - 45px) / 4)); }
/* The rail carries 30px of right padding so an overflowing rail bleeds past
   the gutter. The four-tile pathways rail does not overflow, so that padding
   is dead space that shrinks every tile by 8px. */
.acp-cfg .acp-paths .acp-rail { padding-right: 0; }
.acp-cfg .acp-tile { width: 100%; max-width: 334px; }
.acp-cfg .acp-tile .acp-media,
.acp-cfg .acp-tile .acp-ph { height: 300px; border-radius: 15px; }
.acp-cfg .acp-tile-label {
	font-size: 36px;
	line-height: 1.8;
	padding: 0 12px 6px 20px;
	border-bottom-left-radius: 20px;
	border-top-right-radius: 15px;
}
/* The frame carries no descriptive note under the tile label. */
.acp-cfg .acp-tile-note { display: none; }

@media (max-width: 640px) {
	.acp-cfg .acp-tile { width: 282px; }
	.acp-cfg .acp-tile .acp-media,
	.acp-cfg .acp-tile .acp-ph { height: 254px; }
	.acp-cfg .acp-tile-label { font-size: 28px; padding: 0 10px 5px 15px; }
}

/* --------------------------------------------------------------------------
   6. Range band  (sidebar 2024:3778 / 3855, grid 2024:3870.., pager 2024:4611)
   --------------------------------------------------------------------------
   The band is the ONLY place on the page where the Unlimited Elements product
   grid, the two select filters and the pagination live. None of those widgets
   is rebuilt: they are re-laid-out and restyled. The section is an old-style
   Elementor section/column pair, so the container query has to reach through
   .elementor-container and .elementor-column. */

.acp-cfg-rangeband { background: #ffffff !important; padding: 114px 0 100px; }
.acp-cfg-rangeband > .elementor-container {
	max-width: 1560px;
	margin: 0 auto;
	padding: 0 30px;
	display: flex;
	align-items: flex-start;
	gap: 15px;
}
/* Left column: the sidebar card stack, fixed to the frame's 334px. */
.acp-cfg-rangeband > .elementor-container > .elementor-column:first-child {
	width: 334px;
	flex: 0 0 334px;
	max-width: 334px;
}
.acp-cfg-rangeband > .elementor-container > .elementor-column:last-child {
	flex: 1 1 auto;
	width: auto;
	max-width: none;
	min-width: 0;
}
.acp-cfg-rangeband .elementor-widget-wrap { padding: 0 !important; }

/* 6a. Sidebar cards. Two cream panels: the range heading + filter, and the
   two guarantee promos. */
.acp-cfg-sidecard {
	background: rgba(246, 245, 239, 0.75);
	border-radius: 15px;
	padding: 23px;
}
.acp-cfg-sidecard + .acp-cfg-sidecard { margin-top: 20px; }
.acp-cfg-sidecard .acp-lede { margin-top: 14px; }

/* 6b. Filter panel. "FILTER" sits on the eyebrow style with a hairline under
   it, then the widget's own selects. */
.acp-cfg-filterhead {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	margin-top: 26px;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--acp-green);
}
.acp-cfg-filterhead .acp-eyebrow,
.acp-cfg-filterhead .acp-eyebrow .elementor-heading-title { color: var(--acp-green); }
.acp-cfg-filtertoggle {
	appearance: none;
	background: none;
	border: 0;
	padding: 0;
	min-width: 24px;
	min-height: 24px;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	color: var(--acp-green);
	font: inherit;
	cursor: pointer;
}
.acp-cfg-filtertoggle::before { content: "\2013"; font-size: 14px; line-height: 1; }
.acp-cfg-filtertoggle[aria-expanded="false"]::before { content: "+"; }

/* The select filters. The widget draws its own label and box; the frame wants
   a white pill-less rounded field with a single chevron and no "Filter By". */
.acp-cfg-rangeband .elementor-widget-ucaddon_ue_select_post_filter {
	padding: 0 !important;
	box-shadow: none !important;
	margin: 12px 0 0 !important;
}
.acp-cfg-rangeband .ue-filter-label,
.acp-cfg-rangeband .elementor-widget-ucaddon_ue_select_post_filter label { display: none !important; }
.acp-cfg-rangeband .elementor-widget-ucaddon_ue_select_post_filter select {
	width: 100%;
	height: 40px;
	padding: 0 34px 0 13px;
	background: #ffffff;
	border: 1px solid var(--acp-line);
	border-radius: 10px;
	font-family: inherit;
	font-size: 14px;
	font-weight: 400;
	line-height: 1.4;
	color: var(--acp-ink);
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 8 5'%3E%3Cpath d='M0 0h8L4 5z' fill='%2300833f'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 13px center;
}

/* 6c. Product search (2024:3565 "PRODUCT" + magnifier).
   The Unlimited Elements "Search Filter" widget, so the markup is theirs: an
   .uc-search-filter__input and a .uc-search-filter-btn that already carries a
   Font Awesome magnifier. Only the box is restyled; the widget keeps its own
   AJAX behaviour, which is why this filters the grid in place rather than
   navigating to a search results page. */
.acp-cfg-psearch { margin-top: 15px !important; padding: 0 !important; }
.acp-cfg-psearch .uc-search-filter,
.acp-cfg-psearch .uc-search-filter-input-wrapper { position: relative; width: 100%; }
/* The widget colours its own input at a specificity our class cannot reach,
   so this is scoped through the band as well to win on class count. */
.acp.acp-cfg.acp-cfg-rangeband .acp-cfg-psearch input.uc-search-filter__input {
	width: 100%;
	height: 50px;
	padding: 0 56px 0 20px;
	background: transparent;
	border: 1px solid var(--acp-green);
	border-radius: 10px;
	font-family: inherit;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: var(--acp-green);
	box-shadow: none;
}
/* The placeholder is the field's only visible label, so its contrast matters.
   The widget colours it grey (3.19:1) from an ID selector
   (#uc_posts_search_filter_elementor_<id>), which no class count can beat, and
   the id contains a generated element id so hard-coding it would be brittle.
   This is one of the defensive !important overrides this sheet already uses
   where a plugin fights us. Both the prefixed and unprefixed pseudo-elements
   are listed because the widget targets the prefixed one. */
.acp.acp-cfg.acp-cfg-rangeband .acp-cfg-psearch input.uc-search-filter__input::placeholder {
	color: var(--acp-green) !important;
	opacity: 1;
}
.acp.acp-cfg.acp-cfg-rangeband .acp-cfg-psearch input.uc-search-filter__input::-webkit-input-placeholder {
	color: var(--acp-green) !important;
	opacity: 1;
}
.acp.acp-cfg.acp-cfg-rangeband .acp-cfg-psearch .uc-search-filter-btn {
	position: absolute;
	top: 50%;
	right: 8px;
	transform: translateY(-50%);
	width: 34px;
	height: 34px;
	min-width: 0;
	min-height: 0;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: 0;
	border-radius: 999px;
	color: var(--acp-green);
	cursor: pointer;
}
.acp.acp-cfg.acp-cfg-rangeband .acp-cfg-psearch .uc-search-filter-btn .ue-btn-icon { color: var(--acp-green); }
.acp.acp-cfg.acp-cfg-rangeband .acp-cfg-psearch .uc-search-filter-btn .ue-btn-icon i { font-size: 16px; }
/* The widget's own empty label span would otherwise add width to the pill. */
.acp-cfg-rangeband .acp-cfg-psearch .uc-search-filter-btn .ue-btn-text { display: none; }
.acp-cfg-rangeband .acp-cfg-psearch .uc-search-filter-btn:hover { background: var(--acp-cream); }

/* 6d. Guarantee promos. The two image-box widgets already carry the badge and
   the approved guarantee wording; only their box is restyled. The visualiser
   promo is dropped from the sidebar, because the frame puts a Visualizer pill
   on every product card instead. */
.acp-cfg-rangeband .visualise-popup-btn { display: none !important; }
.acp-cfg-rangeband .elementor-widget-image-box {
	padding: 0 !important;
	margin: 0 !important;
}
.acp-cfg-rangeband .elementor-widget-image-box + .elementor-widget-image-box {
	margin-top: 30px !important;
	padding-top: 30px !important;
	border-top: 1px solid var(--acp-green);
}
.acp-cfg-rangeband .elementor-image-box-wrapper { text-align: left; }
.acp-cfg-rangeband .elementor-image-box-img { width: 100px !important; margin: 0 0 18px !important; }
.acp-cfg-rangeband .elementor-image-box-title {
	font-family: var(--acp-serif) !important;
	font-size: 32px !important;
	font-weight: 400 !important;
	line-height: 0.95 !important;
	letter-spacing: -0.96px !important;
	color: var(--acp-green) !important;
	margin: 0 0 12px !important;
}
.acp-cfg-rangeband .elementor-image-box-title a { color: inherit !important; }
.acp-cfg-rangeband .elementor-image-box-description {
	font-size: 14px !important;
	line-height: 1.4 !important;
	color: var(--acp-ink) !important;
}

/* 6e. Product cards (2024:4510). The widget renders
   [image] [uc_content: category label, title, swatches]. The frame wants
   title, then image with a Visualizer pill, then swatches, so the two
   intermediate boxes are flattened with display:contents and the children are
   ordered. No markup is rebuilt. */
.acp-cfg-rangeband .ue-woo-grid { gap: 15px !important; }
.acp-cfg-rangeband .uc_post_grid_style_one_item {
	display: flex !important;
	/* !important: the widget is configured layout:side_by_side and writes its
	   own row direction at a specificity we cannot beat from here. Without this
	   the reordered title, image and swatches laid out side by side. */
	flex-direction: column !important;
	background: rgba(246, 245, 239, 0.75) !important;
	border-radius: 15px !important;
	padding: 10px 10px 14px !important;
	box-shadow: none !important;
}
.acp-cfg-rangeband .uc_post_grid_style_one_item > div { display: contents; }
.acp-cfg-rangeband .uc_content { display: contents !important; padding: 0 !important; }
.acp-cfg-rangeband .ue_category_label { display: none !important; }
.acp-cfg-rangeband .uc_title { order: 1; margin: 0 0 8px 14px; }
.acp-cfg-rangeband .uc_post_grid_style_one_image { order: 2; display: block; }
.acp-cfg-rangeband .ue-variation_swatches { order: 3; margin-top: 12px; padding: 0 4px; }

.acp-cfg-rangeband .uc_title,
.acp-cfg-rangeband .uc_title a {
	font-family: var(--acp-serif) !important;
	font-size: 32px !important;
	font-weight: 400 !important;
	line-height: 1.4 !important;
	letter-spacing: -0.96px !important;
	color: var(--acp-green) !important;
	text-transform: none !important;
	text-decoration: none;
}
.acp-cfg-rangeband .uc_post_grid_style_one_image { position: relative; }
.acp-cfg-rangeband .uc_post_image,
.acp-cfg-rangeband .uc_post_image img {
	border-radius: 10px;
	display: block;
	width: 100%;
}
.acp-cfg-rangeband .uc_post_image {
	aspect-ratio: 314 / 206;
	overflow: hidden;
}
.acp-cfg-rangeband .uc_post_image img { height: 100%; object-fit: cover; }

/* The per-card Visualizer pill (2024:4590). This is the Floori plugin's own
   per-product button, moved into the image mount and restyled by
   js/flooring-category.js. Any Floori button that has not been adopted yet is
   kept out of the card flow so it cannot flash in the wrong place. */
.acp-cfg-rangeband .floori-additional-button:not(.acp-cfg-vis) { display: none; }
.acp-cfg-vis {
	position: absolute;
	top: 9px;
	right: 9px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 10px 15px;
	background: #ffffff;
	border-radius: 103px;
	font-family: inherit;
	font-size: 12px;
	font-weight: 600;
	line-height: normal;
	color: var(--acp-green);
	text-decoration: none;
	white-space: nowrap;
	border: 0;
	cursor: pointer;
	appearance: none;
}
.acp-cfg-vis:hover,
.acp-cfg-vis:focus-visible { background: var(--acp-cream); color: var(--acp-green-dark); }

/* Swatches: 29 x 19, radius 4, 1px hairline, 7px gutter (36px pitch). */
.acp-cfg-rangeband .ue-variation_swatches {
	display: flex;
	flex-wrap: wrap;
	gap: 7px;
}
.acp-cfg-rangeband .product-category-swatch { margin: 0 !important; }
.acp-cfg-rangeband .product-category-swatch a { display: block; line-height: 0; }
.acp-cfg-rangeband .product-category-swatch img {
	width: 29px;
	height: 19px;
	object-fit: cover;
	border: 1px solid rgba(0, 0, 0, 0.35);
	border-radius: 4px;
	display: block;
}

/* 6f. Pagination (2024:4611 numbers, 2024:4613 / 4615 the two pills)
   --------------------------------------------------------------------------
   Measured off the frame: the two pills are the SAME 64x30 as the rail-foot
   navs, pinned to the two ends of the grid column (x379 and x1347..1411), with
   the numbers centred between them at x841..949. Current page is full green
   and semibold; the rest are green at 50%. Glyph pitch is ~20px.

   MY OWN BUG, fixed here: the first pass styled `.next` as a 58x38 icon pill,
   but the widget renders it as the WORD "Next" plus a Font Awesome chevron, so
   the label overflowed the oval and the chevron dropped underneath it.

   The widget writes its own colours and padding from
   `#uc_archive_pagination_elementor_<id> ...`, an ID selector no class count
   can beat, so the handful of declarations that fight it carry !important.
   Rather than hide the widget's chevron pseudo-elements and draw on the other
   one, this repurposes them: `content` is emptied and the same nav-arrow mask
   is painted into the box they already occupy. */

.acp.acp-cfg.acp-cfg-rangeband .archive_pagination {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0;
	min-height: 30px;
}

/* Numbers */
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers {
	width: auto;
	min-width: 20px;
	height: 30px;
	padding: 0 !important;
	border: 0;
	border-radius: 0;
	background: none !important;
	font-size: 15px;
	font-weight: 400;
	line-height: 1;
	color: rgba(0, 131, 63, 0.5) !important;
}
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.current {
	color: var(--acp-green) !important;
	font-weight: 600;
}
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination a.page-numbers:hover {
	color: var(--acp-green) !important;
}

/* The two pills, pinned to the ends of the grid column */
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.prev,
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.next {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 64px;
	min-width: 64px;
	height: 30px;
	padding: 0 !important;
	border: 1px solid var(--acp-green);
	border-radius: 999px;
	background: #ffffff !important;
	/* Hides the "Next" / "Previous" label and the icon font while leaving the
	   text in the accessibility tree, so the link keeps its name. */
	font-size: 0 !important;
	overflow: hidden;
}
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.prev { left: 0; }
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.next { right: 0; }
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.prev:hover,
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.next:hover {
	background: var(--acp-green) !important;
}

/* The widget's own chevron pseudo-elements, repainted as the nav arrow. */
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.prev::before,
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.next::after {
	content: "" !important;
	position: absolute;
	/* -1px, not 0: an absolutely positioned child resolves against the PADDING
	   box, which is 62x28 inside the 1px border, and the mask is drawn at the
	   frame's 64x30. */
	inset: -1px;
	padding: 0 !important;
	background: var(--acp-green);
	-webkit-mask: var(--acp-cfg-nav-arrow) center / 64px 30px no-repeat;
	        mask: var(--acp-cfg-nav-arrow) center / 64px 30px no-repeat;
}
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.prev::before {
	transform: scaleX(-1);
}
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.prev:hover::before,
.acp.acp-cfg.acp-cfg-rangeband .archive_pagination .page-numbers.next:hover::after {
	background: #ffffff;
}

/* On page one WordPress emits no `prev` link at all, so the frame's greyed-out
   left pill simply is not there. The numbers stay centred and the next pill
   stays on the right, which is the same reading. */

@media (max-width: 1200px) {
	.acp-cfg-rangeband > .elementor-container { flex-wrap: wrap; }
	.acp-cfg-rangeband > .elementor-container > .elementor-column:first-child,
	.acp-cfg-rangeband > .elementor-container > .elementor-column:last-child {
		width: 100%;
		flex: 1 1 100%;
		max-width: none;
	}
}
@media (max-width: 960px) {
	.acp-cfg-rangeband { padding: 62px 0 62px; }
	.acp-cfg-rangeband > .elementor-container { padding: 0 20px; }
	/* Mobile collapses the filter to a single "FILTER +" bar (mobile frame). */
	.acp-cfg-sidecard[data-collapsed="true"] .acp-cfg-filterbody { display: none; }
	.acp-cfg-rangeband .uc_title,
	.acp-cfg-rangeband .uc_title a { font-size: 26px !important; }
}

/* --------------------------------------------------------------------------
   7. Why choose carpet  (2024:4675 .. 4689)
   --------------------------------------------------------------------------
   Four heading/body pairs in the copy column, each closed by a hairline
   (2024:4677-4679), against a tall image. */

/* Frame: copy 448 at x32, a 16px gutter, image 915, ending on the right
   gutter. The framework's own template left ~194px of the row unused and the
   photograph 240px narrower than drawn. */
.acp-cfg .acp-why .acp-split {
	align-items: start;
	grid-template-columns: 448px minmax(0, 1fr);
	column-gap: 16px;
}
.acp-cfg .acp-why .acp-split-copy { max-width: 448px; }
.acp-cfg .acp-why .acp-split-media .acp-media,
.acp-cfg .acp-why .acp-split-media .acp-ph {
	border-radius: 15px;
	aspect-ratio: 915 / 686;
	height: auto;
	max-height: none;
	min-height: 0;
}
@media (max-width: 960px) {
	/* Same as the hero: the fixed 448px track collapsed the image to zero. */
	.acp-cfg .acp-why .acp-split { grid-template-columns: 1fr; row-gap: 26px; }
	.acp-cfg .acp-why .acp-split-copy { max-width: none; }
}
.acp-cfg .acp-benefits { margin-top: 26px; }
.acp-cfg .acp-benefits li {
	padding: 0 0 22px;
	margin: 0 0 22px;
	border-bottom: 1px solid var(--acp-green);
	list-style: none;
}
.acp-cfg .acp-benefits li:last-child { border-bottom: 0; padding-bottom: 0; margin-bottom: 0; }
.acp-cfg .acp-benefits li > strong,
.acp-cfg .acp-benefits .acp-cfg-bt {
	display: block;
	font-family: var(--acp-serif);
	font-size: 32px;
	font-weight: 400;
	line-height: 0.95;
	letter-spacing: -0.96px;
	color: var(--acp-green);
	margin-bottom: 10px;
}
.acp-cfg .acp-benefits p { font-size: 14px; line-height: 1.4; margin: 0; }

/* --------------------------------------------------------------------------
   8. Split green bands  (2024:3779 + 4692 + 4699, and 2024:3780 + 4696 + 4707)
   --------------------------------------------------------------------------
   One image at 689x365 hard against the left edge, one green panel filling the
   rest, the pair rounded 16 as a single slab. Used twice: "Not sure which
   carpet is right for your home?" and "Find a local Andersens carpet expert
   near you." */

.acp-cfg .acp-cfg-split {
	display: grid;
	grid-template-columns: 689fr 691fr;
	align-items: stretch;
	border-radius: 16px;
	overflow: hidden;
	background: var(--acp-green);
	min-height: 365px;
}
/* The photograph must CROP to the band, never set its height. Timber's help
   band uses a 1333x2000 portrait source: with the media cell in normal flow it
   drove the row to 1034px instead of the frame's 365. Same failure as
   .acp-split-media and a portrait source. Taking the media out of flow leaves
   the row height to the copy column and the 365px floor. */
.acp-cfg .acp-cfg-split-media { position: relative; overflow: hidden; }
.acp-cfg .acp-cfg-split-media .acp-media,
.acp-cfg .acp-cfg-split-media .acp-ph {
	position: absolute;
	inset: 0;
	height: 100%;
	border-radius: 0;
}
.acp-cfg .acp-cfg-split-media .elementor-widget-image,
.acp-cfg .acp-cfg-split-media .elementor-widget-container { height: 100%; border-radius: 0; }
.acp-cfg .acp-cfg-split-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 0;
	display: block;
}
.acp-cfg .acp-cfg-split-copy {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: flex-start;
	padding: 60px 76px;
	gap: 26px;
}
.acp-cfg .acp-cfg-split-copy .acp-h2 .elementor-heading-title,
.acp-cfg .acp-cfg-split-copy h2.acp-h2 { color: #ffffff; }
.acp-cfg .acp-cfg-split-copy .acp-h2 em,
.acp-cfg .acp-cfg-split-copy .acp-h2 .elementor-heading-title em { color: var(--acp-mint); }
.acp-cfg .acp-cfg-split-copy .acp-actions {
	max-width: none;
	display: flex;
	align-items: center;
	column-gap: 20px;
	row-gap: 12px;
	flex-wrap: wrap;
	margin: 0;
}
.acp-cfg .acp-cfg-split-copy .acp-btn a,
.acp-cfg .acp-cfg-split-copy .acp-btn .elementor-button {
	width: auto;
	flex: 0 0 auto;
	white-space: nowrap;
	background: #ffffff;
	border-color: #ffffff;
	color: var(--acp-green);
}
.acp-cfg .acp-cfg-split-copy .acp-btn a:hover,
.acp-cfg .acp-cfg-split-copy .acp-btn .elementor-button:hover {
	background: var(--acp-cream);
	color: var(--acp-green-dark);
}
.acp-cfg .acp-cfg-split-copy .acp-arrow,
.acp-cfg .acp-cfg-split-copy .acp-arrow a { color: #ffffff; padding: 0; }

@media (max-width: 960px) {
	.acp-cfg .acp-cfg-split { grid-template-columns: 1fr; min-height: 0; }
	.acp-cfg .acp-cfg-split-media { aspect-ratio: 689 / 365; }
	.acp-cfg .acp-cfg-split-copy { padding: 32px 26px 38px; gap: 20px; }
}

/* --------------------------------------------------------------------------
   9. Room-by-room band  (2024:3579 .. 3599, 3593)
   --------------------------------------------------------------------------
   Desktop: one photograph 1380x792, a white detail card pinned top-right, and
   the room names laid over the foot of the image, the selected one white and
   the rest at 50% white (2024:3593). Mobile: the same names become a stacked
   list with the selected room's card beneath it.

   It is ONE component and ONE behaviour at both widths: an ARIA tablist, so
   the framework's existing roving-tabindex JS drives it. */

.acp-cfg .acp-rooms .acp-head-centre { max-width: 660px; margin: 0 auto; text-align: center; }
.acp-cfg .acp-rooms .acp-head-centre .acp-lede { margin-left: auto; margin-right: auto; }

.acp-cfg-roomband {
	position: relative;
	margin-top: 36px;
	border-radius: 15px;
	overflow: hidden;
	min-height: 792px;
}
.acp-cfg-roomband-media { position: absolute; inset: 0; }
.acp-cfg-roomband-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}
/* The scrim. It rides on ::after so the image widget's own box is untouched,
   and it is only under the name list, where the contrast problem is. */
.acp-cfg-roomband::after {
	content: "";
	position: absolute;
	inset: auto 0 0 0;
	height: 46%;
	background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.42) 62%, rgba(0, 0, 0, 0.52) 100%);
	pointer-events: none;
}
/* Elementor gives .elementor-widget its own position, which made each html
   widget the containing block for the absolutely positioned list and card. The
   list has bottom:44px, so against a zero-height widget box it landed above the
   photograph instead of over the foot of it. Force the widget wrappers static
   so the band is the containing block. Containers are untouched, so
   .acp-cfg-roomband-media keeps its own absolute inset:0. */
.acp-cfg-roomband > .elementor-widget,
.acp-cfg-roomband > .elementor-widget > .elementor-widget-container { position: static !important; }

/* The name list, overlaid at the foot. */
.acp-cfg-roomlist {
	position: absolute;
	inset: auto 54px 44px 54px;
	z-index: 3;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: baseline;
	column-gap: 26px;
	row-gap: 0;
}
.acp-cfg-roomlist button {
	appearance: none;
	background: none;
	border: 0;
	padding: 0 2px;
	font-family: var(--acp-serif);
	/* 32 at 402 -> 68 at the 1425 layout width. */
	font-size: clamp(32px, calc(17.854px + 3.519vw), 68px);
	font-weight: 400;
	line-height: 0.95;
	letter-spacing: -0.136px;
	color: rgba(255, 255, 255, 0.5);
	cursor: pointer;
	transition: color 0.18s ease;
}
.acp-cfg-roomlist button[aria-selected="true"] { color: #ffffff; }
.acp-cfg-roomlist button:hover { color: rgba(255, 255, 255, 0.8); }
.acp-cfg-roomlist button:focus-visible {
	outline: 2px solid #ffffff;
	outline-offset: 3px;
	border-radius: 4px;
}

/* The detail card, pinned top-right. */
.acp-cfg-roompanels {
	position: absolute;
	top: 39px;
	right: 26px;
	width: 334px;
	z-index: 3;
}
.acp-cfg-roompanel {
	background: rgba(255, 255, 255, 0.94);
	border-radius: 15px;
	padding: 23px 25px 25px;
}
.acp-cfg-roompanel .acp-h3,
.acp-cfg-roompanel h3 {
	font-family: var(--acp-serif);
	font-size: 32px;
	font-weight: 400;
	line-height: 0.95;
	letter-spacing: -0.96px;
	color: var(--acp-green);
	margin: 0 0 14px;
}
.acp-cfg-roompanel p { font-size: 14px; line-height: 1.4; margin: 0 0 12px; }
.acp-cfg-roompanel p:last-child { margin-bottom: 0; }
.acp-cfg-roompanel hr {
	height: 0;
	border: 0;
	border-top: 1px solid var(--acp-green);
	margin: 16px 0;
}
.acp-cfg-roompanel .acp-cfg-inl {
	font-weight: 600;
	color: var(--acp-green);
}

@media (max-width: 1200px) {
	.acp-cfg-roomband { min-height: 640px; }
	.acp-cfg-roompanels { width: 300px; }
}
/* Mobile: no photograph, no overlay. The names become a list and the selected
   room's card opens beneath it (mobile frame 2024:4868). */
@media (max-width: 960px) {
	.acp-cfg-roomband {
		min-height: 0;
		border-radius: 0;
		overflow: visible;
		margin-top: 26px;
	}
	.acp-cfg-roomband-media,
	.acp-cfg-roomband::after { display: none; }
	.acp-cfg-roomlist {
		position: static;
		inset: auto;
		display: block;
		column-gap: 0;
	}
	.acp-cfg-roomlist button {
		width: 100%;
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 12px;
		min-height: 48px;
		padding: 10px 0;
		border-bottom: 1px solid rgba(0, 131, 63, 0.35);
		font-size: 32px;
		line-height: 1.1;
		text-align: left;
		color: rgba(0, 131, 63, 0.4);
	}
	.acp-cfg-roomlist button[aria-selected="true"] { color: var(--acp-green); }
	.acp-cfg-roomlist button:hover { color: rgba(0, 131, 63, 0.7); }
	.acp-cfg-roomlist button::after {
		content: "+";
		font-family: Inter, sans-serif;
		font-size: 18px;
		line-height: 1;
		flex: 0 0 auto;
	}
	.acp-cfg-roomlist button[aria-selected="true"]::after { content: "\2013"; }
	.acp-cfg-roomlist button:focus-visible { outline-color: var(--acp-green); }
	.acp-cfg-roompanels {
		position: static;
		top: auto;
		right: auto;
		width: auto;
		margin-top: 18px;
	}
	.acp-cfg-roompanel { background: rgba(246, 245, 239, 0.9); }
}

/* --------------------------------------------------------------------------
   10. Style cards  (2024:4715 "Group 131")
   --------------------------------------------------------------------------
   White card, 10px image mount, then title, body, hairline, a green
   semibold label and a second body. */

.acp-cfg .acp-style-card {
	width: 334px;
	background: #ffffff;
	border-radius: 15px;
	padding: 10px 10px 22px;
}
.acp-cfg .acp-style-card .acp-media,
.acp-cfg .acp-style-card .acp-ph { height: 206px; border-radius: 10px; }
.acp-cfg .acp-style-card .acp-h3,
.acp-cfg .acp-style-card h3 { margin: 16px 14px 8px; }
.acp-cfg .acp-style-card p { margin: 0 14px; font-size: 14px; line-height: 1.4; }
.acp-cfg .acp-style-card hr {
	height: 0;
	border: 0;
	border-top: 1px solid var(--acp-green);
	margin: 16px 14px;
}
.acp-cfg .acp-style-card .acp-cfg-sub {
	display: block;
	margin: 0 14px 6px;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.4;
	color: var(--acp-green);
}

@media (max-width: 640px) {
	.acp-cfg .acp-style-card { width: 300px; }
	.acp-cfg .acp-style-card .acp-media,
	.acp-cfg .acp-style-card .acp-ph { height: 186px; }
}

/* --------------------------------------------------------------------------
   11. Fibre accordion  (2024:3500 expanded state, 2024:3512.. collapsed)
   --------------------------------------------------------------------------
   Copy column 681px, portrait photograph 683x749 right. Each fibre is a
   <details>, so every answer is in the rendered HTML and no JS is needed.

   ACCESSIBILITY NOTE, DELIBERATE: the frame draws a closed row's name and tag
   at 40% of the green (2024:3513, 2024:3544). Against this band that is about
   1.9:1, well under WCAG AA, and these are interactive controls rather than
   decorative text. Shipped as drawn on Bron's "match the Figma exactly"
   direction, consistent with the 7 September palette swap and the 37px CTAs.
   Raising the closed state to 65% would clear AA with almost no visual change
   if an audit picks it up. */

.acp-cfg .acp-fibres .acp-cfg-fibregrid {
	display: grid;
	grid-template-columns: 681fr 683fr;
	column-gap: 16px;
	align-items: start;
}
.acp-cfg .acp-cfg-fibremedia .acp-media,
.acp-cfg .acp-cfg-fibremedia .acp-ph {
	border-radius: 15px;
	aspect-ratio: 683 / 749;
	height: auto;
}
.acp-cfg .acp-cfg-fibres { margin-top: 26px; border-top: 1px solid var(--acp-green); }
.acp-cfg .acp-cfg-fibre { border-bottom: 1px solid var(--acp-green); }
.acp-cfg .acp-cfg-fibre > summary {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 12px 0;
	min-height: 48px;
	cursor: pointer;
	list-style: none;
}
.acp-cfg .acp-cfg-fibre > summary::-webkit-details-marker { display: none; }
.acp-cfg .acp-cfg-fibre-name {
	font-family: var(--acp-serif);
	font-size: 36px;
	font-weight: 400;
	line-height: 0.95;
	letter-spacing: -0.072px;
	color: rgba(0, 131, 63, 0.4);
}
.acp-cfg .acp-cfg-fibre[open] .acp-cfg-fibre-name { color: var(--acp-green); }
.acp-cfg .acp-cfg-fibre-tag {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 10px 15px;
	background: var(--acp-cream);
	border-radius: 110px;
	font-size: 10px;
	font-weight: 700;
	line-height: 0.95;
	letter-spacing: 2px;
	text-transform: uppercase;
	color: rgba(0, 131, 63, 0.4);
}
.acp-cfg .acp-cfg-fibre[open] .acp-cfg-fibre-tag { color: var(--acp-green); }
.acp-cfg .acp-cfg-fibre-plus {
	margin-left: auto;
	flex: 0 0 auto;
	width: 24px;
	height: 24px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: Inter, sans-serif;
	font-size: 18px;
	font-weight: 400;
	line-height: 1;
	color: rgba(0, 131, 63, 0.4);
}
.acp-cfg .acp-cfg-fibre-plus::before { content: "+"; }
.acp-cfg .acp-cfg-fibre[open] .acp-cfg-fibre-plus { color: var(--acp-green); }
.acp-cfg .acp-cfg-fibre[open] .acp-cfg-fibre-plus::before { content: "\2013"; }
.acp-cfg .acp-cfg-fibre-body { padding: 0 0 22px; max-width: 681px; }
.acp-cfg .acp-cfg-fibre-body p { font-size: 14px; line-height: 1.4; margin: 0 0 10px; }
.acp-cfg .acp-cfg-fibre-body p:last-child { margin-bottom: 0; }
.acp-cfg .acp-cfg-fibre-body .acp-cfg-inl { font-weight: 600; color: var(--acp-green); }
.acp-cfg .acp-cfg-fibre > summary:focus-visible {
	outline: 2px solid var(--acp-green);
	outline-offset: 2px;
}

@media (max-width: 960px) {
	.acp-cfg .acp-fibres .acp-cfg-fibregrid { grid-template-columns: 1fr; row-gap: 24px; }
	.acp-cfg .acp-cfg-fibre-name { font-size: 30px; }
}

/* --------------------------------------------------------------------------
   12. "Find the perfect fit" head  (2024:4791 / 4792 / 4793)
   -------------------------------------------------------------------------- */

.acp-cfg .acp-cfg-fit .acp-cfg-fithead {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 30px;
	flex-wrap: wrap;
}
.acp-cfg .acp-cfg-fit .acp-cfg-fithead .acp-lede { max-width: 392px; margin-top: 12px; }
.acp-cfg .acp-cfg-fit .acp-cfg-fithead .acp-arrow,
.acp-cfg .acp-cfg-fit .acp-cfg-fithead .acp-arrow a { color: var(--acp-gold); padding: 0; }
.acp-cfg .acp-cfg-fit .acp-rail-wrap { margin-top: 36px; }

/* --------------------------------------------------------------------------
   13. Article cards  (2024:3781 "Group 142")
   --------------------------------------------------------------------------
   Same 334 card as a style card, with a two-line serif title and a green
   text link instead of the sub-label pair. */

.acp-cfg .acp-guides .acp-rail-wrap { margin-top: 36px; }
.acp-cfg .acp-cfg-post {
	width: 334px;
	display: flex;
	flex-direction: column;
	background: #ffffff;
	border-radius: 15px;
	padding: 10px 10px 22px;
	text-decoration: none;
}
.acp-cfg .acp-cfg-post .acp-media,
.acp-cfg .acp-cfg-post .acp-ph { height: 206px; border-radius: 10px; }
.acp-cfg .acp-cfg-post .acp-h3,
.acp-cfg .acp-cfg-post h3 { margin: 16px 14px 10px; }
.acp-cfg .acp-cfg-post p { margin: 0 14px 16px; font-size: 14px; line-height: 1.4; }
.acp-cfg .acp-cfg-post .acp-arrow,
.acp-cfg .acp-cfg-post .acp-arrow a,
.acp-cfg .acp-cfg-post .acp-cfg-more {
	margin: auto 14px 0;
	padding: 0;
	color: var(--acp-green);
	font-size: 12px;
	font-weight: 600;
}

@media (max-width: 640px) {
	.acp-cfg .acp-cfg-post { width: 300px; }
	.acp-cfg .acp-cfg-post .acp-media,
	.acp-cfg .acp-cfg-post .acp-ph { height: 186px; }
}

/* --------------------------------------------------------------------------
   14. Trust cards  (2024:4844 / 4833 / 4856)
   --------------------------------------------------------------------------
   450 wide, white at 90%, 15px radius, 10px image mount, staggered +100 and
   +199 (the shared layer offsets +90 / +180). */

.acp-cfg .acp-cfg-trust-h { margin-bottom: 44px; }
.acp-cfg .acp-cfg-trust-h .acp-eyebrow,
.acp-cfg .acp-cfg-trust-h .acp-eyebrow .elementor-heading-title { text-align: center; }
.acp-cfg .acp-trust .acp-feature-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 450px));
	justify-content: center;
	column-gap: 15px;
	align-items: start;
}
.acp-cfg .acp-trust .acp-feature { width: auto; max-width: 450px; padding: 10px; }
/* The frame staggers these by +100 and +199. Bron's call, 16 September 2026:
   the cards sit on one row instead, here and on every other section that uses
   this grid. A deliberate divergence from the frame, recorded. */
.acp-cfg .acp-trust .acp-feature:nth-child(2),
.acp-cfg .acp-trust .acp-feature:nth-child(3) { margin-top: 0; }
.acp-cfg .acp-trust .acp-feature .acp-media,
.acp-cfg .acp-trust .acp-feature .acp-ph {
	aspect-ratio: 430 / 240;
	height: auto;
	border-radius: 10px;
}
.acp-cfg .acp-trust .acp-feature-body { padding: 22px 15px 15px; }
.acp-cfg .acp-trust .acp-feature-body .acp-h3,
.acp-cfg .acp-trust .acp-feature-body h3 { margin: 0 0 12px; }
.acp-cfg .acp-trust .acp-feature-body p { font-size: 14px; line-height: 1.4; margin: 0 0 16px; }
.acp-cfg .acp-trust .acp-feature-body .acp-arrow,
.acp-cfg .acp-trust .acp-feature-body .acp-arrow a { color: var(--acp-green); padding: 0; }

@media (max-width: 960px) {
	.acp-cfg .acp-trust .acp-feature-grid { grid-template-columns: minmax(0, 450px); row-gap: 20px; }
	.acp-cfg .acp-trust .acp-feature:nth-child(2),
	.acp-cfg .acp-trust .acp-feature:nth-child(3) { margin-top: 0; }
}

/* --------------------------------------------------------------------------
   15. Shared inline label, used in the room card and the fibre bodies
   -------------------------------------------------------------------------- */
.acp-cfg .acp-cfg-inl { font-weight: 600; color: var(--acp-green); }

/* --------------------------------------------------------------------------
   16. The text-link arrow glyph
   --------------------------------------------------------------------------
   MOVED OUT on 11 September 2026. This was a carpet-scoped fix for a bug that
   affects every converted page, so it now lives in its own framework-wide
   block at the foot of this file. Only the carpet-specific
   pieces stay here: the article card's "Read more", which is a plain span
   rather than an .acp-arrow, and the two colour overrides further up. */

.acp-cfg .acp-cfg-post .acp-cfg-more { display: inline-flex; align-items: center; gap: 8px; }
.acp-cfg .acp-cfg-post .acp-cfg-more::after {
	content: "";
	flex: 0 0 auto;
	width: 18px;
	height: 12px;
	background: currentColor;
	-webkit-mask: var(--acp-arrow-glyph) center / 18px 12px no-repeat;
	        mask: var(--acp-arrow-glyph) center / 18px 12px no-repeat;
}

/* The product grid's own stylesheet puts 16px on the card, where the frame's
   body is 14. Equal specificity, and the widget's sheet loads later, so this
   needs the extra class. */
.acp.acp-cfg.acp-cfg-rangeband .uc_post_grid_style_one_item { font-size: 14px; }

/* --------------------------------------------------------------------------
   17. The containers that need a horizontal row
   --------------------------------------------------------------------------
   Elementor drives container direction through `--flex-direction`, consumed by
   TWO-class selectors, so a plain `flex-direction` declaration on a single
   class can never win. The framework already lists its own exceptions in
   section 7 of this file; these are the ones this page adds, written the same
   way and at a higher class count so they beat the framework's own entries.

   `.acp .acp-hero .acp-actions.e-flex` is set to COLUMN upstream, because the
   framework's hero stacks two pills at a common width. The frame has one pill
   and a text link side by side, so that has to be undone here specifically. */

.acp.acp-cfg .acp-hero .acp-actions.e-flex,
.acp.acp-cfg .acp-hero .acp-actions {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: center;
	--gap: 14px; --row-gap: 12px; --column-gap: 14px;
	/* The variable alone is not enough here. Unlike every other container on
	   the page, the hero's action row also carries a DIRECT
	   `flex-direction: column` (section 4 of this file, "the hero deliberately
	   stacks its two pills at a common width"), and that declaration loads
	   after Elementor's `flex-direction: var(--flex-direction)` at the same
	   two-class specificity, so it wins. Both have to be undone. */
	flex-direction: row;
	align-items: center;
	flex-wrap: wrap;
	/* 14px, not 20: the frame's row is 395 wide (pill 234 + 14 + link 147) and
	   has to sit inside a 400px copy column. At 20 it wrapped. */
	gap: 12px 14px;
	max-width: none;
	margin-top: 34px;
}
/* With the row restored, the button's wrapper container must stop stretching
   or the single pill fills the column and pushes the text link off the row. */
.acp.acp-cfg .acp-hero .acp-actions > .acp-btn,
.acp.acp-cfg .acp-hero .acp-actions > .e-con {
	--width: auto;
	width: auto;
	flex: 0 0 auto;
}
.acp.acp-cfg .acp-cfg-fithead.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: flex-end;
	--justify-content: space-between;
	--gap: 30px; --row-gap: 20px; --column-gap: 30px;
}
.acp-cfg .acp-cfg-filterhead.e-flex {
	--flex-direction: row;
	--align-items: center;
	--justify-content: space-between;
	--gap: 10px; --row-gap: 10px; --column-gap: 10px;
}
/* The head block inside the fit row must not stretch to the full width, or the
   arrow link is pushed onto its own line. */
.acp.acp-cfg .acp-cfg-fithead > .e-con { --width: auto; width: auto; flex: 1 1 620px; }
.acp.acp-cfg .acp-cfg-fithead > .acp-arrow { flex: 0 0 auto; }

@media (max-width: 640px) {
	.acp.acp-cfg .acp-hero .acp-actions.e-flex { --align-items: flex-start; }
}

/* --------------------------------------------------------------------------
   18. Rail foot: nav pills and progress dashes
   --------------------------------------------------------------------------
   Read straight off the frame's own flattened SVG for node 2024:3774, so these
   are exact rather than measured off a render:

     <rect x=.5 y=.5 width=63 height=29 rx=14.5 fill="white" stroke="#00833F"/>
     <path d="M39 20L44 15L39 10M44 15H20" stroke="#00833F" stroke-linejoin="round"/>

   That is a 64x30 pill with a 1px border and a WHITE fill, holding a 24x10
   arrow drawn at stroke-width 1. The framework ships 58x38, a 1.5px border, a
   transparent fill and a 16x10 arrow at stroke-width 1.6, which is why the live
   pills read as too tall and the arrow too short and too heavy.

   The dashes measured off the same frame: active 60x3 mint, inactive 24x3 at
   FULL green. The framework draws both at 4px in #2f2f2b at 55% opacity, a
   grey that is not in the palette, with the active one 66px.

   Scoped to .acp-cfg, like every other disagreement between this frame and the
   shared ramp: the rail foot is on all 33 pages and only carpet has a frame.
   Promote it if and when the others get one.

   The 24px hit target is preserved: the button stays 24px tall and the dash is
   drawn as a pseudo-element inside it, which is the framework's own device. */

.acp-cfg .acp-navs { gap: 11px; }
.acp-cfg .acp-nav {
	width: 64px;
	height: 30px;
	border-width: 1px;
	background: #ffffff;
}
.acp-cfg .acp-nav:hover { background: var(--acp-green); }

/* The mask keeps the frame's own 64x30 viewBox and path, so the arrow lands
   exactly where it is drawn rather than being re-centred by hand. */
.acp-cfg .acp-nav::before {
	width: 64px;
	height: 30px;
	-webkit-mask-image: var(--acp-cfg-nav-arrow);
	        mask-image: var(--acp-cfg-nav-arrow);
	-webkit-mask-size: 64px 30px;
	        mask-size: 64px 30px;
}
.acp-cfg {
	--acp-cfg-nav-arrow: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2030'%20fill='none'%20stroke='%23000'%20stroke-width='1'%20stroke-linejoin='round'%3E%3Cpath%20d='M39%2020L44%2015L39%2010M44%2015H20'/%3E%3C/svg%3E");
}
/* The frame's path points RIGHT, the opposite of the framework's source path,
   so the mirroring swaps over: next is drawn as-is and prev is flipped. */
.acp-cfg .acp-nav-next::before { transform: translate(-50%, -50%); }
.acp-cfg .acp-nav-prev::before { transform: translate(-50%, -50%) scaleX(-1); }

/* The dashes are only reachable at all because the container-defaults block
   stops .acp-navs taking the whole rail foot. These are carpet's own numbers:
   the frame's 60/24 at 3px, against the framework's 66/22 at 4px. min-width
   floors them so they survive a tight row. */
/* Written at .acp.acp-cfg so these beat the framework's own 22/66 floor in the
   container-defaults block, which is appended after this one. */
.acp-cfg .acp-dots { gap: 7px; }
.acp.acp-cfg .acp-dot { width: 24px; min-width: 24px; }
.acp.acp-cfg .acp-dot::before {
	height: 3px;
	background: var(--acp-green);
	opacity: 1;
}
.acp.acp-cfg .acp-dot[aria-current='true'] { width: 60px; min-width: 60px; }
.acp.acp-cfg .acp-dot[aria-current='true']::before { background: var(--acp-mint); }

/* --------------------------------------------------------------------------
   19. MOVED OUT
   --------------------------------------------------------------------------
   Elementor's default vertical container padding, and `.acp-navs` starving the
   rail dashes, were both fixed here first and are now framework-wide at
   Bron's direction. See the container-defaults block at the foot of this file.
   Only carpet's own numbers stay above: the 64x30 pill, the 60/24 dashes and
   the 24px WCAG floor on the inactive dash. */

/* --------------------------------------------------------------------------
   20. Range band with no sidebar
   --------------------------------------------------------------------------
   Bron's call for timber, 11 September 2026: every one of its eight filters is
   switched off in `filter_display_settings` and the category holds four
   products, so the frame's 334px filter sidebar would be an empty panel above
   a single row of cards. The column is hidden rather than deleted, because the
   eight filter widgets and the visualiser promo must stay in the DOM: the
   promo is where the per-card Visualizer pill reads its popup href, and the
   filters have to survive in case the toggles are ever switched on.

   The guarantee promos are moved under the grid by the build script and laid
   out as a row of cards, so approved published content is not lost with the
   sidebar. */

.acp-cfg-nosidebar > .elementor-container > .elementor-column:first-child {
	display: none;
}
.acp-cfg-nosidebar > .elementor-container > .elementor-column:last-child {
	width: 100%;
	flex: 1 1 100%;
	max-width: none;
}

.acp-cfg .acp-cfg-promos.e-flex {
	--flex-direction: row;
	--flex-wrap: wrap;
	--align-items: stretch;
	--gap: 15px; --row-gap: 15px; --column-gap: 15px;
}
.acp-cfg .acp-cfg-promos { margin-top: 30px; }
.acp-cfg .acp-cfg-promos .elementor-widget-image-box {
	flex: 1 1 300px;
	background: rgba(246, 245, 239, 0.75);
	border-radius: 15px;
	padding: 23px !important;
	margin: 0 !important;
	border-top: 0;
}

/* --------------------------------------------------------------------------
   21. Anchor targets clear the sticky header
   --------------------------------------------------------------------------
   The pathway tiles jump to the section containers. `header.anh` is sticky and
   measures 123px, so a target landing at y=0 has its eyebrow and part of its
   H2 hidden underneath it.

   The sheet's existing convention is `scroll-margin-top: 90px` (.acp-range,
   and the FMQ, in-home-service, company-profile and join-our-team anchors).
   That is 33px SHORT of the real header and always has been - those pages park
   their headings partly under it today. 130px actually clears it, with a small
   gap, and still reads correctly if the header is ever shortened.

   Scoped to the product pages rather than changed globally: correcting the
   other pages' 90px is a separate call for Bron. */

.acp-cfg .acp-range,
.acp-cfg .acp-rooms,
.acp-cfg .acp-styles,
.acp-cfg .acp-fibres,
.acp-cfg .acp-why,
.acp-cfg-rangeband {
	scroll-margin-top: 130px;
}

/* ACP-CFG-END */

/* ACP-ARROW-START */
/* =========================================================================
   .acp-arrow — restore the missing glyph, framework-wide
   =========================================================================
   Added 11 September 2026, after the carpet Figma build turned this up.

   THE BUG. `.acp-arrow` is the tertiary CTA: a 12px underlined text link with
   a right-pointing arrow. On every page that went through the Elementor
   conversion the inline <svg> became a text-editor widget holding a BARE
   ORPHANED <path>. A <path> outside an <svg> paints nothing, so the arrow is
   simply absent, and its holder container still stretches to `--width: 100%`
   (measured at 480px on the carpet hero) and pushes the row. Same failure as
   the rail arrows, which were fixed by redrawing from CSS with the original
   path as a mask; the text links were never done.

   THE AUDIT, across all 33 registered .acp pages: 137 arrow links.

     27  a real inline <svg>          working, must not be touched
     93  an orphaned <path> box       broken, this fixes them
     17  no icon markup at all        never had one, this gives them one

   All 137 use the SAME path, `M1 5h12M9 1l4 4-4 4`. There are no left-pointing
   or otherwise variant arrows, so one glyph is safe.

   WHY `:not(:has(svg))`. The 27 working links must not gain a second arrow, so
   the glyph and the orphan-hiding are both gated on the link having no real
   <svg> of its own. Where `:has()` is unsupported the whole rule is dropped and
   the page renders exactly as it does today, which is the current state — so
   the fallback is no worse than no fix.

   The mask is sized to match a real one exactly: `.acp .acp-arrow svg` is
   width 18px on a 15x10 viewBox, so the box is 18x12 and the mask 18px 12px.
   ========================================================================= */

.acp {
	--acp-arrow-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='15' height='10' viewBox='0 0 15 10'%3E%3Cpath d='M1 5h12M9 1l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* Converted pages only: the link is an Elementor container, so it takes its
   direction and width from the variables. Without the row it stacks the glyph
   under the label; without the auto width it stretches the whole column and
   drags the underline with it. Listed here rather than in section 7 because it
   belongs with the rest of the fix. */
.acp .acp-arrow.e-flex {
	--flex-direction: row;
	--align-items: center;
	--gap: 8px; --row-gap: 8px; --column-gap: 8px;
	--width: auto;
}
.acp .acp-arrow.e-con { width: auto; }

/* SECOND, PRE-EXISTING BUG, found while verifying the first. Elementor sets
   `min-width: 0` on nested containers, so an arrow sitting in a row such as
   .acp-actions shrank below its own content and wrapped character by character
   into a 0px-wide column. Measured on /awnings/ BEFORE this block existed:
   0x302, 0x215, 0x157, 0x157, 0x331 — five links rendered as vertical stacks
   of letters. It is the same failure, and the same fix, as .acp-btn: Figma's
   link labels are all whitespace-nowrap. Longest label site-wide is "Make a
   claim under this guarantee" at about 241px including the glyph, which still
   fits the narrowest card (300px) at 402. */
.acp .acp-arrow { flex: 0 0 auto; white-space: nowrap; }

/* The orphan box paints nothing but still occupies the row. */
.acp .acp-arrow:not(:has(svg)) > .e-con { display: none !important; }

/* THIRD, also pre-existing. `--width: auto` above shrink-wraps the link in a
   ROW, but in a COLUMN container width is the cross axis, so `align-items:
   normal` stretched it and the underline ran well past the label: measured
   395px under a 124px "Find a local store". It is the same three links on
   every page, the arrow in each of the three "why Andersens" feature cards.
   Scoped to that component rather than applied to every .acp-arrow, because
   `align-self` on an arrow sitting in a row would top-align it and break its
   alignment with the pill beside it (verified: row arrows stay centred). */
.acp .acp-feature-body .acp-arrow { align-self: flex-start; }

.acp .acp-arrow:not(:has(svg))::after {
	content: "";
	flex: 0 0 auto;
	width: 18px;
	height: 12px;
	background: currentColor;
	-webkit-mask: var(--acp-arrow-glyph) center / 18px 12px no-repeat;
	        mask: var(--acp-arrow-glyph) center / 18px 12px no-repeat;
}
/* ACP-ARROW-END */

/* ACP-CONTAINER-DEFAULTS-START */
/* =========================================================================
   Two Elementor container defaults, fixed for every .acp page
   =========================================================================
   Added 11 September 2026 at Bron's direction, after both turned up while
   building the carpet page to its Figma frame. Both were carpet-scoped first
   and are now lifted to all 33 registered `.acp` pages.

   Neither changes a design decision. Both remove an Elementor default that was
   never asked for and that the framework has been fighting since conversion.

   ---------------------------------------------------------------------------
   1. The default VERTICAL container padding

   The 7 September gutter-normalise block zeroed Elementor's default container
   padding on the INLINE axis only, which is what put the framework back on its
   30px gutter. The 10px top and bottom was left behind, on every `.acp-head`,
   `.acp-hero-grid`, `.acp-actions`, `.acp-tile`, `.acp-rail-foot`, `.acp-navs`,
   `.acp-split`, `.acp-feature-grid` and every media box.

   Surveyed before the change: 70 such containers on the timber archive, 116 on
   awnings, 116 on curtains, 45 on the company profile. Each was adding 20px of
   height nobody specified, and showing a band of ground around anything meant
   to sit flush - which is how Bron caught it, twice, as green showing around
   two photographs on the carpet page.

   Zeroed through the variables, not `padding: 0`: `.e-con` consumes them at a
   specificity a single class cannot beat. Anything that sets its own padding
   keeps it, because those are shorthand declarations in this sheet, which
   loads after Elementor's.

   ---------------------------------------------------------------------------
   2. `.acp-navs` starving the rail dashes

   `.acp-navs` is an Elementor container carrying `--width: 100%`, so it took
   about 1281px of a 1365px rail foot and left the dashes 49px. They then
   flex-shrank to their minimum, which is why **the active dash has never
   rendered at its designed 66px on any page** - measured at 21px on timber,
   awnings, curtains and the company profile before this change. The width was
   being applied and then shrunk away, which is why it looked like a cascade
   problem and was not one.

   `flex: 0 0 auto` on the dot is what makes the fix hold; without it the dash
   is shrunk again as soon as the row is tight.
   ========================================================================= */

.acp .e-con {
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-top: 0px;
	--padding-bottom: 0px;
}

.acp .acp-navs {
	--width: auto;
	width: auto;
	flex: 0 0 auto;
}
/* `min-width` is what actually makes it hold. `flex: 0 0 auto` alone still
   rendered the active dash at 22px on a real timber page load even though its
   specified width is 66px; flooring it at the designed width is what pins it.
   Neither value is a design change: 66 and 22 are the framework's own. */
.acp .acp-dot { flex: 0 0 auto; min-width: 22px; }
.acp .acp-dot[aria-current='true'] { min-width: 66px; }
/* ACP-CONTAINER-DEFAULTS-END */

/* ACP-CFG-FIBREMEDIA-CROP-START
   The "compare fibres / getting the tone right" portrait must CROP to its box,
   never set the row height.

   `.acp-cfg .acp-cfg-fibremedia .acp-media` already carries
   `aspect-ratio: 683 / 749`, so the BOX is the right shape. The <img> inside it
   was never constrained, so it kept its own intrinsic height and overflowed a
   box it was supposed to fill. How far out it went depended entirely on the
   source: carpet's 1200x1316 lands on 749 by coincidence and looked fine, which
   is why this was missed when the frame shipped.

       carpet   1200x1316  ->  749px   fits by luck
       vinyl     900x1110  ->  842px   overflows 93px
       cork     1707x2560  -> 1024px   overflows 275px
       timber   1187x2000  -> 1151px   overflows 402px, bleeds into the next band

   Same failure, same fix, as `.acp-cfg .acp-cfg-split-media` above: give the
   box a definite height and make the photograph fill and crop rather than
   drive the layout. 11 September 2026. */
.acp-cfg .acp-cfg-fibremedia .acp-media { position: relative; overflow: hidden; }
.acp-cfg .acp-cfg-fibremedia .acp-media .elementor-widget-image,
.acp-cfg .acp-cfg-fibremedia .acp-media .elementor-widget-container { height: 100%; }
.acp-cfg .acp-cfg-fibremedia .acp-media img {
	width: 100%;
	height: 100%;
	min-height: 0;
	max-height: none;
	object-fit: cover;
	display: block;
	border-radius: 15px;
}
/* ACP-CFG-FIBREMEDIA-CROP-END */

/* === SHOP RANGE PHOTO CARDS START ========================================= *
 * 16 September 2026. Bron's change request against /shop-range/: take the
 * product count and the word "products" off the nine floor-covering cards and
 * put the photograph behind the card instead. Extended the same afternoon to the
 * four window-furnishing cards, so both grids on the page are photo cards.
 *
 * The photograph itself is a container background set per card in Elementor, so
 * it stays editable in the builder. This block is the reading layer only.
 *
 * The card keeps the Figma vocabulary unchanged: 15px radius, the 10px white
 * mount, one shadow, the existing hover lift. Only the inner .acp-guide-body
 * becomes the picture, at the 10px inner radius, which is the same mount the
 * image-first .acp-guide has always drawn around a photograph.
 *
 * Selector lists rather than one shorter selector: the two grids are
 * .acp-shop-grid (nine, 3-up) and .acp-shop-window .acp-guide-grid (four, 4-up).
 * Written out so each rule's specificity is obvious, because the shared card
 * rules further up this file sit at (0,3,0) and (0,3,1).
 *
 * The .acp-shop-n rules further up are now dead. Left in place rather than
 * deleted: this file has concurrent editors and the smaller diff is safer.
 */

.acp-shop-range .acp-shop-grid .acp-guide-body,
.acp-shop-range .acp-shop-window .acp-guide-grid .acp-guide-body {
	position: relative;
	overflow: hidden;
	border-radius: 10px;
	min-height: 300px;
	padding: 26px 24px 24px;
	/* The ground under the photograph while it loads, and under the scrim. */
	background-color: #10241a;
	/* Belt and braces. Elementor writes these per card as well, but a container
	   background with no explicit size tiles at its intrinsic size, which is
	   exactly what caught the homepage bands. */
	background-size: cover;
	background-position: center center;
	background-repeat: no-repeat;
}

/* The scrim.
 *
 * The copy sits at the TOP of the card and the product in every one of these
 * photographs is lower in the frame, so the gradient runs the opposite way to
 * the usual caption treatment: solid where the words are, clear over the floor
 * or the window, which is the thing the card is actually selling.
 *
 * Measured rather than guessed, by compositing each source image at the real
 * card size and sampling every row the copy can occupy. Worst of the thirteen is
 * 6.4:1 against white, on the narrower 4-up window cards where the copy runs to
 * three lines. AA needs 4.5:1. The 42% and 60% stops are what carry that third
 * line; do not pull them up without re-running the measurement.
 */
.acp-shop-range .acp-shop-grid .acp-guide-body::before,
.acp-shop-range .acp-shop-window .acp-guide-grid .acp-guide-body::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(to bottom,
		rgba(16, 36, 26, 0.91) 0%,
		rgba(16, 36, 26, 0.85) 42%,
		rgba(16, 36, 26, 0.56) 60%,
		rgba(16, 36, 26, 0.14) 80%,
		rgba(16, 36, 26, 0) 95%);
	pointer-events: none;
}

/* Widgets are static boxes, so they need lifting over the scrim explicitly. */
.acp-shop-range .acp-shop-grid .acp-guide-body > *,
.acp-shop-range .acp-shop-window .acp-guide-grid .acp-guide-body > * { position: relative; z-index: 1; }

/* Type inverts over the photograph. Four classes deliberately: the card title
 * rule `.acp.acp-shop-range .acp-guide .acp-h4` is (0,3,0) and the body copy
 * rule `.acp.acp-shop-range .acp-guide p:not(...)` is (0,3,1), so anything
 * shorter loses and the heading stays green on a dark photograph. */
.acp.acp-shop-range .acp-shop-grid .acp-guide .acp-h4,
.acp.acp-shop-range .acp-shop-grid .acp-guide .acp-h4 .elementor-heading-title,
.acp.acp-shop-range .acp-shop-window .acp-guide .acp-h4,
.acp.acp-shop-range .acp-shop-window .acp-guide .acp-h4 .elementor-heading-title { color: #fff; }
.acp.acp-shop-range .acp-shop-grid .acp-guide p,
.acp.acp-shop-range .acp-shop-window .acp-guide p { color: rgba(255, 255, 255, 0.93); }

/* A 1px hover ring reads as noise against a photograph, so the lift and a
 * deeper shadow carry the hover instead. The border stays for :focus-visible. */
.acp-shop-range .acp-shop-grid .acp-guide:hover,
.acp-shop-range .acp-shop-grid .acp-guide:focus-visible,
.acp-shop-range .acp-shop-window .acp-guide:hover,
.acp-shop-range .acp-shop-window .acp-guide:focus-visible {
	box-shadow: 0 12px 30px rgba(0, 0, 0, 0.16);
	border-color: transparent;
}
.acp-shop-range .acp-shop-grid .acp-guide:focus-visible,
.acp-shop-range .acp-shop-window .acp-guide:focus-visible { border-color: var(--acp-green); }

@media (max-width: 1200px) {
	.acp-shop-range .acp-shop-grid .acp-guide-body,
	.acp-shop-range .acp-shop-window .acp-guide-grid .acp-guide-body { min-height: 270px; }
}
@media (max-width: 640px) {
	.acp-shop-range .acp-shop-grid .acp-guide-body,
	.acp-shop-range .acp-shop-window .acp-guide-grid .acp-guide-body { min-height: 240px; padding: 22px 20px 20px; }
}
/* === SHOP RANGE PHOTO CARDS END =========================================== */

/* === START acp-guide card fix 2026-09-17 =================================
   Two defects on the "Keep looking" band, reported in the Final Website Sweep
   (Gabby, row 5, /window-blinds/).

   1. The image wrapper stretched and pushed the copy out of the card.
      The Elementor compatibility layer sets `height: 100%` on `.acp .acp-img`
      and its `.elementor-widget-container` so converted pages fill their media
      box. Inside a `.acp-guide` card that is a stretched grid item, that
      percentage resolves against the ROW height, so the wrapper grew to the
      full card (336px) while the <img> stayed at its fixed 190px. The
      `.acp-guide-body` then began below the card's own bottom edge and
      overflowed it by up to 136px, which reads as the heading colliding with
      the card on the row beneath. All four cards were affected, not just the
      one in the report.

      `.acp-style-card` already carries exactly this exemption. This mirrors it
      for `.acp-guide` rather than weakening the shared rule, so no other
      component moves. Shutters, curtains and tiles already measure 190px, so
      they are unchanged by it.

   2. Window blinds had four cards in the shared three-up grid, leaving a single
      orphan on a second row. Curtains, tiles and shutters already carry a
      four-up override for exactly this reason; this mirrors those, including
      their 1200px and 960px breakpoints, and touches no other page.

   Awnings has five cards in the three-up grid. That is 3 + 2 rather than a
   single orphan and it does not overflow, so it is deliberately left alone.
   ========================================================================= */

.acp .acp-guide .acp-img,
.acp .acp-guide .acp-img .elementor-widget-container { height: auto; }

.acp-blinds .acp-guide-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }

@media (max-width: 1200px) {
	.acp-blinds .acp-guide-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 960px) {
	.acp-blinds .acp-guide-grid { grid-template-columns: 1fr; }
}
/* === END acp-guide card fix 2026-09-17 =================================== */

/* === START acp-cfg image widget crop fix 2026-09-17 ======================
   The block above takes `.acp-media` and `.acp-ph` out of flow so a portrait
   source crops to the band instead of setting its height. A CONVERTED page
   holds the photograph in an Elementor image widget instead, which only ever
   received `height: 100%` here, so it stayed in normal flow.

   Found placing cork's two green CTA photographs (sweep row 3): both sources
   are 1333x2000 portrait and drove the band to 711px against the frame's 365.
   Exactly the failure the note above describes, one selector short.
   ========================================================================= */

.acp-cfg .acp-cfg-split-media .elementor-widget-image {
	position: absolute;
	inset: 0;
}
/* === END acp-cfg image widget crop fix 2026-09-17 ======================== */

/* Preview-layout responsive: one column below the card's own breakpoint. */
@media (max-width: 700px) {
	.acp-formhost .gform_fields { grid-template-columns: 1fr; }
}
