/* ==========================================================================
   ART CENTRRAL — the premium layer
   ==========================================================================

   THE IDEA
   --------
   ART CENTRRAL sells light. Illuminated boards, backlit letters, neon, light
   boxes — the product only exists once it is switched on, and it is at its best
   after dark. A site that is white from top to bottom is the worst possible
   room to show that work in.

   So the page now runs a dark spine through it: the hero, the portfolio and the
   closing call to action are cinematic and dark, and the reading sections stay
   light between them. The work glows because there is something for it to glow
   against, and the light sections feel like relief rather than default.

   Everything here sits on top of ac-layout / ac-components. It changes the
   staging, not the structure — the page still edits normally in Elementor.
   ========================================================================== */

:root {
	--ac-night:      #0A0B0C;
	--ac-night-2:    #131417;
	--ac-glow:       #FFB38A;
	/*
	 * The hero is one screen, not "at least" one screen.
	 *
	 * It was min-height only, so tall content simply pushed past the fold and
	 * the two calls to action ended up below it — the one thing in the hero
	 * that has a job to do was the first thing cut off. svh rather than vh so
	 * a phone's collapsing address bar does not change the answer mid-scroll.
	 */
	--ac-hero-h: min(100svh, 900px);
}

/*
 * Anchor landings clear the fixed header.
 *
 * The smooth-scroll layer used to handle this by scrolling to the target
 * minus 90px. With it gone the browser does the scrolling, so the offset has
 * to be declared here or a jumped-to heading lands underneath the header.
 * scroll-behavior is deliberately left alone: the jump is instant, which is
 * what the browser does everywhere else.
 */
html { scroll-padding-top: 96px; }

/* ==========================================================================
   1. GRAIN
   ==========================================================================
   Large flat areas of near-black band badly on cheap panels and look plasticky
   on good ones. A very fine noise layer breaks the gradient up and is most of
   why a dark section reads as photographed rather than filled. */

.ac-night-surface { position: relative; isolation: isolate; }

.ac-night-surface::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;

	/*
	 * Painted flat, not blended.
	 *
	 * mix-blend-mode: overlay made the compositor read back everything behind
	 * this layer and re-blend it on every frame. Across the hero, the services
	 * band, the work rail and the closing band that came to more than four
	 * screens of blended surface, and it showed up as jitter while scrolling.
	 *
	 * On a near-black ground, overlay-blending grey noise and simply painting
	 * that noise at a low opacity look almost the same. The opacity is lower
	 * here because nothing is amplifying it any more.
	 */
	opacity: .055;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
	background-size: 160px 160px;
}

/* Content has to out-rank the grain, or the grain sits over the type. */
.ac-night-surface > * { position: relative; z-index: 1; }

/* ==========================================================================
   1b. THE HEADER OVER THE HERO
   ==========================================================================
   On a page that opens with the cinematic hero the header floats over the
   photograph and only becomes a solid bar once the page has moved. Two things
   have to change with it: the navigation goes white, and the logo swaps.

   The supplied logo is black artwork on a pale ground, so the horizontal
   lockup vanishes on a dark hero. The round badge carries its own pale disc
   and reads on anything — so the badge shows while the header is transparent
   and the lockup returns when it is not. That is a swap between two assets the
   client supplied, not a recolour of their artwork. */

.ac-logo-badge { display: none; }

body.ac-cine .e-con.ac-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	background: transparent;
	border-bottom-color: transparent;
	transition: background .45s var(--ac-ease), border-color .45s var(--ac-ease);
}

/* A soft scrim so the navigation stays legible over a bright patch of the
   photograph without the header reading as a filled bar. */
body.ac-cine .e-con.ac-header::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background: linear-gradient(to bottom, rgba(10, 11, 12, .72), transparent);
	transition: opacity .45s var(--ac-ease);
}

body.ac-cine .ac-header:not(.ac-stuck) .ac-logo-lockup { display: none; }
body.ac-cine .ac-header:not(.ac-stuck) .ac-logo-badge { display: block; }
body.ac-cine .ac-header:not(.ac-stuck) .ac-logo-badge img { max-height: 54px; width: auto; }

/* Desktop only, and that qualifier is the whole point.

   Over a dark hero the inline nav has to be white. Below 1024 there is no
   inline nav — the items live in a white dropdown panel — and this rule was
   still reaching them at (0,5,2), beating the panel's own colour at (0,4,1).
   Every item in the open mobile menu was white on white: the separators
   drew, the text did not, and the menu looked like six empty rows. */
@media (min-width: 1024px) {
	body.ac-cine .ac-header:not(.ac-stuck) .hfe-nav-menu a.hfe-menu-item {
		color: rgba(255, 255, 255, .88);
	}
	body.ac-cine .ac-header:not(.ac-stuck) .hfe-nav-menu a.hfe-menu-item:hover { color: #fff; }
}
/* Elementor writes per-widget CSS keyed to the element id
   (.elementor-element-xxxx .elementor-button), which outranks any class-based
   selector the theme can write. This is one of the few places !important is
   the correct tool rather than a shortcut. */
/*
 * Over the hero the outline button is an outline — a line and a label, no
 * fill. It used to carry 8% white behind a 34% border, which on near-black is
 * not enough to be a surface and too much to be nothing: it read as a box
 * somebody had forgotten to finish, sitting next to a solid orange button that
 * had clearly been finished. A crisper line at 46% and no fill states what it
 * is. The fill arrives on hover, where a change is the point.
 *
 * fill, not just color, on the icon — see the note in ac-layout.css.
 */
body.ac-cine .ac-header:not(.ac-stuck) .ac-btn-outline .elementor-button {
	color: #fff !important;
	background-color: transparent !important;
	border-color: rgba(255, 255, 255, .46) !important;
}
body.ac-cine .ac-header:not(.ac-stuck) .ac-btn-outline .elementor-button:hover {
	background-color: rgba(255, 255, 255, .14) !important;
	border-color: #fff !important;
}
body.ac-cine .ac-header:not(.ac-stuck) .ac-btn-outline .elementor-button svg,
body.ac-cine .ac-header:not(.ac-stuck) .ac-btn-outline .elementor-button i {
	color: #fff !important;
	fill: #fff !important;
}
/*
 * The menu toggle, same story as the phone icon.
 *
 * color: #fff was already here and did nothing visible, because the burger is
 * an inline SVG that HFE paints with an explicit black fill — so the one
 * control a phone visitor needs was a black icon on a near-black header. It
 * was legible only as a faint shape against the hero photograph.
 */
body.ac-cine .ac-header:not(.ac-stuck) .hfe-nav-menu__toggle,
body.ac-cine .ac-header:not(.ac-stuck) .hfe-nav-menu-icon { color: #fff; }
body.ac-cine .ac-header:not(.ac-stuck) .hfe-nav-menu__toggle svg { fill: #fff !important; }

/* Once it sticks it is the ordinary solid bar again. */
body.ac-cine .ac-header.ac-stuck {
	/*
	 * Opaque, with no backdrop-filter.
	 *
	 * A full-width fixed bar blurring everything scrolling underneath it is
	 * the most reliable way to make a page stutter, and at 96% opacity the
	 * blur was doing almost nothing that could be seen. Solid white costs
	 * nothing and looks the same.
	 */
	background: #fff;
	border-bottom-color: var(--ac-border);
}
body.ac-cine .ac-header.ac-stuck::before { opacity: 0; }

/* ==========================================================================
   2. THE HERO
   ==========================================================================
   Full bleed, dark, with the photograph pushed right and faded into the ground
   so the headline sits on black rather than on a busy picture. The scrim is a
   gradient rather than a flat overlay: flatten a night photograph with 60%
   black and the light in it — the only interesting thing in the frame — goes
   with it. */

.e-con.ac-hero-cine {
	position: relative;
	overflow: clip;
	min-height: var(--ac-hero-h);
	background: var(--ac-night);
	color: rgba(255, 255, 255, .74);
	--padding-top: 0px; --padding-bottom: 0px;
	--padding-left: 0px; --padding-right: 0px;
	--justify-content: center;
	isolation: isolate;
}

.e-con.ac-hero-bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	/* This is the element that is scaled and parallaxed, so the compositor
	   hint belongs here rather than on each slide. */
	will-change: transform;
	--padding-top: 0px; --padding-bottom: 0px;
	--padding-left: 0px; --padding-right: 0px;
	--width: 100%;
	pointer-events: none;
}

.ac-hero-bg .ac-media,
.ac-hero-bg .elementor-widget-container,
.ac-hero-bg .elementor-image,
.ac-hero-bg figure { height: 100%; }

/* ---- the slideshow ------------------------------------------------------
   Every slide occupies the same box; only the active one is opaque. The
   cross-fade is opacity on a stacked layer, which the compositor handles on
   its own — the same reason the power-on veil is a sheet rather than a filter.
   ------------------------------------------------------------------------ */
.ac-hero-bg .ac-hero-slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	/* No transition here: GSAP drives the cross-fade, and a CSS transition on
	   the same property would fight it. This is only the resting state. */
}
.ac-hero-bg .ac-hero-slide.is-active { opacity: 1; }

/* Before the script runs — or if it never does — slide one is the hero. */
.ac-hero-bg .ac-hero-slide:first-child { opacity: 1; }

.ac-hero-bg img,
.ac-hero-bg .ac-shot {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 62% 50%;
	border-radius: 0;
	box-shadow: none;
	transform-origin: 60% 50%;

	/*
	 * No filter here on purpose.
	 *
	 * This image is about 136% of the viewport and is both scaled on load and
	 * parallaxed on scroll. A filter on a layer that is being transformed
	 * forces it to be re-rasterised every frame instead of just moved by the
	 * compositor, and the saturate/contrast nudge it carried was too small to
	 * be worth that. The brightness ramp is done with an overlay's opacity
	 * instead — see .ac-hero-veil.
	 */
}

/* The "power on": a black sheet over the photograph whose opacity is animated.
   Opacity on a solid layer is compositor-only, where animating the image's own
   brightness filter is not. */
.ac-hero-veil {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: #000;
	opacity: 0;
}

/* Two scrims. The first lays the headline's ground in from the left, the
   second seats the whole frame so it does not float against the next section. */
.ac-hero-cine::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background:
		linear-gradient(100deg,
			var(--ac-night) 0%,
			rgba(10, 11, 12, .96) 26%,
			rgba(10, 11, 12, .72) 46%,
			rgba(10, 11, 12, .34) 70%,
			rgba(10, 11, 12, .52) 100%),
		linear-gradient(to top, rgba(10, 11, 12, .92) 0%, transparent 34%);
}

/* .ac-wrap.ac-bare zeroes container padding at a higher specificity than
   .e-con.ac-hero-inner would, so this has to match all three classes. Without
   it the padding resolved to 0 and the eyebrow sat underneath the fixed
   header, invisible. */
.e-con.ac-wrap.ac-hero-inner.ac-bare,
.e-con.ac-hero-inner {
	position: relative;
	z-index: 2;
	/* Enough to clear the fixed header, and no more — the space below has to
	   be paid for out of the same single screen. */
	--padding-top: clamp(104px, 13vh, 168px);
	--padding-bottom: clamp(48px, 7vh, 88px);
	--row-gap: clamp(14px, 1.8vh, 26px);
}

/* The one place on the site where the type is allowed to be loud. */
.ac-hero-cine .ac-hero-title .elementor-heading-title,
.ac-hero-cine h1 {
	/*
	 * Sized against the viewport's height as well as its width.
	 *
	 * On a wide, short screen — most laptops — a purely width-based clamp gave
	 * a 100px headline that ran to five lines and pushed everything under it
	 * off the bottom. The vh term caps it by the room actually available.
	 */
	font-size: clamp(2.6rem, min(4.6vw, 7.4vh), 5.2rem);
	line-height: 1;
	letter-spacing: -.035em;
	color: #fff;
	/* Wide enough for three or four lines rather than five, and still clear of
	   the lit sign on the right of the photograph. */
	max-width: 15ch;
	margin: 0;
}

.ac-hero-cine .ac-eyebrow .elementor-heading-title { color: var(--ac-glow); }
.ac-hero-cine .ac-lead {
	color: rgba(255, 255, 255, .70);
	font-size: clamp(1.02rem, .95rem + .45vw, 1.24rem);
	max-width: 46ch;
}
.ac-hero-cine .ac-hero-meta li { color: rgba(255, 255, 255, .58); }
.ac-hero-cine .ac-hero-meta li::before { background: var(--ac-glow); }

/* The accented word glows rather than simply changing colour — the whole
   design argument in one detail. */
.ac-hero-cine .ac-display em {
	color: #fff;
	text-shadow:
		0 0 14px rgba(255, 179, 138, .55),
		0 0 44px rgba(255, 149, 96, .40),
		0 0 96px rgba(255, 120, 60, .28);
}
.ac-hero-cine .ac-display em::after { background: var(--ac-glow); opacity: .9; }

/* Scroll cue: a hairline that runs, rather than a bouncing arrow. */
.ac-hero-cue {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 26px;
	z-index: 3;
	display: flex;
	justify-content: center;
	pointer-events: none;
}
.ac-hero-cue span {
	display: block;
	width: 1px;
	height: 54px;
	background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, .55));
	overflow: hidden;
	position: relative;
}
.ac-hero-cue span::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--ac-glow);
	animation: ac-cue 2.4s cubic-bezier(.6, 0, .3, 1) infinite;
}
@keyframes ac-cue {
	0%   { transform: translateY(-100%); }
	60%  { transform: translateY(100%); }
	100% { transform: translateY(100%); }
}

@media (max-width: 1023px) {
	.e-con.ac-hero-cine { min-height: clamp(520px, 74vh, 720px); }
	.ac-hero-bg img, .ac-hero-bg .ac-shot { object-position: 58% 46%; }
	.ac-hero-cine::before {
		background:
			linear-gradient(178deg, rgba(10,11,12,.90) 0%, rgba(10,11,12,.62) 42%, rgba(10,11,12,.30) 62%, rgba(10,11,12,.88) 100%);
	}
	/*
	 * A touch smaller on a phone. At the shared floor the longest line came to
	 * exactly the column width — it fitted, but ran edge to edge with no air
	 * either side, which reads as an accident rather than a decision.
	 */
	.ac-hero-cine .ac-hero-title .elementor-heading-title {
		font-size: 2.3rem;
		max-width: 13ch;
	}
	.ac-hero-cue { display: none; }
}

/* ==========================================================================
   3. CHAPTER NUMERALS
   ==========================================================================
   The page is a sequence — what we do, our work, how it works, get in touch —
   so the numbers carry something true rather than decorating. They are set
   oversized and nearly invisible: structure you feel before you read it. */

.e-con.ac-sec-head { position: relative; }

/* Elementor Free cannot put a custom attribute on a container, so the numeral
   arrives as a class and the content is declared here. */
.ac-sec-head.ac-ch-01::before { content: "01"; }
.ac-sec-head.ac-ch-02::before { content: "02"; }
.ac-sec-head.ac-ch-03::before { content: "03"; }
.ac-sec-head.ac-ch-04::before { content: "04"; }
.ac-sec-head.ac-ch-05::before { content: "05"; }

.ac-sec-head[class*="ac-ch-"]::before {
	/* The section head is a grid, so this pseudo-element becomes a grid item
	   and "right: 0" would resolve against its cell rather than the whole
	   block — which parked the numeral on the left. Spanning every track puts
	   it back where it belongs. */
	grid-area: 1 / 1 / -1 / -1;
	position: absolute;
	right: 0;
	top: -.42em;
	z-index: 0;
	font-family: var(--ac-font-head, "Manrope"), sans-serif;
	font-size: clamp(6rem, 3rem + 11vw, 15rem);
	font-weight: 800;
	line-height: .8;
	letter-spacing: -.06em;
	color: var(--ac-ink, #24262A);
	opacity: .045;
	pointer-events: none;
	user-select: none;
}
.ac-section--dark .ac-sec-head[class*="ac-ch-"]::before,
.ac-work-section .ac-sec-head[class*="ac-ch-"]::before { color: #fff; opacity: .07; }
.ac-sec-head > * { position: relative; z-index: 1; }

@media (max-width: 767px) {
	.ac-sec-head[class*="ac-ch-"]::before { font-size: 6rem; top: -.3em; opacity: .04; }
}

/* ==========================================================================
   4. MASKED TEXT REVEAL
   ==========================================================================
   Headings are split into lines by SplitType and each line rises out of its own
   overflow box. This is the single clearest signal that a page was designed
   rather than assembled, and it costs nothing at rest.

   The mask is only applied once the script has successfully split the heading —
   the .is-split class is added by JS — so a failure leaves plain, visible text. */

/*
 * The mask is taller than the line it hides, and takes the difference back as
 * a negative margin so the layout is unchanged.
 *
 * Without that it clipped the type. The display headings run at 1.08em leading,
 * and a descender — the g in "Signage & branding", the y in "your business" —
 * hangs below the line box. overflow: hidden on a box exactly one line tall
 * sliced every one of them off flat, on every heading on the site.
 *
 * The travel goes up with it. At translateY(105%) of its own height the line
 * would still show through the extra room at the bottom of a taller mask, so
 * it moves 125% instead: enough to clear 1.08em of line plus 0.16em of padding
 * with room to spare, and it is off screen either way.
 */
.ac-split-line {
	overflow: hidden;
	display: block;
	padding-bottom: .16em;
	margin-bottom: -.16em;
}
.ac-split-line .line { display: block; }

.is-split .ac-split-line .line {
	transform: translateY(125%);
	will-change: transform;
}

/* ==========================================================================
   5. DARK SHOWCASE SECTIONS
   ========================================================================== */

.ac-section--dark {
	background-color: var(--ac-night);
	position: relative;
	isolation: isolate;
}

/* A single warm light source, low and off-centre, so the dark bands are lit
   rather than merely unlit. */
.ac-section--dark::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background: radial-gradient(120% 90% at 15% 0%, rgba(228, 87, 46, .16), transparent 58%);
}
.ac-section--dark > * { position: relative; z-index: 1; }

/* ==========================================================================
   6. THE WORK SECTION
   ==========================================================================
   This was a rail: on a wide screen the section pinned itself and the work
   travelled sideways as you scrolled down. It read well when it behaved, but
   it hijacked the page's scroll to do it, and hijacked scrolling stutters the
   moment anything else on the page wants a frame. On a phone it fell back to
   a swipeable strip, which put a horizontal scroll inside a vertical page —
   two gestures fighting over the same drag.

   It is an ordinary grid now. The work is still the point of the section; it
   is simply read the way every other grid on the site is read. */

.e-con.ac-work-section {
	background: var(--ac-night);
	color: rgba(255, 255, 255, .72);
	overflow: clip;
	position: relative;
	isolation: isolate;
}
.ac-work-section .ac-sec-head .elementor-heading-title,
.ac-work-section h2 { color: #fff; }
.ac-work-section .ac-sec-head p { color: rgba(255, 255, 255, .6); }

/* The tiles carry their own grid from ac-layout.css (.ac-work-grid); all this
   section adds is the breathing room under the heading. */
.ac-work-section .ac-work-grid { margin-top: clamp(28px, 3vw, 44px); }

/* No feature tiles here.
   On the portfolio page the first and sixth tile run double width, which gives
   that page its rhythm. Nine tiles plus two double-width ones is eleven
   columns across a three-column grid, so the last row comes up short and ends
   in a hole. The portfolio page is the place for the uneven rhythm; the home
   page shows the same nine as a clean three by three. */
.ac-work-section .ac-work-grid > .ac-work-item:nth-of-type(1),
.ac-work-section .ac-work-grid > .ac-work-item:nth-of-type(6) { grid-column: auto; }

/* ==========================================================================
   7. CARD AND TILE INTERACTION
   ========================================================================== */

.ac-card {
	transition:
		transform .5s var(--ac-ease),
		box-shadow .5s var(--ac-ease),
		border-color .5s var(--ac-ease);
}
.ac-card:hover {
	transform: translateY(-6px);
	box-shadow: 0 26px 60px rgba(16, 17, 18, .13);
}

.ac-work-item {
	transition: transform .55s var(--ac-ease), box-shadow .55s var(--ac-ease);
}
.ac-work-item:hover { box-shadow: 0 30px 70px rgba(0, 0, 0, .45); }

/* Buttons lean very slightly toward the pointer. The movement is small enough
   to feel like weight rather than a trick. */
.ac-magnetic { will-change: transform; }

/* ==========================================================================
   8. THE TICKER
   ==========================================================================
   Promoted from a caption-sized strip to a band that carries the page. */

.ac-ticker {
	padding: 26px 0;
	background: var(--ac-night);
	border-top: 0;
	border-bottom: 0;
}
.ac-ticker__row span {
	font-size: clamp(.86rem, .6rem + .5vw, 1.15rem);
	font-weight: 800;
	letter-spacing: .13em;
	color: rgba(255, 255, 255, .30);
	transition: color .4s var(--ac-ease);
}
.ac-ticker__row span::after { background: var(--ac-primary); opacity: .9; }
.ac-ticker:hover .ac-ticker__row span { color: rgba(255, 255, 255, .52); }

/* ==========================================================================
   9. REDUCED MOTION
   ==========================================================================
   Everything above must arrive at its resting state with no movement at all.
   The script checks the same query and skips building the timelines. */

@media (prefers-reduced-motion: reduce) {
	.is-split .ac-split-line .line { transform: none !important; }
	.ac-hero-cue { display: none; }
	.ac-hero-bg img, .ac-hero-bg .ac-shot { transform: none !important; }
	.ac-card:hover, .ac-work-item:hover { transform: none; }
	.ac-ticker__row { animation: none; }
}

/* ==========================================================================
   10. CARDS ON A DARK SECTION
   ==========================================================================
   The service cards now sit on black. A white card there would punch a hole in
   the section, so the card becomes a dark object with a hairline edge and the
   mock-up supplies the only light in it — which is the point of the whole
   section. */

.ac-section--dark .ac-card {
	background: var(--ac-night-2);
	border-color: rgba(255, 255, 255, .10);
	position: relative;
	isolation: isolate;
}

/*
 * A light source on the card, not just a fill.
 *
 * The section's whole argument is that signage is a lit object seen after
 * dark, and eight flat charcoal rectangles were arguing the opposite. A very
 * soft warm wash from the top of each card gives it a direction the light is
 * coming from — the same trick as the closing band, at a fraction of the
 * strength. It brightens on hover, which is the card acknowledging the pointer
 * before anything moves.
 */
.ac-section--dark .ac-card::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	border-radius: inherit;
	background: radial-gradient(120% 70% at 50% 0%, rgba(255, 179, 138, .09), transparent 62%);
	opacity: .8;
	transition: opacity .5s var(--ac-ease);
}
.ac-section--dark .ac-card:hover::before { opacity: 1.6; }

.ac-section--dark .ac-card:hover {
	border-color: rgba(255, 255, 255, .26);
	box-shadow: 0 30px 70px rgba(0, 0, 0, .55);
}

.ac-section--dark .ac-card .elementor-heading-title { color: #fff; }
.ac-section--dark .ac-card p { color: rgba(255, 255, 255, .60); }
.ac-section--dark .ac-card-no .elementor-heading-title { color: rgba(255, 255, 255, .38); }

/* The arrow link needs to be readable on black; the small variant keeps its
   orange, which reads well there. */
.ac-section--dark .ac-link--sm .elementor-button { color: var(--ac-glow); }

/* The section heading rule and note follow the section, not the page. */
.ac-section--dark .e-con.ac-sec-head { border-bottom-color: rgba(255, 255, 255, .14); }
.ac-section--dark .ac-note-lg p,
.ac-section--dark .ac-sec-head p { color: rgba(255, 255, 255, .58); }

/* ==========================================================================
   11. THE HERO ON A PHONE
   ==========================================================================
   The header is shorter here and there is far less screen to give away, so the
   hero opens tighter. Everything above the fold should still be the headline
   and one call to action, not padding. */

@media (max-width: 767px) {
	.e-con.ac-wrap.ac-hero-inner.ac-bare,
	.e-con.ac-hero-inner {
		--padding-top: 104px;
		--padding-bottom: 56px;
	}
	.e-con.ac-hero-cine { min-height: 0; }
	.ac-hero-cine .ac-hero-title .elementor-heading-title { max-width: 14ch; }
}

/* ==========================================================================
   12. INNER-PAGE OPENERS
   ==========================================================================
   Dark like the homepage hero, and deliberately a different shape.

   The home hero is photograph-dominant and nearly full height, because its job
   is to show the work. An inner page already has the visitor; its job is to say
   what the page is. So these are type-dominant, about half the height, with the
   photograph pushed well back — present as atmosphere, not as subject.

   Every page opening in exactly the same way is what made the site feel
   repetitive, so the difference between the two is the point. */

.e-con.ac-page-open {
	position: relative;
	overflow: clip;
	background: var(--ac-night);
	color: rgba(255, 255, 255, .72);
	--padding-top: 0px; --padding-bottom: 0px;
	--padding-left: 0px; --padding-right: 0px;
	isolation: isolate;
}

.e-con.ac-open-bg {
	position: absolute;
	inset: 0;
	z-index: 0;
	--width: 100%;
	--padding-top: 0px; --padding-bottom: 0px;
	--padding-left: 0px; --padding-right: 0px;
	pointer-events: none;
}
.ac-open-bg .ac-media,
.ac-open-bg .elementor-widget-container,
.ac-open-bg .elementor-image,
.ac-open-bg figure { height: 100%; }

.ac-open-bg img,
.ac-open-bg .ac-shot {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 55% 42%;
	border-radius: 0;
	box-shadow: none;
	/* Held right back. The heading has to win here; a photograph at full
	   strength behind display type just makes both harder to read. */
	opacity: .30;
	filter: grayscale(.35) contrast(1.05);
}

.ac-page-open::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background:
		linear-gradient(92deg, var(--ac-night) 8%, rgba(10, 11, 12, .74) 44%, rgba(10, 11, 12, .58) 100%),
		linear-gradient(to top, var(--ac-night) 2%, transparent 46%);
}

.e-con.ac-wrap.ac-open-inner.ac-bare,
.e-con.ac-open-inner {
	position: relative;
	z-index: 2;
	--padding-top: clamp(148px, 15vh, 196px);
	--padding-bottom: clamp(60px, 8vh, 96px);
}

.ac-page-open .ac-page-title .elementor-heading-title {
	color: #fff;
	font-size: clamp(2.3rem, 1.3rem + 3.4vw, 4.1rem);
	line-height: 1.03;
	max-width: 17ch;
}
.ac-page-open .ac-eyebrow .elementor-heading-title { color: var(--ac-glow); }
.ac-page-open .ac-lead { color: rgba(255, 255, 255, .68); max-width: 56ch; }

/* The outline CTA has to invert here, same as in the floating header. */
.ac-page-open .ac-btn-outline .elementor-button {
	color: #fff !important;
	background-color: rgba(255, 255, 255, .08) !important;
	border-color: rgba(255, 255, 255, .30) !important;
}

@media (max-width: 767px) {
	.e-con.ac-wrap.ac-open-inner.ac-bare,
	.e-con.ac-open-inner {
		--padding-top: 116px;
		--padding-bottom: 52px;
	}
	.ac-page-open .ac-page-title .elementor-heading-title { max-width: 16ch; }
}

/* ==========================================================================
   13. THE SERVICES PAGE
   ==========================================================================
   This is the page that sells, and it was the flattest thing left: eight rows
   of identical rhythm, each floating in the middle of a white page with the
   visual boxed inside the content measure.

   Two changes. The three groups become three grounds — Signage dark, Printing
   light, Branding dark — and the visual breaks out of the measure and runs to
   the edge of the page. A picture that touches the edge reads as part of the
   page; a picture inside a column reads as an illustration of it. */

.e-con.ac-service-row {
	--row-gap: clamp(28px, 3.4vw, 54px);
	--column-gap: clamp(32px, 4vw, 72px);
	gap: clamp(32px, 4vw, 72px);
	--align-items: center;
	position: relative;
	padding-block: clamp(28px, 3.4vw, 56px);
}

/* A hairline between services, so a long page still has structure. */
.ac-service-row + .ac-service-row { border-top: 1px solid var(--ac-border); }
.ac-section--dark .ac-service-row + .ac-service-row { border-top-color: rgba(255, 255, 255, .10); }

/* ---- the bleed ----------------------------------------------------------
   The row sits inside the 1240px measure. This pulls the visual back out to
   the viewport edge on whichever side it is on, using the same arithmetic the
   measure itself uses so the two always agree.
   ------------------------------------------------------------------------ */
@media (min-width: 960px) {
	.ac-service-media {
		--ac-bleed: max(20px, calc((100vw - var(--ac-wrap, 1240px)) / 2 + 32px));

		/*
		 * Elementor gives every container an explicit width (width: var(--width)),
		 * so a negative margin only slides the box sideways — it keeps its width
		 * and leaves a hole on the inboard side. Releasing the width lets the
		 * grid item stretch into the negative margin instead, which is the
		 * difference between an image that bleeds and one that has simply moved.
		 */
		--width: auto;
		width: auto;
	}
	.ac-row--img-left  .ac-service-media { margin-left: calc(-1 * var(--ac-bleed)); }
	.ac-row--img-right .ac-service-media { margin-right: calc(-1 * var(--ac-bleed)); }

	.ac-service-media .ac-shot,
	.ac-service-media img { border-radius: 0; }

	/* Round only the inboard corners, so the bleed edge stays square against
	   the page and the other side still belongs to the card language. */
	.ac-row--img-left .ac-service-media .ac-shot,
	.ac-row--img-left .ac-service-media img {
		border-radius: 0 var(--ac-radius-lg) var(--ac-radius-lg) 0;
	}
	.ac-row--img-right .ac-service-media .ac-shot,
	.ac-row--img-right .ac-service-media img {
		border-radius: var(--ac-radius-lg) 0 0 var(--ac-radius-lg);
	}
}

/* ---- the index numeral --------------------------------------------------
   Promoted from a caption to a real element: it is the only thing that makes
   eight rows feel like a numbered range rather than a repeated block.
   ------------------------------------------------------------------------ */
.ac-service-no .elementor-heading-title {
	font-family: var(--ac-font-head, "Manrope"), sans-serif;
	font-size: clamp(2.6rem, 1.6rem + 2.6vw, 4rem);
	font-weight: 800;
	line-height: .85;
	letter-spacing: -.05em;
	color: var(--ac-border);
}
.ac-section--dark .ac-service-no .elementor-heading-title { color: rgba(255, 255, 255, .16); }

.ac-service-copy { max-width: 46rem; }

/* ---- dark-band type ----------------------------------------------------- */
.ac-section--dark .ac-service-title .elementor-heading-title { color: #fff; }
.ac-section--dark .ac-service-row p { color: rgba(255, 255, 255, .64); }
.ac-section--dark .ac-uses-label { color: rgba(255, 255, 255, .42); }
.ac-section--dark .ac-ticklist li { color: rgba(255, 255, 255, .74); }

@media (max-width: 959px) {
	/* No bleed on a narrow screen — there is no margin to bleed into, and a
	   full-width image between two blocks of copy reads fine on its own. */
	.ac-service-media { margin-inline: 0; }
	.e-con.ac-service-row { padding-block: clamp(24px, 5vw, 40px); }
}

/* ==========================================================================
   14. THE CLOSING BAND AND THE FOOTER
   ========================================================================== */

/* ---- the orange band ----------------------------------------------------
   Everything else on the page gained depth, which left a flat fill of brand
   orange looking like the one unfinished thing. Same treatment as the dark
   sections: a light source and a little grain, so it reads as a surface.
   ------------------------------------------------------------------------ */
.ac-section--accent {
	position: relative;
	isolation: isolate;
	/* The one place the brighter original orange is kept. Everything on this
	   band is display-sized, which needs 3:1 rather than 4.5:1, and white on
	   #E4572E clears that at 3.68 — so the band can have the life the darker
	   working orange gives up for the sake of small text elsewhere. */
	background-image:
		radial-gradient(120% 140% at 82% 0%, rgba(255, 255, 255, .16), transparent 62%),
		linear-gradient(104deg, var(--ac-primary) 0%, var(--ac-primary-bright, #E4572E) 58%);
}
.ac-section--accent > * { position: relative; z-index: 1; }

/* Not on the thank-you page. The band asks for a quote, and the visitor has
   just sent one — the page above it is the confirmation. Hidden rather than
   removed from the footer template because the band is sitewide and every
   other page still wants it. */
body.ac-page-thank-you .ac-section--accent { display: none; }

.ac-section--accent::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	/* Flat for the same reason as the grain above. */
	opacity: .09;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.4'/%3E%3C/svg%3E");
	background-size: 160px 160px;
}

/* It is the last thing before the footer and it asks for the enquiry, so it
   gets to be loud. */
.ac-section--accent .elementor-heading-title {
	font-size: clamp(2rem, 1.2rem + 2.8vw, 3.6rem);
	line-height: 1.04;
}

/* ---- the footer ---------------------------------------------------------
   The badge was rendering at around 200px, which made the one bright white
   disc on the page the loudest thing in the footer. It is an identity mark
   here, not a hero.
   ------------------------------------------------------------------------ */
.ac-footer-col .ac-logo img,
.ac-footer-grid .ac-logo img {
	max-width: 112px;
	height: auto;
}

/* Column headings were the same weight as the links under them, so the
   footer read as one undifferentiated list of words. */
.ac-footer-col .elementor-widget-heading .elementor-heading-title {
	color: rgba(255, 255, 255, .92);
}

.ac-footer-links a {
	transition: color .2s var(--ac-ease), padding-left .2s var(--ac-ease);
}
.ac-footer-links a:hover { padding-left: 4px; }

/* ==========================================================================
   15. 404
   ==========================================================================
   The one page still rendering in the old flat style. It gets the same dark
   treatment as every other opener — a visitor who hits a dead link should not
   feel like they have fallen out of the site.

   The numeral is handled the same way as the chapter numbers: very large, very
   faint, structural rather than decorative. Shouting "404" at someone who is
   already lost helps nobody; the routes out are what matter, so those are what
   is bright. */

/* Hello Elementor caps this element with
     body:not([class*="elementor-page-"]) .site-main
   which is (0,2,1) — an element plus two class-weight parts. Anything shorter
   loses, and the dark ground stayed a box floating in white. Matching
   body.error404 .site-main.ac-404 clears it honestly, without !important. */
body.error404 .site-main.ac-404,
.ac-404 {
	position: relative;
	/* 100vw counts the scrollbar; the content box does not. On a page with
	   a vertical scrollbar that made this band ~8px wider than the page and
	   put a horizontal scrollbar under it. 100% of the parent is the width
	   actually available, and the negative margins still bleed it full. */
	width: auto;
	max-width: none;
	margin-inline: calc(50% - 50%);
	background: var(--ac-night);
	color: rgba(255, 255, 255, .68);
	padding: clamp(150px, 17vh, 220px) 20px clamp(90px, 11vh, 140px);
	isolation: isolate;
	overflow: clip;
}

.ac-404::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
	background: radial-gradient(110% 80% at 50% 0%, rgba(228, 87, 46, .18), transparent 62%);
}
.ac-404 > * { position: relative; z-index: 1; }

.ac-404__code {
	font-family: var(--ac-font-head, "Manrope"), sans-serif;
	font-size: clamp(7rem, 4rem + 14vw, 17rem);
	font-weight: 800;
	line-height: .78;
	letter-spacing: -.06em;
	color: #fff;
	opacity: .07;
	margin: 0 0 -.18em;
	user-select: none;
}

.ac-404 h1 {
	color: #fff;
	font-size: clamp(1.9rem, 1.2rem + 2.4vw, 3.2rem);
	max-width: 18ch;
	margin-inline: auto;
}
.ac-404 p { color: rgba(255, 255, 255, .62); }

.ac-404__links a:first-child { background: var(--ac-primary); color: #fff; }
.ac-404__links a + a {
	border-color: rgba(255, 255, 255, .32);
	color: #fff;
}
.ac-404__links a + a:hover { background: #fff; color: var(--ac-dark); border-color: #fff; }
.ac-404__meta { color: rgba(255, 255, 255, .5); }
.ac-404__meta a { color: var(--ac-glow); }

/* ==========================================================================
   16. FORM STATES
   ==========================================================================
   Someone who has just sent an enquiry is at the most valuable moment on the
   site, and the reply to them was a one-pixel border colour change. These are
   the three things that can happen, each said clearly.

   Contact Form 7 puts .sent, .invalid or .failed on the form itself and writes
   the message into .wpcf7-response-output, so the state is styleable without
   any JavaScript. */

.ac-form .wpcf7-response-output {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 16px 0 0 !important;
	padding: 14px 16px !important;
	border-width: 1px !important;
	border-radius: var(--ac-radius);
	font-size: .88rem;
	line-height: 1.5;
}

/* A glyph rather than an icon font: one character, no extra request, and it
   still reads if the stylesheet is all that loads. */
.ac-form .wpcf7-response-output::before {
	flex: none;
	width: 20px;
	height: 20px;
	margin-top: 1px;
	border-radius: 50%;
	display: grid;
	place-items: center;
	font-size: .72rem;
	font-weight: 700;
	color: #fff;
}

/* ---- sent ---- */
.ac-form .wpcf7-form.sent .wpcf7-response-output {
	background: #EAF6EF;
	border-color: var(--ac-wa) !important;
	color: #14532D;
}
.ac-form .wpcf7-form.sent .wpcf7-response-output::before {
	content: "\2713";
	background: var(--ac-wa);
}

/* ---- did not validate ---- */
.ac-form .wpcf7-form.invalid .wpcf7-response-output,
.ac-form .wpcf7-form.unaccepted .wpcf7-response-output {
	background: #FDF0EC;
	border-color: var(--ac-primary-d) !important;
	color: #7A2A12;
}
.ac-form .wpcf7-form.invalid .wpcf7-response-output::before,
.ac-form .wpcf7-form.unaccepted .wpcf7-response-output::before {
	content: "!";
	background: var(--ac-primary-d);
}

/* ---- could not send ---- */
.ac-form .wpcf7-form.failed .wpcf7-response-output,
.ac-form .wpcf7-form.aborted .wpcf7-response-output {
	background: #FBF3E8;
	border-color: #B7791F !important;
	color: #6B4708;
}
.ac-form .wpcf7-form.failed .wpcf7-response-output::before,
.ac-form .wpcf7-form.aborted .wpcf7-response-output::before {
	content: "!";
	background: #B7791F;
}

/* The field that failed should be findable without reading the message. */
.ac-form .wpcf7-not-valid {
	border-color: var(--ac-primary-d) !important;
	background: #FFFBFA;
}
.ac-form .wpcf7-not-valid-tip {
	font-size: .76rem;
	color: var(--ac-primary-d);
	margin-top: 5px;
	font-weight: 500;
}

/* While it is submitting, say so — the button is the thing being waited on. */
.ac-form .wpcf7-form.submitting .wpcf7-submit {
	opacity: .72;
	cursor: progress;
}
.ac-form .wpcf7-spinner { margin: 10px auto 0; display: block; }

/* ==========================================================================
   17. THE SERVICE CARDS
   ==========================================================================
   Three things were wrong with these.

   The image was a 16:9 strip, too shallow to carry a photograph. The index
   number sat in the body, pushing the heading down. And the "Learn more" link
   was pinned to the card foot, so a card with two lines of copy left a visible
   hole where a card with four lines had none — eight cards, eight different
   amounts of empty space.

   Now: a 4:3 figure with the number on it, and a body that ends where the copy
   ends. The cards still line up because the grid stretches them, not because
   the link is nailed to the bottom. */

.e-con.ac-service-tile {
	overflow: hidden;
	--padding-top: 0px; --padding-bottom: 0px;
	--padding-left: 0px; --padding-right: 0px;
}

.e-con.ac-card-figure {
	position: relative;
	overflow: hidden;
	--padding-top: 0px; --padding-bottom: 0px;
	--padding-left: 0px; --padding-right: 0px;
	--row-gap: 0px;
}

.ac-card-figure .ac-media,
.ac-card-figure .elementor-widget-container { line-height: 0; }

.ac-card-figure img,
.ac-card-figure .ac-shot {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 0;
	display: block;
}

/* A gradient into the card, so the photograph is seated rather than pasted on,
   and the numeral always has something to sit against. */
.ac-card-figure::after {
	content: "";
	position: absolute;
	inset: auto 0 0 0;
	/* Shallow and weak on purpose. Its only job is to seat the photograph into
	   the card and give the numeral something to sit on; at 58% with a solid
	   stop it was swallowing the lower half of every image. */
	height: 42%;
	pointer-events: none;
	background: linear-gradient(to top, rgba(19, 20, 23, .88) 0%, rgba(19, 20, 23, .34) 46%, transparent 100%);
}
.ac-section:not(.ac-section--dark) .ac-card-figure::after {
	background: linear-gradient(to top, rgba(255, 255, 255, .9) 0%, rgba(255, 255, 255, .3) 46%, transparent 100%);
}

/* The index, on the image. */
.ac-card-figure .ac-card-no {
	position: absolute;
	left: 20px;
	bottom: 12px;
	z-index: 2;
	margin: 0;
}
.ac-card-figure .ac-card-no .elementor-heading-title {
	font-family: var(--ac-font-head, "Manrope"), sans-serif;
	font-size: 1.5rem;
	font-weight: 800;
	line-height: 1;
	letter-spacing: -.04em;
	color: #fff;
	opacity: .92;
}
.ac-section:not(.ac-section--dark) .ac-card-figure .ac-card-no .elementor-heading-title {
	color: var(--ac-ink);
	opacity: .34;
}

/*
 * The body fills the card and the link is pushed to its foot.
 *
 * It used to carry margin-top: 6px, which quietly cancelled the margin-top:
 * auto in ac-layout.css that exists precisely to line these up. With it, every
 * card put "Learn more" directly under its own last line of copy, so the eight
 * links sat at four different heights across a row — the thing that made the
 * grid look untidy however good the photographs were.
 */
.ac-service-tile .ac-card-body {
	--padding-top: 16px;
	--row-gap: 9px;
	height: 100%;
}
.ac-service-tile .ac-card-body > .ac-link { margin-top: auto; padding-top: 14px; }

.ac-service-tile h3,
.ac-service-tile .elementor-widget-heading .elementor-heading-title { text-wrap: balance; }
.ac-service-tile p { font-size: .9rem; }

/* Only the photograph moves on hover; the card lifts as before. */
.ac-card-figure img,
.ac-card-figure .ac-shot {
	transition: transform .6s var(--ac-ease);
}
.ac-service-tile:hover .ac-card-figure img,
.ac-service-tile:hover .ac-card-figure .ac-shot { transform: scale(1.06); }

/*
 * Hovering the card is hovering its link.
 *
 * The whole tile behaves like one target — it lifts, the photograph moves —
 * and it was odd that the one thing you would actually click sat there
 * unchanged until the pointer found the eight characters of "Learn more". The
 * rule draws and the arrow steps whenever the card is hovered, so the card
 * reads as a single control rather than a panel with a small link on it.
 */
.ac-service-tile:hover .ac-link .elementor-button-text::after {
	transform: scaleX(1);
	transform-origin: left center;
}
.ac-service-tile:hover .ac-link .elementor-button-icon { transform: translateX(5px); }

@media (prefers-reduced-motion: reduce) {
	.ac-service-tile:hover .ac-card-figure img,
	.ac-service-tile:hover .ac-card-figure .ac-shot { transform: none; }
}
