/*
Theme Name: Arolax Child
Theme URI: https://krenative.ae
Description: Child theme for Arolax. All Krenative customizations live here so vendor updates to the parent theme never overwrite them.
Author: Krenative
Author URI: https://krenative.ae
Template: arolax
Version: 1.0.0
Text Domain: arolax-child
*/

/* Custom styles below. Parent styles load first (see functions.php). */

/* ---------------------------------------------------------------------------
   Brand foundation
   The parent theme exposes --primary, --font-primary and --font-secondary on
   :root, and master.min.css references var(--primary) in 34 rules. Overriding
   them here rebrands the whole site from one place.
   Agrandir is licensed to Krenative; Poppins is SIL OFL. Both self-hosted so
   the site carries no dependency on fonts.googleapis.com.
--------------------------------------------------------------------------- */

@font-face {
	font-family: "Agrandir";
	src: url("fonts/Agrandir-GrandHeavy.woff2") format("woff2");
	font-weight: 600 900;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Agrandir";
	src: url("fonts/Agrandir-Regular.woff2") format("woff2");
	font-weight: 100 500;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Poppins";
	src: url("fonts/poppins-v24-latin-300.woff2") format("woff2");
	font-weight: 300;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Poppins";
	src: url("fonts/poppins-v24-latin-400.woff2") format("woff2");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Poppins";
	src: url("fonts/poppins-v24-latin-500.woff2") format("woff2");
	font-weight: 500;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Poppins";
	src: url("fonts/poppins-v24-latin-600.woff2") format("woff2");
	font-weight: 600;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Poppins";
	src: url("fonts/poppins-v24-latin-700.woff2") format("woff2");
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

:root {
	--primary: #b92c2f;
	--font-primary: "Poppins", sans-serif;
	--font-secondary: "Agrandir", sans-serif;
}

/* ---------------------------------------------------------------------------
   Work segment filter pills
   The wcf--portfolio widget renders its own filter bar; this is styling only.
   Note the wrapper class is .wcf__portfolio with a double underscore, while
   the widget name uses a double hyphen. Buttons also need an explicit
   font-family, since <button> does not inherit one. The plugin's portfolio.css
   has the same specificity and loads after this file, so every rule here adds
   .enable-filter to outrank it.
--------------------------------------------------------------------------- */

.wcf__portfolio.enable-filter .filter {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.6rem;
}

.wcf__portfolio.enable-filter .filter button {
	font-family: var(--font-primary);
	font-weight: 300;
	font-size: 0.95rem;
	letter-spacing: 0.02em;
	line-height: 1;
	color: inherit;
	border: 1px solid rgba(0, 0, 0, 0.15);
	border-radius: 999px;
	padding: 0.6rem 1.15rem;
	background: transparent;
	cursor: pointer;
	transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.wcf__portfolio.enable-filter .filter button:hover {
	border-color: var(--primary);
	color: var(--primary);
}

.wcf__portfolio.enable-filter .filter button.mixitup-control-active {
	background: var(--primary);
	border-color: var(--primary);
	color: #fff;
}

/* The item count that precedes each label. The widget prints one inside every
   button; the client asked for the pills to read as labels alone. Hidden
   rather than unset, because the count comes from the widget's own render. */
.wcf__portfolio.enable-filter .filter button span {
	display: none;
}

/* ---------------------------------------------------------------------------
   International Presence map
   The animation carries its own colour; this is the frame around it.
--------------------------------------------------------------------------- */

.wcf-lottie-wrp lottie-player {
	filter: drop-shadow(0 0 18px rgba(185, 44, 47, 0.18));
}

/* ---------------------------------------------------------------------------
   Hero
   Full-bleed video with a scrim at the foot, so the buttons keep their
   contrast whatever frame the reel happens to be on. The section sits inside
   a gutter, hence the 100vw break-out.
--------------------------------------------------------------------------- */

.kre-hero {
	position: relative;
	width: 100vw;
	margin-left: calc(50% - 50vw);
	overflow: hidden;
}

.kre-hero > .elementor-background-video-container,
.kre-hero .elementor-background-video-container video {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Scrim: transparent through the top two thirds, so the footage reads, then
   deepening behind the buttons. */
.kre-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(
		to bottom,
		rgba(0, 0, 0, 0.35) 0%,
		rgba(0, 0, 0, 0) 28%,
		rgba(0, 0, 0, 0) 52%,
		rgba(0, 0, 0, 0.72) 100%
	);
}

/* The buttons must sit above the scrim. */
.kre-hero > .e-con-inner,
.kre-hero > .elementor-element {
	position: relative;
	z-index: 2;
}

/* ---------------------------------------------------------------------------
   Hero call-to-action buttons
   These use the theme's own oval button; what follows is a refinement of it,
   not a replacement — brand fill for the primary, glass for the secondary.
--------------------------------------------------------------------------- */

.kre-cta .wcf-btn-oval {
	font-family: var(--font-primary);
	font-weight: 500;
	font-size: 0.875rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 1.05rem 2.4rem;
	border: 1px solid transparent;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
}

.kre-cta .wcf-btn-oval:hover {
	transform: translateY(-2px);
}

.kre-cta--primary .wcf-btn-oval {
	background: var(--primary);
	border-color: var(--primary);
	color: #fff;
}

.kre-cta--primary .wcf-btn-oval:hover {
	background: #fff;
	border-color: #fff;
	color: #111;
}

/* Glass rather than a hard outline, so it recedes behind the primary. */
.kre-cta--ghost .wcf-btn-oval {
	background: rgba(255, 255, 255, 0.08);
	border-color: rgba(255, 255, 255, 0.45);
	color: #fff;
	-webkit-backdrop-filter: blur(6px);
	backdrop-filter: blur(6px);
}

.kre-cta--ghost .wcf-btn-oval:hover {
	background: rgba(255, 255, 255, 0.16);
	border-color: #fff;
	color: #fff;
}

/* The oval style draws a decorative rule in some contexts; the hero does not
   want it. */
.kre-hero .kre-cta .wcf-btn-underline::before,
.kre-hero .kre-cta .wcf-btn-oval::before,
.kre-hero .kre-cta .wcf-btn-oval::after {
	display: none;
}

/* ---------------------------------------------------------------------------
   International Presence map
   The animation carries its own colour; this is the frame around it.
--------------------------------------------------------------------------- */

.wcf-lottie-wrp lottie-player {
	filter: drop-shadow(0 0 18px rgba(185, 44, 47, 0.18));
}

/* ---------------------------------------------------------------------------
   Hero call-to-action buttons
   Two wcf--button widgets sit over the hero video. The widget renders a plain
   link, so the button treatment lives here: filled for the primary action,
   outlined for the secondary.
--------------------------------------------------------------------------- */

.kre-cta .wcf-btn,
.kre-cta a {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	font-family: var(--font-primary);
	font-weight: 500;
	font-size: 0.95rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: none;
	padding: 0.95rem 1.9rem;
	border-radius: 999px;
	border: 1px solid transparent;
	transition: background-color 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}

.kre-cta--primary a {
	background: var(--primary);
	border-color: var(--primary);
	color: #fff;
}

.kre-cta--primary a:hover {
	background: transparent;
	color: #fff;
	border-color: #fff;
}

.kre-cta--ghost a {
	background: transparent;
	border-color: rgba(255, 255, 255, 0.55);
	color: #fff;
}

.kre-cta--ghost a:hover {
	background: #fff;
	border-color: #fff;
	color: #111;
}

/* The two CTAs sit side by side once there is room for them. */
@media (min-width: 600px) {
	.kre-cta {
		display: inline-block;
	}
}

/* ---------------------------------------------------------------------------
   Client logo band
   The logos arrive in every colour and ink weight, and a third of them are
   dark on transparent while another third are white on transparent. Any
   treatment that keeps their own colour leaves one group invisible, so the
   band is flattened to a single ink — dark by default, inverted inside a
   section that carries a dark background. That section is matched by id, not
   class: this Elementor build stores a container's classes but never renders
   them, so a class-based hook fails silently.
--------------------------------------------------------------------------- */

[class*="brand-slider"] img,
[class*="brand"] .swiper-slide img {
	max-height: 34px;
	width: auto;
	object-fit: contain;
	filter: brightness(0) opacity(0.5);
	transition: opacity 0.3s ease, filter 0.3s ease;
}

#kre-band-dark [class*="brand-slider"] img,
#kre-band-dark [class*="brand"] .swiper-slide img {
	filter: brightness(0) invert(1) opacity(0.58);
}

/* Hovering a slide restores the client's own colours. The id-scoped rule above
   outranks a plain attribute selector, so the hover has to be scoped to the
   same id or it never lands — which is why the band stayed white on hover. */
[class*="brand-slider"] img:hover,
[class*="brand"] .swiper-slide img:hover,
#kre-band-dark [class*="brand-slider"] img:hover,
#kre-band-dark [class*="brand"] .swiper-slide img:hover {
	filter: none;
	opacity: 1;
}

@media (max-width: 767px) {
	[class*="brand-slider"] img,
	[class*="brand"] .swiper-slide img {
		max-height: 26px;
	}
}

/* ---------------------------------------------------------------------------
   Gallery scroll badge
   The badge is a red disc carrying the label "Our works", with a smaller
   progress disc behind it filled by a conic gradient driven by an inline
   --value. Because that disc is smaller than the label and fills white from
   underneath, the label was being eaten as it advanced.
   Making the progress a ring at the badge's edge keeps the label on solid
   red at all times, and reads more clearly as progress.
   The extra .gallery--slider raises specificity over the plugin stylesheet,
   which loads after this file.
--------------------------------------------------------------------------- */

.gallery--slider .g-slider--title .progress-circle {
	top: -7%;
	left: -7%;
	width: 114%;
	height: 114%;
	transform: none;
	background: conic-gradient(
		#fff calc(var(--value, 0) * 1%),
		rgba(255, 255, 255, 0.25) 0
	);
	-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
	mask: radial-gradient(farthest-side, transparent calc(100% - 4px), #000 calc(100% - 3px));
}

/* The label sits above the ring, never under it. */
.gallery--slider .g-slider--title .g-title {
	position: relative;
	z-index: 2;
	font-family: var(--font-primary);
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	font-size: 0.8rem;
	color: #fff;
}

/* ---------------------------------------------------------------------------
   International Presence map
   Inline SVG geography, markers positioned as percentages of the map box, and
   routes radiating from Abu Dhabi. The pulse is staggered per marker so the
   map reads as a signal travelling outward rather than six lights blinking
   together.
--------------------------------------------------------------------------- */

.kre-map {
	width: 100%;
}

.kre-map__stage {
	position: relative;
	width: 100%;
}

/* The geography itself. currentColor keeps the landmass tone in one place. */
.kre-map__geo {
	display: block;
	width: 100%;
	height: auto;
	color: rgba(17, 17, 19, 0.13);
}

.kre-map__routes {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	overflow: visible;
	pointer-events: none;
}

.kre-map__route {
	fill: none;
	stroke: var(--primary);
	/* non-scaling-stroke means these values are px, not viewBox units. */
	stroke-width: 1.1;
	stroke-linecap: round;
	stroke-dasharray: 5 7;
	opacity: 0.4;
	vector-effect: non-scaling-stroke;
	animation: kre-map-flow 2.6s linear infinite;
}

@keyframes kre-map-flow {
	to {
		stroke-dashoffset: -12;
	}
}

.kre-map__marker {
	position: absolute;
	left: var(--x);
	top: var(--y);
	width: 0;
	height: 0;
}

.kre-map__dot {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 9px;
	height: 9px;
	margin: -4.5px 0 0 -4.5px;
	border-radius: 50%;
	background: var(--primary);
	box-shadow: 0 0 0 3px rgba(185, 44, 47, 0.14);
}

.kre-map__marker.is-hub .kre-map__dot {
	width: 13px;
	height: 13px;
	margin: -6.5px 0 0 -6.5px;
	box-shadow: 0 0 0 5px rgba(185, 44, 47, 0.18);
}

/* The expanding ring. Each marker is delayed by its index, so the pulse
   travels outward from the hub rather than firing all at once. */
.kre-map__pulse {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 14px;
	height: 14px;
	margin: -7px 0 0 -7px;
	border-radius: 50%;
	border: 1px solid var(--primary);
	opacity: 0;
	animation: kre-map-pulse 4s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
	animation-delay: calc(var(--i, 0) * 0.45s);
}

@keyframes kre-map-pulse {
	0% {
		transform: scale(0.4);
		opacity: 0.85;
	}
	55% {
		transform: scale(3.6);
		opacity: 0;
	}
	100% {
		transform: scale(3.6);
		opacity: 0;
	}
}

.kre-map__label {
	position: absolute;
	left: 50%;
	bottom: 14px;
	transform: translateX(-50%) translateY(4px);
	white-space: nowrap;
	font-family: var(--font-primary);
	font-weight: 500;
	font-size: 0.68rem;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: #111113;
	background: rgba(255, 255, 255, 0.92);
	padding: 0.28em 0.6em;
	border-radius: 3px;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.25s ease, transform 0.25s ease;
}

/* The hub is always named; the rest reveal on hover. */
.kre-map__marker.is-hub .kre-map__label,
.kre-map__marker:hover .kre-map__label {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
}

.kre-map__marker {
	pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
	.kre-map__pulse,
	.kre-map__route {
		animation: none;
	}

	.kre-map__pulse {
		opacity: 0.5;
		transform: scale(1.6);
	}
}

@media (max-width: 767px) {
	.kre-map__dot {
		width: 7px;
		height: 7px;
		margin: -3.5px 0 0 -3.5px;
	}

	.kre-map__label {
		font-size: 0.6rem;
	}
}

/* ---------------------------------------------------------------------------
   Client logo wall
   A static grid, no hover effect, in the clients' own colours. The eleven
   marks that exist only as white artwork are held as ink recolours instead —
   white on this light section is nothing at all.
--------------------------------------------------------------------------- */

.kre-logos {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	gap: 2.4rem 2rem;
	align-items: center;
	margin: 0;
	padding: 0;
	list-style: none;
}

.kre-logos__item {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 46px;
}

.kre-logos__img {
	max-width: 100%;
	max-height: 40px;
	width: auto;
	height: auto;
	object-fit: contain;
	/* The wall runs in the clients' own colours at the client's request. The
	   eleven marks that only exist as white artwork are held as ink recolours
	   instead — see inc/client-logos.php. */
	transition: opacity 0.3s ease;
}

@media (max-width: 767px) {
	.kre-logos {
		grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
		gap: 1.6rem 1.2rem;
	}

	.kre-logos__img {
		max-height: 28px;
	}
}

/* ---------------------------------------------------------------------------
   Our Journey — the Edit Timeline
   A timecode rail down the left with a playhead tracking scroll position, and
   a year that pins while its milestone scrolls past. The metaphor is the
   scrubber in an edit timeline, which is the tool this studio lives in.
--------------------------------------------------------------------------- */

.kre-timeline {
	position: relative;
	max-width: 1290px;
	margin: 0 auto;
	padding: 0 20px;
}

/* The rail itself. */
.kre-timeline::before {
	content: "";
	position: absolute;
	left: calc(7.5rem + 20px);
	top: 0;
	bottom: 0;
	width: 1px;
	background: rgba(17, 17, 19, 0.14);
}

.kre-timeline__playhead {
	position: absolute;
	left: calc(7.5rem + 15px);
	width: 11px;
	height: 11px;
	border-radius: 50%;
	background: var(--primary);
	box-shadow: 0 0 0 4px rgba(185, 44, 47, 0.16);
	/* Position comes from a transform the script drives, so the head can chase
	   the scroll rather than jumping with it; centring is done by the negative
	   margin, since the transform is no longer free to hold it. */
	top: 0;
	margin-top: -5.5px;
	will-change: transform;
	z-index: 2;
}

.kre-timeline__entry {
	display: grid;
	grid-template-columns: 7.5rem 1fr;
	gap: 0 2.75rem;
	padding-bottom: 4.5rem;
}

.kre-timeline__rail {
	position: relative;
}

.kre-timeline__year {
	position: sticky;
	top: 42vh;
	display: block;
	font-family: var(--font-secondary);
	font-weight: 900;
	font-size: clamp(1.6rem, 3vw, 2.4rem);
	line-height: 1;
	letter-spacing: -0.01em;
	color: #111113;
	opacity: 0.28;
	transition: opacity 0.35s ease, color 0.35s ease;
}

.kre-timeline__entry.is-active .kre-timeline__year {
	opacity: 1;
	color: var(--primary);
}

.kre-timeline__title {
	margin: 0 0 0.9rem;
	font-family: var(--font-secondary);
	font-weight: 900;
	font-size: clamp(1.15rem, 2vw, 1.6rem);
	line-height: 1.15;
}

.kre-timeline__points {
	margin: 0;
	padding: 0;
	list-style: none;
}

.kre-timeline__points li {
	position: relative;
	padding-left: 1.1rem;
	margin-bottom: 0.7rem;
	font-family: var(--font-primary);
	font-weight: 300;
	line-height: 1.65;
}

.kre-timeline__points li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.7em;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--primary);
}

.kre-timeline .kre-timeline__still {
	display: block;
	width: 100%;
	max-width: 520px;
	height: auto;
	max-height: 300px;
	object-fit: cover;
	margin-top: 1.6rem;
	border-radius: 2px;
}

@media (max-width: 767px) {
	.kre-timeline::before {
		left: calc(3.6rem + 16px);
	}

	.kre-timeline__playhead {
		left: calc(3.6rem + 11px);
	}

	.kre-timeline {
		padding: 0 16px;
	}

	.kre-timeline__entry {
		grid-template-columns: 3.6rem 1fr;
		gap: 0 1.25rem;
		padding-bottom: 3rem;
	}

	.kre-timeline__year {
		top: 20vh;
		font-size: 1.1rem;
	}
}

@media (prefers-reduced-motion: reduce) {
	.kre-timeline__playhead {
		transition: none;
	}
}

/* ---------------------------------------------------------------------------
   Testimonial cards
   Three quotes side by side, so they can be scanned rather than waited for.
--------------------------------------------------------------------------- */

.kre-quotes {
	/* One track per quote where they fit — four reviews render as four cards,
	   three as three — and fewer per row as the column narrows. auto-fit
	   collapses the tracks it cannot fill, so the count needs no stylesheet. */
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
	gap: 1.6rem;
	max-width: 1290px;
	margin: 0 auto;
	padding: 0 20px;
}

.kre-quotes__card {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 1.6rem;
	margin: 0;
	padding: 2.2rem 1.9rem 2rem;
	background: #fff;
	border: 1px solid rgba(17, 17, 19, 0.09);
	border-radius: 3px;
	transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.45s ease, border-color 0.45s ease;
}

/* A red rule across the top edge, drawn on hover from the left. The card is
   otherwise deliberately quiet, and this is the whole of its reaction. */
.kre-quotes__card::after {
	content: "";
	position: absolute;
	top: -1px;
	left: -1px;
	right: -1px;
	height: 2px;
	background: var(--primary);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.kre-quotes__card:hover {
	transform: translateY(-4px);
	border-color: rgba(17, 17, 19, 0.16);
	box-shadow: 0 18px 40px -28px rgba(17, 17, 19, 0.45);
}

.kre-quotes__card:hover::after {
	transform: scaleX(1);
}


/* The theme gives blockquote a tinted panel and a rule; the card is the
   container here, so the quote itself resets to plain text. */
.kre-quotes .kre-quotes__quote {
	background: none;
	border: 0;
	padding: 0;
	quotes: none;
}

.kre-quotes__quote {
	margin: 0;
	font-family: var(--font-primary);
	font-weight: 300;
	font-size: 0.95rem;
	line-height: 1.7;
	color: #2a2b2f;
}

/* A quote mark, set in the display face, marking the card without shouting. */
.kre-quotes__quote::before {
	content: "\201C";
	display: block;
	font-family: var(--font-secondary);
	font-weight: 900;
	font-size: 2.6rem;
	line-height: 0.6;
	color: var(--primary);
	margin-bottom: 0.7rem;
}

.kre-quotes__by {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	padding-top: 1.1rem;
	border-top: 1px solid rgba(17, 17, 19, 0.09);
}

.kre-quotes__name {
	font-family: var(--font-secondary);
	font-weight: 900;
	font-size: 0.9rem;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: #111113;
}

.kre-quotes__role {
	font-family: var(--font-primary);
	font-weight: 300;
	font-size: 0.78rem;
	line-height: 1.45;
	color: #6a6b70;
}

@media (max-width: 1024px) {
	.kre-quotes {
		grid-template-columns: 1fr;
		max-width: 640px;
	}
}

/* ---------------------------------------------------------------------------
   Not case-study rules. Historically colocated in this range; kept verbatim
   so the Services page and the rest of the site don't regress.
--------------------------------------------------------------------------- */

/* Services page: the service widget always renders an image slot, falling
   back to Elementor's placeholder graphic when none is set. Hide the slot
   until real photos exist. Delete this rule once the images are in. */
.a-service--item .image:has(img[src*="placeholder"]) {
	display: none;
}

/* Services page: pin the image column while the service list scrolls past.
   The theme's own pin extension touches the element but never creates the
   pin; position: sticky gives the same result without depending on it. */
#service-visual {
	position: sticky;
	top: 0;
	align-self: flex-start;
	height: 100vh;
}

#service-visual .elementor-widget-wcf--image,
#service-visual .wcf--image,
#service-visual figure,
#service-visual img {
	height: 100%;
	width: 100%;
	object-fit: cover;
}

@media (max-width: 767px) {
	#service-visual {
		position: static;
		height: auto;
	}

	#service-visual img {
		height: auto;
	}
}

/* Sitewide: Elementor writes a container's vertical padding to --padding-top
   and --padding-bottom, then the theme's own .e-con padding shorthand resets
   both, so section padding set in Elementor never renders. Not case-study
   specific — other pages' sections depend on this too. */
.elementor .e-con {
	padding-block-start: var(--padding-top, 0px);
	padding-block-end: var(--padding-bottom, 0px);
}

/* ---------------------------------------------------------------------------
   Case studies. One system across four pages: Library is the Flagship,
   Artisans / Symphony / Al Ain are the Focus variant.

   Every hook is an element id or a widget class. Elementor renders a
   container's _element_id and silently DROPS its _css_classes on this stack,
   so container styling must key off the id (prefix match — the build appends
   a counter). Widgets take classes normally.
--------------------------------------------------------------------------- */

:root {
	--cs-ink: #101010;
	--cs-hairline: rgba(16, 16, 16, 0.12);
	--cs-surface: #f7f6f4;
	--cs-quiet: #6b6b6b;
}

/* Every cs-* section is content_width: full at the Elementor level, and full
   never renders an .e-con-inner wrapper at all (checked on the live DOM —
   zero exist on any cs-* section, on any of the four pages). Every rule in
   this file that used to target "> .e-con-inner" was dead code sitting on
   top of a working page: nothing centered content to the site's measure,
   and nothing capped the double padding that comment used to describe
   either, because there was never a wrapper for either fix to land on.
   The section itself is what's on screen, so the measure is applied as
   padding on the section — padding paints inside the section's own
   background/image, so the background still bleeds full width while the
   content column centers to ~1290px. cs-hero and cs-gallery keep full-bleed
   content and are excluded below (hero sets its own inline padding in its
   dedicated block further down).

   `[id^="cs-"]` alone is specificity 0,1,0 — identical to the theme's own
   `.e-con` padding shorthand, so it's a cascade-order coin flip and the
   theme was winning. Every cs-* section IS an `.e-con`, so qualifying with
   it (`.e-con[id^="cs-"]`, 0,2,0) beats the theme regardless of load order
   while staying below Elementor's per-element CSS. */
.e-con[id^="cs-"] {
	padding-block: 64px 32px;
	padding-inline: max(24px, calc((100% - 1290px) / 2));
}

/* The cadence. Ink bands and the dark full-bleed film carry their own ground
   and force white text — the theme's own heading/paragraph color otherwise
   wins by inheritance rules alone. */
#cs-glance,
#cs-results,
#cs-film {
	background: var(--cs-ink);
}

#cs-hero,
#cs-hero h1,
#cs-hero h2,
#cs-hero h3,
#cs-hero .elementor-heading-title,
#cs-hero p,
#cs-glance,
#cs-glance h1,
#cs-glance h2,
#cs-glance h3,
#cs-glance .elementor-heading-title,
#cs-glance p,
#cs-results,
#cs-results h1,
#cs-results h2,
#cs-results h3,
#cs-results .elementor-heading-title,
#cs-results p,
#cs-film,
#cs-film h1,
#cs-film h2,
#cs-film h3,
#cs-film .elementor-heading-title,
#cs-film p {
	color: #fff;
}

#cs-film {
	padding-block: 64px;
}

/* The hero's IMAGE bleeds (it's the section's own background) but its
   CONTENT is meant to sit at the same measure as every reading section —
   those are different things. Zeroing padding-inline here zeroed both,
   clipping the H1 at the viewport edge. #cs-hero no longer appears in this
   exclusion: it now falls through to .e-con[id^="cs-"]'s own
   padding-inline formula below. Only #cs-gallery's stills genuinely
   bleed edge to edge. */
.e-con#cs-hero,
.e-con#cs-gallery {
	padding-block: 0;
}

.e-con#cs-gallery {
	padding-inline: 0;
}

/* The measure. Body copy ran the full container — about 140 characters a
   line. The class sits on the widget wrapper itself. */
.kre-measure {
	max-width: 68ch;
}

/* ---------------------------------------------------------------------------
   Browser surfaces (E). Text selection, focus ring and link underlines were
   still the browser default here — belonging to no design system. Scoped to
   [id^="cs-"] rather than :root so this doesn't restyle selection/focus on
   the rest of the site without that being asked for.
--------------------------------------------------------------------------- */
[id^="cs-"] ::selection {
	background: var(--primary);
	color: #fff;
}

[id^="cs-"] :focus-visible {
	outline: 2px solid var(--primary);
	outline-offset: 2px;
}

[id^="cs-"] a {
	text-underline-offset: 0.15em;
}

/* Eyebrow. Small caps, letterspaced, brand red, above a section title. */
.kre-eyebrow .elementor-heading-title {
	font-family: var(--font-primary);
	font-weight: 500;
	font-size: 12px;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--primary);
}

/* Elementor's per-element generated margin outspecifies a plain class, same
   story as the padding fix above — the eyebrow sat flush on the title it
   labels without this. */
.elementor-widget.kre-eyebrow {
	margin-block-end: 12px !important;
}

/* Brand red reads muddy on the ink bands; a lightened red keeps the eyebrow's
   hierarchy without going all the way to white. The hero and the film keep
   plain translucent white — they already carry a photograph or a player.
   Derived from --primary rather than a hand-picked hex so it follows a brand
   change; #ff6b6e (the old hand-lightened value) stays as the fallback for
   a browser without color-mix() support. */
#cs-glance .kre-eyebrow .elementor-heading-title,
#cs-results .kre-eyebrow .elementor-heading-title {
	color: #ff6b6e;
	color: color-mix(in srgb, var(--primary) 70%, white);
}

#cs-hero .kre-eyebrow .elementor-heading-title,
#cs-film .kre-eyebrow .elementor-heading-title {
	color: rgba(255, 255, 255, 0.75);
}

/* Section title, used by cs-location, cs-film (Focus), cs-results, cs-why. */
.kre-section-title .elementor-heading-title {
	font-family: var(--font-primary);
	font-size: clamp(1.75rem, 3vw, 2.25rem);
	font-weight: 700;
	line-height: 1.2;
}

/* Lists that used to be bullet characters inside one text block. Used by
   cs-approach, cs-location and cs-results.

   The client's own eye caught this: the red dot sat ON the first letter of
   every item. Cause, measured live — Elementor's own
   `.elementor-widget .elementor-icon-list-item { padding: 0 }`
   (assets/css/custom-widget-icon-list.min.css) ties this rule at the same
   specificity (0,2,0) and loads AFTER this stylesheet, so it won the
   padding-left that made room for the dot while leaving the dot itself
   (a different selector) untouched. Qualifying with `.elementor-widget`
   raises this to (0,3,0), which wins regardless of load order — the actual
   cause, not a !important patch over it. */
.elementor-widget.kre-list .elementor-icon-list-item {
	position: relative;
	padding-left: 18px;
	margin-block-end: 8px;
	align-items: flex-start;
}

.elementor-widget.kre-list .elementor-icon-list-item::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.62em;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--primary);
}

.elementor-widget.kre-list .elementor-icon-list-icon {
	display: none;
}

/* cs-results is the one section that puts a .kre-list on the ink band; its
   text isn't a heading or a <p>, so the white-text rule above misses it. */
#cs-results .elementor-icon-list-text {
	color: #fff;
}

/* Card. Off-white surface, hairline border, no shadow — matches the six
   service cards on Our Services. */
.kre-card-label .elementor-heading-title {
	font-size: 11px;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--cs-quiet);
}

/* Measured live: the card's own children shared one uniform 10px container
   gap above and below the title, so it read as floating rather than
   introducing the copy under it. A few px more above than below (E). */
.kre-card-title .elementor-heading-title {
	font-size: 22px;
	line-height: 1.25;
	margin-block-start: 6px;
}

/* ---------------------------------------------------------------------------
   cs-hero. Full-bleed photograph, dark scrim, content anchored to the foot.

   The scrim must clear WCAG AA for white text over the LIGHTEST of the four
   hero stills (the Al Ain aerial and the Artisans kandura ensemble are both
   light) while still leaving the photograph itself visible — a scrim strong
   enough to pass contrast three times over just obliterates the imagery it's
   sitting on. Measured against the actual four stills (gradient alpha
   composited over the brightest pixel per row, worst case for white type):
   .30/.68/.84 -> 7.09:1, real margin above the 4.5:1 floor, and the picture
   roughly 2.3x more visible behind the headline than a heavier wash. This
   ramps to 68%+ by the point the text block actually sits, which is always
   in the lower half since the content is bottom-anchored.
--------------------------------------------------------------------------- */

/* #cs-hero's own flex-direction defaults to column (verified live — every
   Elementor container here defaults to column, same reason the F1 fix above
   exists). align-items controls the CROSS axis, which in a column is
   horizontal — so "align-items: flex-end" was pinning the title to the
   right edge (measured left: 1234px at a 1920 viewport) instead of anchoring
   it to the foot. justify-content is the MAIN axis in a column (vertical) —
   that's the property that actually means "bottom". content_width: full
   never renders an .e-con-inner wrapper (see the shared cs-* comment above),
   so the stacking context lives directly on the section. No padding-inline
   here — the section's own background bleeds, but the content measure
   (same ~1290px as every reading section) comes from .e-con[id^="cs-"]
   above; a flat 24px here previously outranked that (an ID beats a bare
   class regardless of source order) and clipped the H1 at the edge. */
#cs-hero {
	position: relative;
	overflow: hidden;
	min-height: 640px;
	display: flex;
	justify-content: flex-end;
	padding-block-end: 56px;
	background-color: var(--cs-ink);
}

#cs-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		180deg,
		rgba(16, 16, 16, 0.3) 0%,
		rgba(16, 16, 16, 0.68) 40%,
		rgba(16, 16, 16, 0.84) 100%
	);
	pointer-events: none;
	z-index: 0;
}

/* Title and subhead. The largest type on the page — an explicit size here,
   not a theme H1 default that could change under it later. */
.kre-cs-title .elementor-heading-title {
	font-size: clamp(2.25rem, 5vw, 3.75rem);
	font-weight: 700;
	line-height: 1.08;
	margin-block-end: 16px;
}

.kre-cs-subhead {
	max-width: 58ch;
	font-size: 18px;
	line-height: 1.5;
}

/* Meta bar. CLIENT / ROLE / SCALE / TEAM (4-up Flagship) or CLIENT / PROJECT
   / PRODUCED BY (3-up Focus), one scale for every label, one for every
   value — explicit classes now, not nth-of-type odd/even. */
#cs-hero [id^="kre-meta-bar-"] {
	display: flex;
	flex-wrap: wrap;
	gap: 24px 48px;
	margin-block-start: 40px;
	padding-block-start: 24px;
	border-block-start: 1px solid rgba(255, 255, 255, 0.22);
}

/* Without a grow/basis of its own, a cell keeps flex-grow:0; flex-basis:auto
   and inherits width:100% from .e-con-full, so each cell wraps onto its own
   line instead of sharing the row — the same fix as the stat cells (which
   already carry theirs via the "flex" shorthand directly). Works for both
   the Focus pages' 3 fields and Library's 4. */
#cs-hero .e-con[id^="kre-meta-cell-"] {
	min-width: 120px;
	--flex-grow: 1;
	--flex-basis: 0;
}

#cs-hero .kre-meta-label .elementor-heading-title {
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.62);
	margin-block-end: 4px;
}

#cs-hero .kre-meta-value .elementor-heading-title {
	font-size: 16px;
	font-weight: 400;
	line-height: 1.4;
}

/* ---------------------------------------------------------------------------
   cs-glance. Ink band, edge to edge within the section's own measure.

   Fixes: equal height so a two-line stat no longer makes the row ragged
   (kre-stat-value--long drops one type step so long values stay one line);
   full width via flex so 3 or 5 stats both fill the band instead of
   stopping partway across.
--------------------------------------------------------------------------- */

#cs-glance [id^="kre-row-stats-"] {
	display: flex;
	flex-wrap: wrap;
	width: 100%;
}

#cs-glance .e-con[id^="kre-stat-"] {
	flex: 1 1 0;
	min-width: 140px;
	padding-inline: 28px;
	border-left: 1px solid rgba(255, 255, 255, 0.16);
	text-align: center;
}

#cs-glance .e-con[id^="kre-stat-"]:first-child {
	border-left: 0;
	padding-inline-start: 0;
}

.kre-stat-value .elementor-heading-title {
	font-family: var(--font-primary);
	font-size: clamp(2.5rem, 5vw, 4rem);
	font-weight: 900;
	line-height: 1;
	font-variant-numeric: tabular-nums;
}

.kre-stat-value--long .elementor-heading-title {
	font-size: clamp(1.6rem, 3vw, 2.5rem);
}

#cs-glance .kre-stat-caption .elementor-heading-title {
	margin-block-start: 10px;
	font-size: 13px;
	letter-spacing: 0.04em;
	color: rgba(255, 255, 255, 0.62);
}

/* ---------------------------------------------------------------------------
   cs-brief. One measure, light. Eyebrow, large lede, body.
--------------------------------------------------------------------------- */

.kre-lede .elementor-heading-title {
	font-family: var(--font-primary);
	font-size: clamp(1.5rem, 2.4vw, 2rem);
	font-weight: 600;
	line-height: 1.3;
	margin-block-end: 16px;
}

/* ---------------------------------------------------------------------------
   cs-location. Library only. A 26-item list as a flowing, columned run
   rather than one screen-and-a-half-long ribbon.

   This is the one list that carries no dot: 26 place names read as an index,
   not a set of distinct action items, so the marker the generic .kre-list
   rule draws is noise here. Suppressed explicitly (both selectors below beat
   .elementor-widget.kre-list on specificity via the #cs-location id, so the
   fix above can't un-suppress it by accident) rather than left to whichever
   rule happens to win the cascade — the client-reported bug above was
   exactly that kind of accident.
--------------------------------------------------------------------------- */

#cs-location .kre-list .elementor-icon-list-items {
	columns: 3;
	column-gap: 40px;
}

#cs-location .kre-list .elementor-icon-list-item {
	break-inside: avoid;
	padding-left: 0;
}

#cs-location .kre-list .elementor-icon-list-item::before {
	display: none;
}

/* The "(Al Ain)" qualifier reads as part of the place name at full weight;
   it's subordinate information, not a second name. */
#cs-location .kre-list-tag {
	font-size: 0.85em;
	color: var(--cs-quiet);
}

@media (max-width: 1024px) {
	#cs-location .kre-list .elementor-icon-list-items {
		columns: 2;
	}
}

@media (max-width: 600px) {
	#cs-location .kre-list .elementor-icon-list-items {
		columns: 1;
	}
}

/* ---------------------------------------------------------------------------
   cs-film. Dark, full-bleed ground. Focus: eyebrow, title, description,
   player. Flagship: eyebrow, intro, three cutdown cards in a row.
--------------------------------------------------------------------------- */

/* display:grid here was inert — Elementor drives this container's
   display/flex-direction through per-element CSS custom properties, not
   direct declarations, so a grid never actually applied; the container was
   flexing as a column all along. The row itself is now a real flex row via
   the container's own settings (build-case-study.php's kre_flex_row());
   sizing the children is still done here, through the same variable system
   so it survives (a plain property on the child loses the same way). */
#cs-film [id^="kre-grid-cutdowns-"] {
	gap: 32px;
	margin-block-start: 40px;
}

#cs-film .e-con[id^="kre-cutdown-"] {
	display: flex;
	flex-direction: column;
	gap: 10px;
	--flex-grow: 1;
	--flex-basis: 260px;
}

#cs-film .kre-card-title .elementor-heading-title {
	font-size: 18px;
	font-weight: 600;
}

/* The video widget was sitting 50px left of its own container on one page,
   overhanging the measure everything else lines up on. */
#cs-film .elementor-widget-video {
	margin-inline: 0;
	max-width: 100%;
}

#cs-film iframe,
#cs-film video {
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	display: block;
}

/* ---------------------------------------------------------------------------
   cs-approach. Phase cards, equal height, in a row. Label carrying phase and
   duration, a title, a real bulleted list with brand-red markers.
--------------------------------------------------------------------------- */

/* display:grid here was inert, same story as cs-film's cutdowns above — the
   row is a real flex row via the container's own settings now; sizing goes
   on the children below through the variable system. */
[id^="kre-grid-cards-"] {
	gap: 24px;
	margin-block-start: 32px;
}

/* .e-con[id^="kre-card-"] alone is still only 0,2,0 — tied with Elementor's
   own .e-con.e-flex baseline (--flex-basis:auto; --flex-grow:0), so it came
   down to load order and Elementor won (computed flex-grow/basis stayed
   0/auto, cards sized to content and wrapped unevenly). #cs-glance's stat
   rule escaped this only because it happens to carry a section id, taking
   it to 1,2,0. kre-card only ever appears inside #cs-approach (checked:
   Library's cs-film cutdowns use the separate kre-cutdown- id prefix, not
   this one, so this scoping can't miss them). */
/* 240px let 5 cards (Al Ain) almost-but-not-quite fit 5-up in the 1290px
   measure (5*240 + 4*24 gap = 1296px), wrapping 4 + 1 — a lone trailing
   card. 380px wraps Al Ain to a balanced 3 + 2 (3*380 + 2*24 = 1188px) while
   every other page's card count (Artisans 2, Symphony 3, Library 3) still
   fits on one line at 380px (3*380 + 2*24 = 1188px, same math). */
#cs-approach .e-con[id^="kre-card-"] {
	background: var(--cs-surface);
	border: 1px solid var(--cs-hairline);
	border-radius: 4px;
	padding: 28px;
	display: flex;
	flex-direction: column;
	gap: 10px;
	--flex-grow: 1;
	--flex-basis: 380px;
}

/* ---------------------------------------------------------------------------
   cs-delivered. Library and Al Ain. Term / definition pairs, two up.
--------------------------------------------------------------------------- */

/* display:grid here was inert, same story as above. */
[id^="kre-grid-pairs-"] {
	gap: 28px 40px;
	margin-block-start: 32px;
}

#cs-delivered .e-con[id^="kre-pair-"] {
	--flex-grow: 1;
	--flex-basis: 240px;
}

.kre-pair-term .elementor-heading-title {
	font-size: 15px;
	font-weight: 600;
	letter-spacing: 0.02em;
	margin-block-end: 6px;
}

.kre-pair-def {
	color: var(--cs-quiet);
}

.kre-pair-footer {
	margin-block-start: 24px;
	padding-block-start: 20px;
	border-block-start: 1px solid var(--cs-hairline);
	color: var(--cs-quiet);
	font-size: 15px;
}

/* ---------------------------------------------------------------------------
   cs-challenges. Artisans and Symphony. Rows, challenge left in ink,
   solution right in grey, hairline between rows. The second piece of old CSS
   worth carrying forward, rewritten to the shared hairline token and to the
   rows' own ids now that they have one — no more relying on ">.e-con".
--------------------------------------------------------------------------- */

[id^="kre-challenge-row-"] {
	display: grid;
	grid-template-columns: 1fr 1.4fr;
	gap: 0 40px;
	padding-block: 22px;
	border-block-start: 1px solid var(--cs-hairline);
	align-items: start;
}

[id^="kre-challenge-row-"]:last-child {
	border-block-end: 1px solid var(--cs-hairline);
}

.kre-challenge-head .elementor-heading-title {
	font-weight: 600;
}

.kre-challenge-body {
	color: var(--cs-quiet);
}

@media (max-width: 767px) {
	[id^="kre-challenge-row-"] {
		grid-template-columns: 1fr;
		gap: 8px;
		padding-block: 18px;
	}

	.kre-challenge-body {
		padding-inline-start: 16px;
		border-inline-start: 2px solid var(--primary);
	}
}

/* ---------------------------------------------------------------------------
   cs-results. Ink band. Outcomes as a real list, then a status pill.
--------------------------------------------------------------------------- */

.kre-pill {
	display: inline-block;
	margin-block-start: 20px;
	padding: 10px 20px;
	border: 1px solid rgba(255, 255, 255, 0.4);
	border-radius: 999px;
}

.kre-pill .elementor-heading-title {
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: #fff;
}

/* ---------------------------------------------------------------------------
   cs-gallery. Full-bleed still strip, three or four frames, fixed aspect,
   equal heights — the earlier version of this rule exists because an
   earlier gallery grew to 1964px with three ragged heights.
--------------------------------------------------------------------------- */

/* display:grid here was inert, same story as above — the strip is a real
   flex row via the container's own settings now. Stills are plain image
   widgets (no per-item container/id), so sizing targets the widget wrapper
   directly, still through the variable system. */
#cs-gallery [id^="kre-strip-stills-"] > .elementor-widget-image {
	--flex-grow: 1;
	--flex-basis: 300px;
}

[id^="kre-strip-stills-"] img {
	width: 100%;
	height: 420px;
	object-fit: cover;
	display: block;
}

@media (max-width: 767px) {
	[id^="kre-strip-stills-"] img {
		height: 240px;
	}
}

/* ---------------------------------------------------------------------------
   cs-why. Artisans, Symphony, Al Ain. One statement, one measure, larger
   than body — the page's closing argument.
--------------------------------------------------------------------------- */

.kre-statement p {
	font-size: clamp(1.25rem, 2.2vw, 1.6rem);
	line-height: 1.5;
	font-weight: 500;
}

/* ---------------------------------------------------------------------------
   cs-credits. Library only. Three team cards: portrait, role, name, bio.
   The three headshots don't exist yet — a typographic monogram sized and
   cropped exactly as a photograph will be, so the swap is a one-field edit.
--------------------------------------------------------------------------- */

/* display:grid here was inert, same story as above. */
[id^="kre-grid-people-"] {
	gap: 32px;
	margin-block-start: 32px;
}

#cs-credits .e-con[id^="kre-person-"] {
	background: var(--cs-surface);
	border: 1px solid var(--cs-hairline);
	border-radius: 4px;
	padding: 28px;
	text-align: center;
	--flex-grow: 1;
	--flex-basis: 240px;
}

[id^="kre-portrait-"] {
	width: 96px;
	height: 96px;
	margin-inline: auto;
	margin-block-end: 16px;
	border-radius: 50%;
	background: #fff;
	border: 1px solid var(--cs-hairline);
	display: flex;
	align-items: center;
	justify-content: center;
}

.kre-monogram .elementor-heading-title {
	font-size: 28px;
	font-weight: 700;
	color: var(--primary);
}

/* Same measured 20px/20px symmetric gap as the card title above (E). */
.kre-person-name .elementor-heading-title {
	font-size: 17px;
	font-weight: 600;
	margin-block-start: 6px;
}

.kre-person-role .elementor-heading-title {
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--cs-quiet);
}

/* ---------------------------------------------------------------------------
   Small screens.
--------------------------------------------------------------------------- */

@media (max-width: 767px) {
	.e-con[id^="cs-"] {
		padding-block: 40px 24px;
	}

	[id^="kre-card-"],
	[id^="kre-person-"] {
		padding: 20px;
	}

	#cs-hero {
		min-height: 520px;
	}

	#cs-glance [id^="kre-row-stats-"] {
		flex-direction: column;
	}

	#cs-glance [id^="kre-stat-"] {
		border-left: 0;
		border-block-start: 1px solid rgba(255, 255, 255, 0.16);
		padding: 20px 0;
		text-align: left;
	}

	#cs-glance [id^="kre-stat-"]:first-child {
		border-block-start: 0;
		padding-block-start: 0;
	}

	/* min-width: 120px on the desktop rule (see #cs-hero .e-con[id^="kre-meta-cell-"]
	   above) leaves 3 cells too wide for a 313px content column once gaps are
	   counted, wrapping 2 + 1. One cell per row reads as deliberate instead;
	   works for Library's 4 fields the same as the Focus pages' 3. */
	#cs-hero .e-con[id^="kre-meta-cell-"] {
		--flex-basis: 100%;
	}
}

/* ---------------------------------------------------------------------------
   Homepage hero on a phone
   The hero pins its buttons with align-items: flex-end, which reads as
   deliberate bottom-right placement over a full-width video on a desktop. On a
   375px screen it leaves both buttons five pixels from the right edge with the
   whole width empty to their left. Centre them and give them room.
--------------------------------------------------------------------------- */
@media (max-width: 767px) {
	.elementor-element-6188963 > .e-con-inner,
	.elementor-element-6188963 > .e-con {
		align-items: center;
		padding-inline: 20px;
		gap: 0.75rem;
	}
}

/* ---------------------------------------------------------------------------
   Marketing pages: readable text on a phone
   Audited 2026-08-28 against the generated per-page CSS at the 767px
   breakpoint, element by element rather than in aggregate — the aggregate
   figures were misleading, because the largest "type" turned out to be icon
   sizing and most of the spread was legitimate hierarchy.

   What was left is genuinely too small to read on a phone: the recent-work
   slider's subtitle at 10px, and a handful of labels and button faces at 12px.
   Only those are raised, and only at mobile widths.
--------------------------------------------------------------------------- */
@media (max-width: 767px) {

	/* Home: the recent-work slider subtitle ("Media - 2022") at 10px. */
	.elementor-6 .elementor-element-77b2ee17 .subtitle {
		font-size: 12px;
		letter-spacing: 0.06em;
	}

	/* Home: button face at 12px. */
	.elementor-6 .elementor-element-153b68e .wcf__btn a {
		font-size: 13px;
	}

	/* Our Work: card text and titles at 12px. */
	.elementor-9214 .elementor-element-343e28c .wcf--text,
	.elementor-9214 .elementor-element-2190bbf .title {
		font-size: 13px;
	}

	/* Tap targets. A link under the 44px guideline is hard to hit accurately;
	   giving it a minimum height costs nothing visually. */
	.elementor-6 a.elementor-button,
	.elementor-3331 a.elementor-button,
	.elementor-9214 a.elementor-button,
	.elementor-3304 a.elementor-button,
	.elementor-2474 a.elementor-button {
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}
}

/* ---------------------------------------------------------------------------
   Meta links and post tags
   The addons plugin hovers these to #f0b849, a yellow that belongs to no part
   of this brand. It is the only yellow hover on the site — it reaches the
   category and tag lists on portfolio and blog single pages.
--------------------------------------------------------------------------- */

.wcf--meta-list li a:hover,
.wcf--meta-list.style-1 li a:hover,
.wcf--meta-list.style-2 li a:hover,
.wcf--post-tags li a:hover {
	color: var(--primary);
}

/* ---------------------------------------------------------------------------
   Recent work tiles
   The client asked for the category/year line under each title to go. The
   caption fields are empty, but the widget still prints the paragraph, and an
   empty <p> keeps its line box and the gap above it.
--------------------------------------------------------------------------- */

.gallery--slider .content .desc:empty {
	display: none;
}

/* ---------------------------------------------------------------------------
   "Have a story worth telling?"
   The closing call to action, under the logo wall and under every project's
   previous/next links. The buttons are the hero pair, rebuilt for a light
   section: the hero's ghost button is a white translucent pane, which on white
   is nothing at all.
--------------------------------------------------------------------------- */

.kre-story-cta {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1.6rem;
	padding: 4rem 20px;
	text-align: center;
}

.kre-story-cta__heading {
	margin: 0;
	font-family: var(--font-secondary);
	font-size: clamp(1.75rem, 3vw, 2.5rem);
	line-height: 1.15;
	color: #121212;
}

.kre-story-cta__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 1rem;
}

.kre-story-cta__btn {
	font-family: var(--font-primary);
	font-weight: 500;
	font-size: 0.875rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 1.05rem 2.4rem;
	border-radius: 999px;
	border: 1px solid transparent;
	min-height: 44px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
}

.kre-story-cta__btn:hover {
	transform: translateY(-2px);
}

.kre-story-cta__btn--primary {
	background: var(--primary);
	border-color: var(--primary);
	color: #fff;
}

.kre-story-cta__btn--primary:hover {
	background: #121212;
	border-color: #121212;
	color: #fff;
}

.kre-story-cta__btn--ghost {
	background: transparent;
	border-color: rgba(18, 18, 18, 0.25);
	color: #121212;
}

.kre-story-cta__btn--ghost:hover {
	border-color: #121212;
	color: #121212;
}

/* The services section the hero button points at sits under a fixed header. */
#service {
	scroll-margin-top: 90px;
}

/* ---------------------------------------------------------------------------
   Entrance reveals
   The addons plugin animates Elementor widgets, but a shortcode is one widget
   to it, so the timeline's milestones and the quote cards would arrive as a
   block. These carry the theme's own numbers — 40px, three quarters of a
   second, an ease-out curve — so the custom sections move like the rest of the
   site rather than to a timing of their own. See js/reveal.js.
--------------------------------------------------------------------------- */

.kre-reveal {
	opacity: 0;
	transform: translateY(40px);
	transition: opacity 0.75s cubic-bezier(0.22, 0.61, 0.36, 1), transform 0.75s cubic-bezier(0.22, 0.61, 0.36, 1);
	will-change: opacity, transform;
}

.kre-reveal.is-revealed {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	.kre-reveal {
		opacity: 1;
		transform: none;
		transition: none;
	}
}

/* A quote attributed to a company rather than a person carries no name line,
   so the company takes the name's weight. */
.kre-quotes__role--lead {
	font-family: var(--font-secondary);
	font-weight: 900;
	font-size: 0.9rem;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: #111113;
}

/* ---------------------------------------------------------------------------
   Multi-film project pages
   Most projects carry one film. A series carries its episodes, and a few
   shoots delivered two cuts of the same piece. Stacked full width those run
   the page long — My Abu Dhabi Experience is six screens of player — and read
   as a queue rather than a set. Two columns holds a four-episode series to two
   rows.

   The count is read off the DOM rather than recorded anywhere: a container
   whose second child is a film is a container holding more than one. So a
   single-film project is untouched, and a project picks the grid up by itself
   the moment a second film is added in Elementor.
--------------------------------------------------------------------------- */

.single-krenative-portfolio .e-con-inner:has(> .elementor-widget-video:nth-child(2)) {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	align-items: start;
}

/* One column on a phone — half of a half is not a film. */
@media (max-width: 767px) {
	.single-krenative-portfolio .e-con-inner:has(> .elementor-widget-video:nth-child(2)) {
		grid-template-columns: 1fr;
	}
}
