/*
 * hwd-carousel.css  —  styles for the theme's single carousel engine
 * ===========================================================================
 * Pairs with js/hwd-carousel.js. Read that file's header first: it documents
 * the markup contract, the data-* behaviour attributes, the caption variant
 * classes and the public init API.
 *
 * STRUCTURE OF THIS FILE
 *   1. Engine       — viewport, track, slides, fade mode. Every carousel.
 *   2. Navigation   — arrows and dots. Every carousel.
 *   3. Variants     — cap-none / right / below / hover / overlay / side,
 *                     plus the one navigation variant, nav-outside.
 *   4. Site uses    — the few per-placement overrides that genuinely differ.
 *
 * Anything not in section 4 should be true of EVERY carousel on the site. If
 * a change only suits one placement, it belongs in section 4, or in that
 * page's own stylesheet — not in sections 1-3.
 *
 * THE ARTIST BASE'S COPY IS CANONICAL. Sections 1-3 are byte-identical to it
 * apart from the LEGACY selectors in the gallery-source block, which are
 * HWD-only. Section 4 is entirely HWD's own. Make an engine change in the
 * artist base first, then bring it across, so the diff stays down to those
 * two parts. (Sections 1-3 gained fade mode, the cap-overlay and cap-side
 * variants and the reduced-motion fade rule on 2026-08-12, back-ported from
 * the base along with the JS. All are opt-in: no carousel on this site takes
 * any of them, so nothing here changed.)
 *
 * --- TUNABLE SETTINGS ------------------------------------------------------
 *   --hwdc-arrow-color / --hwdc-arrow-bg   chevron colour and button backing
 *   --hwdc-arrow-hover / --hwdc-arrow-bg-hover   the same two on hover
 *   --hwdc-dot-color / --hwdc-dot-active   dot nav colours
 *   --hwdc-panel-rgb + the two alpha values  cap-right panel colour/opacity
 *   --hwdc-transition                      slide animation
 *   --hwdc-fade                            fade-mode crossfade duration
 *   --hwdc-side-split                      cap-side column ratio
 *   --hwdc-nav-gap                         nav-outside arrow/image gap
 * Set any of them on .hwd-carousel, or on one variant, to retune.
 *
 * The 768px breakpoint used for cap-right must stay in sync with
 * CAP_RIGHT_BREAKPOINT in hwd-carousel.js.
 * -------------------------------------------------------------------------
 */

/* ==========================================================================
   1. ENGINE
   ========================================================================== */

.hwd-carousel {
	--hwdc-gap: 0px;                  /* set inline by the JS from data-gap */
	--hwdc-show: 1;                   /* set inline by the JS, responsive */
	--hwdc-slide-w: calc((100% - var(--hwdc-show) * var(--hwdc-gap)) / var(--hwdc-show));
	--hwdc-transition: transform 0.45s ease;
	--hwdc-fade: 1.2s;

	/* Arrows default to a white chevron on a dark semi-opaque box. This was
	   cap-right's own treatment until 2026-08-17, when it moved down here:
	   every carousel that overlays its arrows on a slide needs it, and the
	   bare grey chevron it replaced disappeared over a dark image. A carousel
	   whose arrows sit OUTSIDE the slide instead — nav-outside, and the
	   testimonial placements in section 4 — sets the two backing values back
	   to transparent and takes a dark chevron, since on the page ground there
	   is nothing for the box to earn its place against. */
	--hwdc-arrow-color: #fff;
	--hwdc-arrow-hover: #fff;
	--hwdc-arrow-bg: rgba(0, 0, 0, 0.35);
	--hwdc-arrow-bg-hover: rgba(0, 0, 0, 0.6);
	--hwdc-dot-color: #999;
	--hwdc-dot-active: #333;

	position: relative;
	box-sizing: border-box;
}

/* Before the JS runs the slides are still plain stacked children. Hide them
   to avoid a flash of the unbuilt layout; .hwdc-ready is added at build. */
.hwd-carousel:not(.hwdc-ready) {
	visibility: hidden;
}

/* The stage is the same box as the viewport but does not clip, so arrows can
   be positioned outside the slide area. Arrows are positioned against this. */
.hwdc-stage {
	position: relative;
	width: 100%;
}

.hwdc-viewport {
	position: relative;
	width: 100%;
	overflow: hidden;
}

.hwdc-track {
	display: flex;
	width: 100%;
	transition: var(--hwdc-transition);
	will-change: transform;
}

.hwdc-slide {
	position: relative;
	box-sizing: border-box;
	flex: 0 0 var(--hwdc-slide-w);
	max-width: var(--hwdc-slide-w);
	margin-right: var(--hwdc-gap);
}

/* Used by the gallery source adapter; harmless elsewhere. */
.hwdc-imgwrap {
	position: relative;
	width: 100%;
	line-height: 0;
}

.hwdc-imgwrap img {
	display: block;
	width: 100%;
	height: auto;
	margin: 0;
}

/* --- Fade mode (data-mode="fade") ----------------------------------------
   Every slide occupies the SAME grid cell, so they stack without absolute
   positioning and the track keeps an intrinsic height — the height of the
   tallest slide. That is the whole reason for grid here rather than the
   obvious `position: absolute; inset: 0`: absolute slides are out of flow, so
   the viewport would collapse to nothing and every fade carousel would need
   its height hardcoded. Only the hero actually wants a fixed height, and it
   sets one in home.css.

   .is-visible is applied by the JS. Non-visible slides stay in the layout at
   zero opacity, so they must not be clickable or reachable by tab.

   THE HEIGHT CHAIN. The three wrappers take height: 100% here and ONLY here.
   A fade carousel is often given a fixed height by its placement — the hero is
   100svh, .image-container is min(800px, 70vh) — and the slides then have to
   be able to fill it. The hero's slides make that non-negotiable: they are
   empty divs carrying nothing but a background image, so with an auto-height
   chain the grid row measures zero and the whole hero collapses. Scoped to
   fade mode deliberately: in slide mode with data-auto-height the JS writes an
   explicit pixel height onto the viewport, and a track at height: 100% of that
   would clip instead of following the slides. */
.hwd-carousel.hwdc-fade .hwdc-stage,
.hwd-carousel.hwdc-fade .hwdc-viewport {
	height: 100%;
}

.hwd-carousel.hwdc-fade .hwdc-track {
	display: grid;
	height: 100%;
	transition: none;         /* nothing translates in fade mode */
	will-change: auto;
}

.hwd-carousel.hwdc-fade .hwdc-slide {
	grid-area: 1 / 1;
	width: 100%;
	max-width: 100%;
	margin-right: 0;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity var(--hwdc-fade) ease-in-out, visibility 0s linear var(--hwdc-fade);
}

.hwd-carousel.hwdc-fade .hwdc-slide.is-visible {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
	transition: opacity var(--hwdc-fade) ease-in-out, visibility 0s linear 0s;
}

/* --- Gallery source ------------------------------------------------------
   When the slides come from a WP block gallery, the block's own grid and
   figure spacing have to be neutralised before the engine's layout can take.
   To use: on the Gallery block, Advanced > Additional CSS class(es), add
   `hwd-carousel` plus a caption variant, eg `hwd-carousel cap-right`.

   LEGACY — HWD-ONLY, no counterpart in the artist base:
   gallerycarousel1col / gallerycarousel3col are the retired pre-engine gallery
   classes, aliased to `hwd-carousel cap-none` by the JS. They still sit in post
   content across the blog. The alias is applied at runtime, so these selectors
   must name the old classes directly — otherwise the pre-init hide rule would
   not apply until after the JS had run, which is exactly the flash of raw grid
   it exists to prevent. */
.wp-block-gallery.hwd-carousel,
.wp-block-gallery.gallerycarousel1col,
.wp-block-gallery.gallerycarousel3col {
	display: block !important;    /* override the block gallery's grid */
	box-sizing: border-box;
	margin: 0 auto 12px;          /* centre like the body paragraphs */
	max-width: 100%;
}

.wp-block-gallery.hwd-carousel figure,
.wp-block-gallery.hwd-carousel figure.wp-block-image,
.wp-block-gallery.gallerycarousel1col figure,
.wp-block-gallery.gallerycarousel3col figure {
	margin: 0 !important;
	width: auto;
}

.wp-block-gallery.gallerycarousel1col:not(.hwdc-ready),
.wp-block-gallery.gallerycarousel3col:not(.hwdc-ready) {
	visibility: hidden;
}

/* --- Auto height (data-auto-height="true") -------------------------------
   Without this the viewport is as tall as the tallest slide in the whole set,
   because that is how a flex row sizes — so one long thumbnail leaves dead
   space beneath every other slide. With it, the JS sets an explicit viewport
   height from the slides currently on screen and animates between values.
   `align-items: flex-start` stops the shorter slides stretching to match the
   tallest, which is what makes the measurement meaningful. */
.hwd-carousel.has-auto-height .hwdc-track {
	align-items: flex-start;
}

.hwd-carousel.has-auto-height .hwdc-viewport {
	transition: height 0.45s ease;
}

@media (prefers-reduced-motion: reduce) {
	.hwdc-track { transition: none; }
	.hwd-carousel.has-auto-height .hwdc-viewport { transition: none; }
	/* The JS already declines to autoplay under this preference; this covers
	   the crossfade on a manual advance. */
	.hwd-carousel.hwdc-fade .hwdc-slide { transition: none; }
}

/* ==========================================================================
   2. NAVIGATION
   The JS always builds arrows and dots (unless data-arrows/data-dots="false")
   and leaves it to CSS to decide what is visible at what width. That is why a
   carousel can show arrows on desktop and dots on mobile with no JS config.
   ========================================================================== */

.hwdc-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 35px;
	height: 45px;
	padding: 5px 3px;
	border: 0;
	cursor: pointer;
	background: var(--hwdc-arrow-bg);
	color: var(--hwdc-arrow-color);
	transition: color 0.2s ease, opacity 0.2s ease;
}

.hwdc-arrow:hover {
	color: var(--hwdc-arrow-hover);
	background: var(--hwdc-arrow-bg-hover);
}
.hwdc-prev { left: 0; }
.hwdc-next { right: 0; }

/* Chevron paths are inlined by the JS rather than referenced from a sprite
   with <use> — a <use> shadow DOM blocks this stroke rule from reaching them. */
.hwdc-arrow svg {
	width: 100%;
	height: 100%;
	fill: none;
	stroke: currentColor;
	stroke-width: 2px;
	stroke-miterlimit: 10;
}

.hwdc-arrow[disabled] {
	opacity: 0.25;
	cursor: default;
}

.hwdc-dots {
	display: flex;
	justify-content: center;
	gap: 10px;
	margin: 0.9rem 0;
	padding: 12px;
}

.hwdc-dots:empty { display: none; }

.hwdc-dot {
	width: 10px;
	height: 10px;
	padding: 0;
	border: 1px solid var(--hwdc-dot-color);
	border-radius: 50%;
	background: transparent;
	cursor: pointer;
	transition: background 0.2s ease, border-color 0.2s ease;
}

.hwdc-dot.is-active {
	background: var(--hwdc-dot-active);
	border-color: var(--hwdc-dot-active);
}

/* Everything fits on screen — nothing to navigate to. */
.hwd-carousel.hwdc-static .hwdc-arrow,
.hwd-carousel.hwdc-static .hwdc-dots { display: none; }

/* ==========================================================================
   3. CAPTION VARIANTS
   Independent of slide count and of fade/slide mode — combine any variant
   with any data-show and either mode.
   ========================================================================== */

/* --- cap-none: the default. Nothing to do. ------------------------------- */
.hwd-carousel.cap-none .hwdc-caption { display: none; }

/* --- cap-right ----------------------------------------------------------
   Caption in a panel overlaid on the right of the image on wide screens,
   dropping below the image at 768px. Font-size is set inline by the JS from
   the caption's character count; the rule here is only a fallback. */
.hwd-carousel.cap-right {
	--hwdc-panel-rgb: 22, 32, 28;
	--hwdc-panel-alpha-mid: 0.82;
	--hwdc-panel-alpha-edge: 0.55;
	--hwdc-panel-color: #fff;
	/* The three arrow values that used to sit here — white chevron, white on
	   hover, dark backing — became the engine default in section 1 on
	   2026-08-17 and were removed rather than restated. What is left below is
	   the part that is still peculiar to cap-right: a larger button holding a
	   smaller chevron, for a one-up image at full column width. */
}

.hwd-carousel.cap-right .hwdc-imgwrap img {
	border: 1px solid #ccc;
}

.hwd-carousel.cap-right .hwdc-arrow {
	width: 44px;
	height: 60px;
	padding: 0;
}

.hwd-carousel.cap-right .hwdc-arrow svg {
	width: 16px;
	height: 30px;
}

.hwd-carousel.cap-right .hwdc-caption {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	display: flex;
	align-items: center;
	justify-content: flex-start;
	box-sizing: border-box;
	padding: clamp(1rem, 2.5vw, 2.25rem);
	/* Vertical gradient — full opacity through the centre, fading at top and
	   bottom so more of the image shows through there. For a flat band across
	   the middle, move the mid stops in from 50% (eg 35% and 65%). */
	background: linear-gradient(
		to bottom,
		rgba(var(--hwdc-panel-rgb), var(--hwdc-panel-alpha-edge)) 0%,
		rgba(var(--hwdc-panel-rgb), var(--hwdc-panel-alpha-mid)) 50%,
		rgba(var(--hwdc-panel-rgb), var(--hwdc-panel-alpha-edge)) 100%
	);
	color: var(--hwdc-panel-color);
	overflow: hidden;
}

.hwd-carousel.cap-right .hwdc-caption-inner {
	width: 100%;
	line-height: 1.3;
	overflow-wrap: break-word;
	font-size: 1rem;
}

@media (min-width: 769px) {
	.hwd-carousel.cap-right .hwdc-caption { width: 32%; }
	/* Tidier ragging, but only in the narrow overlay panel — on mobile the
	   full-width panel wants the greedy default so the text fills the line. */
	.hwd-carousel.cap-right .hwdc-caption-inner { text-wrap: balance; }
}

@media (max-width: 768px) {
	.hwd-carousel.cap-right {
		--hwdc-panel-alpha-edge: 0.82;   /* flat, no gradient, below the image */
	}
	.hwd-carousel.cap-right .hwdc-caption {
		position: static;
		width: 100%;
		align-items: flex-start;
		padding: 1rem 1.1rem;
	}
	.hwd-carousel.cap-right .hwdc-caption-inner {
		font-size: 1rem !important;      /* JS clears its inline size here */
	}
	.hwd-carousel.cap-right .hwdc-arrow { width: 38px; height: 50px; }
}

/* --- cap-below: caption always under the image, in flow ------------------ */
.hwd-carousel.cap-below .hwdc-slide {
	display: flex;
	flex-direction: column;
}

.hwd-carousel.cap-below .hwdc-caption {
	padding: 0.9rem 0 0;
	font-size: 0.95rem;
	line-height: 1.45;
}

/* --- cap-hover: caption revealed as an overlay on hover ------------------
   The overlay sizes to the slide's link (or the slide itself if there is no
   link) so it matches the image exactly, independent of any slide padding. */
.hwd-carousel.cap-hover {
	--hwdc-hover-bg: rgba(0, 15, 15, 0.93);
	--hwdc-hover-color: #fff;
}

.hwd-carousel.cap-hover .hwdc-slide a {
	display: block;
	position: relative;
}

.hwd-carousel.cap-hover .hwdc-caption {
	position: absolute;
	top: 50%;
	left: 0;
	right: 0;
	transform: translateY(-50%);
	box-sizing: border-box;
	padding: 34px 30px 22px;
	background: var(--hwdc-hover-bg);
	border: 1px solid #999;
	color: var(--hwdc-hover-color);
	opacity: 0;
	transition: opacity 0.3s ease;
	pointer-events: none;
}

.hwd-carousel.cap-hover .hwdc-slide a:hover .hwdc-caption,
.hwd-carousel.cap-hover .hwdc-slide:hover .hwdc-caption {
	opacity: 1;
}

.hwd-carousel.cap-hover .hwdc-caption p {
	margin: 0 auto 12px;
	font-size: 0.8em;
	line-height: 1.6;
	color: inherit;
}

/* --- cap-overlay: caption always visible, positioned over the image -------
   Placed with data-cap-pos on the container: a vertical word, a hyphen and a
   horizontal word, eg data-cap-pos="bottom-left". Defaults to bottom-centre
   when the attribute is absent or unrecognised.

   Built as a full-cover flex box whose alignment moves the panel, rather than
   as an absolutely positioned panel with nine sets of top/left values. The
   flex version is nine one-line rules instead of nine three-line ones, and the
   panel keeps shrink-to-fit sizing in every position. .hwdc-caption-inner is
   the visible panel here; .hwdc-caption is only the positioning frame, so it
   must not paint or catch clicks. */
.hwd-carousel.cap-overlay {
	--hwdc-overlay-bg: rgba(0, 0, 0, 0.55);
	--hwdc-overlay-color: #fff;
	--hwdc-overlay-inset: 1.25rem;
}

.hwd-carousel.cap-overlay .hwdc-caption {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: flex;
	align-items: flex-end;        /* default: bottom … */
	justify-content: center;      /* … centre */
	box-sizing: border-box;
	padding: var(--hwdc-overlay-inset);
	pointer-events: none;
}

.hwd-carousel.cap-overlay .hwdc-caption-inner {
	max-width: 100%;
	padding: 0.7em 1em;
	background: var(--hwdc-overlay-bg);
	color: var(--hwdc-overlay-color);
	font-size: 0.95rem;
	line-height: 1.45;
	pointer-events: auto;
}

.hwd-carousel.cap-overlay[data-cap-pos^="top"]    .hwdc-caption { align-items: flex-start; }
.hwd-carousel.cap-overlay[data-cap-pos^="center"] .hwdc-caption { align-items: center; }
.hwd-carousel.cap-overlay[data-cap-pos^="bottom"] .hwdc-caption { align-items: flex-end; }

.hwd-carousel.cap-overlay[data-cap-pos$="-left"]   .hwdc-caption { justify-content: flex-start; }
.hwd-carousel.cap-overlay[data-cap-pos$="-center"] .hwdc-caption { justify-content: center; }
.hwd-carousel.cap-overlay[data-cap-pos$="-right"]  .hwdc-caption { justify-content: flex-end; }

/* --- cap-side: two-column slide, image left and caption right ------------
   In flow, not overlaid — this is the variant for a slide that is as much
   text as picture. Stacks below 768px, image first. Retune the ratio with
   --hwdc-side-split, eg `--hwdc-side-split: 2fr 1fr` for a wider image.

   Grid rather than flex so the two columns are set by the ratio alone and
   neither can be pushed out of it by a long unbroken word in the caption. */
.hwd-carousel.cap-side {
	--hwdc-side-split: 1fr 1fr;
	--hwdc-side-gap: clamp(1rem, 3vw, 2.5rem);
}

.hwd-carousel.cap-side .hwdc-slide {
	display: grid;
	grid-template-columns: var(--hwdc-side-split);
	align-items: center;
	gap: var(--hwdc-side-gap);
}

.hwd-carousel.cap-side .hwdc-caption {
	font-size: 1rem;
	line-height: 1.5;
}

@media (max-width: 768px) {
	.hwd-carousel.cap-side .hwdc-slide {
		grid-template-columns: 1fr;
		gap: 1rem;
	}
}

/* --- nav-outside: arrows clear of the slide area, not over it ------------
   The one NAVIGATION variant, opt-in and independent of the caption variant,
   so it is added alongside one: `hwd-carousel cap-none nav-outside`. By
   default an arrow sits at left/right 0, ie over the first and last slide,
   which leaves it invisible against a dark image. This moves it outside.
   Possible at all because the arrows hang off .hwdc-stage, which does not
   clip — see section 1.

   IT LIVES AT THE FOOT OF SECTION 3, NOT IN SECTION 2, AND MUST STAY LAST.
   cap-right resizes its arrows, and any cap-* variant may; those rules are
   the same specificity as these (0,3,0), so source order is what lets a
   nav-outside carousel keep its own sizing on a narrow screen. Section 4 is
   per-placement and is still free to override it, which is correct.

   The shift is a transform rather than a negative left/right so that it is
   independent of the arrow's width: `translate(-100%)` is exactly one arrow
   out whatever the arrow measures, where a `left: -50px` would have to be
   recomputed for every variant and placement that resizes it.

   ONLY FOR A CAROUSEL THAT HAS SIDE MARGIN. The arrows are now outside the
   carousel box, so on a full-bleed carousel they would land off-screen. Below
   851px the arrow width and the gap are sized in vw and sum to 4vw — exactly
   .wrapper's side padding in global.css — so even at the narrowest widths,
   where the carousel fills its container, they stay on screen. Keep that sum
   at 4vw if these values are retuned. */
.hwd-carousel.nav-outside {
	--hwdc-nav-gap: 15px;

	/* Chrome off. The engine default puts a white chevron on a dark box so it
	   stays legible over a slide; out here there is no slide behind it, so the
	   box would be decoration sitting on the page ground. Set after the cap-*
	   variants at the same specificity, so a cap-right carousel that also
	   takes nav-outside loses the backing too — which is the intended reading:
	   the backing belongs to arrows that overlay an image, not to cap-right. */
	--hwdc-arrow-color: #666;
	--hwdc-arrow-hover: #000;
	--hwdc-arrow-bg: transparent;
	--hwdc-arrow-bg-hover: transparent;
}

.hwd-carousel.nav-outside .hwdc-prev {
	left: 0;
	transform: translate(calc(-100% - var(--hwdc-nav-gap)), -50%);
}

.hwd-carousel.nav-outside .hwdc-next {
	right: 0;
	transform: translate(calc(100% + var(--hwdc-nav-gap)), -50%);
}

@media (max-width: 850px) {
	.hwd-carousel.nav-outside {
		--hwdc-nav-gap: min(1vw, 6px);
	}

	.hwd-carousel.nav-outside .hwdc-arrow {
		width: min(3vw, 24px);
		height: min(4.5vw, 34px);
		padding: 0;
	}
}

/* ==========================================================================
   4. SITE USES — per-placement overrides only
   HWD-ONLY. Nothing in this section has a counterpart in the artist base,
   which has its own § 4 for its own placements.
   ========================================================================== */

/* Blog posts — "More topics to explore" related-post cards (.blogsByTag).
   Three cards maximum, so above 768px they all show and the engine adds
   .hwdc-static, hiding the nav. Only the 1-up mobile view has arrows, and
   there they sit over the card thumbnail.

   NOTHING IS NEEDED HERE ANY MORE. This block used to carry
   `background: rgba(255, 255, 255, 0.75)` — a light backing so the chevron
   stayed legible against any thumbnail. On 2026-08-17 that same problem was
   solved engine-wide the other way round, with a white chevron on a dark box
   as the section 1 default, so the rule was removed rather than left to fight
   it: a white chevron on a white backing would have been invisible, which is
   the exact fault the change was made to cure. */

/* Portfolio category and tag archives — "What Clients Say" testimonials
   (section.testimonials > .container > .centerslide). One testimonial at a
   time, no dots, arrows outside the text column. The arrows can sit outside
   because they hang off .hwdc-stage, which does not clip; -25px matches where
   Slick's default arrow CSS put them. Colours match the theme's old .chevrons
   rule in style.css.

   The two transparent values are what opt this placement out of the engine's
   default arrow backing (section 1, 2026-08-17). The backing is for a chevron
   overlaid on a slide; these arrows are outside the text column on the pale
   section ground, where a dark box would be decoration. The same reasoning
   sets the same two values on nav-outside. Inherited by .testimonialCards
   below, which overrides only the colours. */
section.testimonials .hwd-carousel {
	--hwdc-arrow-color: #666;
	--hwdc-arrow-hover: #000;
	--hwdc-arrow-bg: transparent;
	--hwdc-arrow-bg-hover: transparent;
}

section.testimonials .hwd-carousel .hwdc-prev { left: -25px; }
section.testimonials .hwd-carousel .hwdc-next { right: -25px; }

@media only screen and (max-width: 768px) {
	/* Was `section.testimonials .slick-prev/.slick-next { top: 40% !important }`
	   in testimonials.css — the quote runs tall on a narrow screen, so vertical
	   centre sits too low. No !important needed here: this selector already
	   outranks the base .hwdc-arrow rule. */
	section.testimonials .hwd-carousel .hwdc-arrow { top: 40%; }
}

/* Homepage "What Clients Say" — the four hardcoded cards (.testimonialCards in
   page-home.php), folded onto the engine 2026-08-11 from a hand-rolled script.
   It shares section#testimonials with the archive carousel above, so the two
   rules above apply to it too and are overridden here where it differs.

   MUST STAY BELOW the block above, including its media query: these selectors
   are the same specificity (0,3,1), so source order is what decides. That is
   deliberate rather than reached for with an ID — it keeps the whole testimonial
   group at one specificity level and readable top to bottom.

   Differences from the archives, all of them carried over verbatim from the
   retired .tCarousel-* rules so the arrows land where they always have:
     • -2.5% side offsets rather than -25px. Both put the arrow outside the
       card window (possible at all because arrows hang off .hwdc-stage, which
       does not clip); this one is proportional because .testimonialCards is
       the full wrapper width rather than the narrower text column.
     • 35% vertical, at EVERY width — the 768px rule above does not apply. The
       cards are equal height with the author line pinned to the foot, so the
       chevron reads best a little above centre whatever the slide count.
     • #555 at 0.55 opacity, going to full on hover, rather than a colour
       change. Opacity is used rather than a lighter grey because the section
       sits on a pale blue ground (#f0f7f8) that a flat hex would have to be
       recomputed against. The disabled step is set explicitly, since this
       selector outranks the base .hwdc-arrow[disabled] rule in section 2. */
section.testimonials .hwd-carousel.testimonialCards {
	--hwdc-arrow-color: #555;
	--hwdc-arrow-hover: #555;
}

section.testimonials .hwd-carousel.testimonialCards .hwdc-arrow {
	top: 35%;
	opacity: 0.55;
}

section.testimonials .hwd-carousel.testimonialCards .hwdc-arrow:hover {
	opacity: 1;
}

section.testimonials .hwd-carousel.testimonialCards .hwdc-arrow[disabled] {
	opacity: 0.18;
}

section.testimonials .hwd-carousel.testimonialCards .hwdc-prev { left: -2.5%; }
section.testimonials .hwd-carousel.testimonialCards .hwdc-next { right: -2.5%; }

/* Art Archiving (and any other single-service page): widen the caption
   carousel beyond the site-wide `figure` cap. That cap is a bare tag rule in
   css/global.css (`figure { width: min(42rem, 100%) }`, ~line 225); a
   three-class selector beats it on specificity, so no !important is needed.
   The `max-width: 100%` above still holds it in on narrow screens. */
.page-template-page-single-service .wp-block-gallery.hwd-carousel {
	width: min(56rem, 100%);
	margin: 36px auto;
}

/* Homepage "Recent Projects" (section.recentProjects > .recentProjectsCarousel).
   Replaced the Sample Websites carousel on 2026-09-20 (RHM). One project per
   slide; the slide's own layout and the image window are in css/home.css under
   HOMEPAGE RECENT PROJECTS CAROUSEL.

   ARROWS ONLY, AT EVERY WIDTH (RHM, 2026-09-20). The dots are switched off at
   the source with `data-dots="false"` in page-home.php, so nothing is built and
   no rule here has to hide them — which matters, because a bare `.hwdc-dots`
   rule reaches every carousel on the site.

   The -4% offsets put the arrows out in .wrapper's own side padding, clear of
   the slide at both the two-column and the stacked widths. Out there they are
   over the page ground rather than over a slide, which by the rule in
   `_websites-context.md` is the case for transparent backing and a dark chevron
   rather than the engine's default white-on-dark box — left as the default for
   now at RHM's sight of it; the two lines to change are commented below. */
.recentProjectsCarousel { padding-top: 20px; }

/*
.recentProjectsCarousel {
	--hwdc-arrow-color: #666;
	--hwdc-arrow-hover: #000;
	--hwdc-arrow-bg: transparent;
	--hwdc-arrow-bg-hover: transparent;
}
*/

.recentProjectsCarousel .hwdc-prev { left: -4%; }
.recentProjectsCarousel .hwdc-next { right: -4%; }
