/**
 * Oplus — City Experience.
 * Taxonomy `property_city`. Loaded nowhere else.
 *
 * WHAT THIS REPLACES
 * ------------------
 * The generic Houzez taxonomy shell: an H1, an empty term description, and a
 * single paginated column of list cards with a sidebar. It gave a market query
 * a listing answer.
 *
 * COLOUR
 * ------
 * Same system as the project experience, so a visitor moving from a city into
 * a project inside it stays on one site. Light editorial body; dark bands used
 * exactly twice — off-plan and the closing ask. Each is a moment where the page
 * changes what it is doing, and the surface change is what marks it.
 *
 * Green is load-bearing, never decorative: CTAs, the active dock chip, key
 * numerals, and the off-plan tag. Nothing else.
 *
 * DIRECTION
 * ---------
 * Written logical-first — `inline-start`/`inline-end`, `padding-inline`,
 * `text-align: start` — so the Arabic build needs no mirrored stylesheet. The
 * two places that must mirror physically are the area rail's scroll direction
 * and its arrow keys; both are handled in JS via `oplusCx.rtl`.
 *
 * MOTION
 * ------
 * Reveals are an IntersectionObserver adding `.is-in`. The rail's depth effect
 * is CSS 3D driven by a scroll listener writing one custom property per card.
 * No animation library, no WebGL: this page loads a hundred property
 * photographs and the main thread belongs to them. `prefers-reduced-motion`
 * holds every end state and kills every transform.
 *
 * SCOPE
 * -----
 * Every rule is under `.cx` or a `cx-` class, so nothing leaks into the header,
 * the footer or the Houzez chrome. Tokens are on :root because the sticky dock
 * is fixed and must not resolve its variables against a transformed ancestor.
 */

/* =========================================================================
   1. TOKENS
   ====================================================================== */

:root {
	/* Ink */
	--cx-ink: #0d1418;
	--cx-body: #4a5560;
	--cx-faint: #737f89;

	/* Brand */
	--cx-green: #00a651;
	--cx-green-deep: #00813f;
	--cx-green-lift: #16c368;
	--cx-tint: #edf7f1;

	/* Surfaces */
	--cx-paper: #ffffff;
	--cx-mist: #f5f8f6;
	--cx-night: #0a1013;
	--cx-night-2: #111a1e;

	/* Lines */
	--cx-line: #e3e9e5;
	--cx-line-2: #cfd8d3;
	--cx-line-night: rgba(255, 255, 255, 0.14);

	/* Type — the project page's stack, for the reasons documented there. */
	--cx-display: "Manrope", "Tajawal", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
	--cx-text: "Manrope", "Tajawal", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;

	/* Fluid type. One clamp per step; no breakpoint overrides for size. */
	--cx-t-display: clamp(2.25rem, 1.1rem + 4.8vw, 4.5rem);
	--cx-t-h2: clamp(1.6875rem, 1.2rem + 2vw, 2.75rem);
	--cx-t-h3: clamp(1.125rem, 1.02rem + 0.5vw, 1.375rem);
	--cx-t-body: clamp(1rem, 0.97rem + 0.14vw, 1.0625rem);
	--cx-t-lede: clamp(1.0625rem, 0.96rem + 0.45vw, 1.25rem);
	--cx-t-meta: 0.8125rem;
	--cx-t-micro: 0.6875rem;

	/* Rhythm */
	--cx-band: clamp(3.5rem, 2rem + 6vw, 7rem);
	--cx-gap: clamp(1rem, 0.6rem + 1.4vw, 1.75rem);
	--cx-radius: 14px;
	--cx-radius-lg: 22px;

	/* Depth. Layered rather than one blur — a single large shadow reads as
	   fog; two reads as a card sitting on a surface. */
	--cx-shadow: 0 1px 2px rgba(13, 20, 24, 0.05), 0 8px 24px rgba(13, 20, 24, 0.07);
	--cx-shadow-lift: 0 2px 6px rgba(13, 20, 24, 0.07), 0 20px 48px rgba(13, 20, 24, 0.14);

	--cx-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
	--cx-dock-h: 60px;

	/*
	 * The site header is `position: sticky; z-index: 1000` and 80px tall — the
	 * same figure the project experience keeps in `--px-header-h`. The dock
	 * parks directly beneath it rather than at the top of the viewport, or it
	 * scrolls underneath and disappears.
	 */
	--cx-header-h: 80px;
}

@media (max-width: 991px) {
	:root {
		/* The header collapses to its mobile bar below the lg breakpoint. */
		--cx-header-h: 64px;
	}
}

/* =========================================================================
   2. SHELL
   ====================================================================== */

.cx {
	font-family: var(--cx-text);
	font-size: var(--cx-t-body);
	line-height: 1.65;
	color: var(--cx-body);
	background: var(--cx-paper);
	overflow-x: clip;
}

.cx *,
.cx *::before,
.cx *::after {
	box-sizing: border-box;
}

.cx-wrap {
	width: min(100% - 2.5rem, 1240px);
	margin-inline: auto;
}

.cx-wrap--narrow {
	width: min(100% - 2.5rem, 860px);
}

.cx-band {
	padding-block: var(--cx-band);
	/* Anchors land below the header AND the dock, instead of behind both. */
	scroll-margin-block-start: calc(var(--cx-header-h) + var(--cx-dock-h) + 12px);
}

.cx-band--paper { background: var(--cx-paper); }
.cx-band--mist  { background: var(--cx-mist); }

.cx-band--night {
	background: var(--cx-night);
	color: rgba(255, 255, 255, 0.72);
}

/* Type ------------------------------------------------------------------ */

.cx h1,
.cx h2,
.cx h3 {
	font-family: var(--cx-display);
	color: var(--cx-ink);
	line-height: 1.12;
	letter-spacing: -0.02em;
	margin: 0;
	text-wrap: balance;
}

.cx-band--night h2,
.cx-band--night h3 {
	color: #fff;
}

.cx-h2 {
	font-size: var(--cx-t-h2);
	font-weight: 800;
}

.cx-eyebrow {
	font-size: var(--cx-t-micro);
	font-weight: 700;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--cx-green-deep);
	margin: 0 0 0.75rem;
}

.cx-band--night .cx-eyebrow {
	color: var(--cx-green-lift);
}

.cx-sub {
	font-size: var(--cx-t-body);
	color: var(--cx-faint);
	margin: 0.75rem 0 0;
	max-width: 62ch;
}

.cx-band--night .cx-sub {
	color: rgba(255, 255, 255, 0.6);
}

.cx-prose p {
	margin: 0 0 1rem;
	font-size: var(--cx-t-lede);
	line-height: 1.72;
	color: var(--cx-body);
}

.cx-prose p:last-child { margin-bottom: 0; }

/* Section heads --------------------------------------------------------- */

.cx-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--cx-gap);
	margin-bottom: clamp(1.75rem, 1rem + 2vw, 3rem);
	flex-wrap: wrap;
}

.cx-head--stack {
	display: block;
}

.cx-icon,
.cx-i {
	width: 20px;
	height: 20px;
	flex: none;
}

/* =========================================================================
   3. BUTTONS
   ====================================================================== */

.cx-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	/* 48px tall at the default font size — above the 44px touch minimum with
	   room for the focus ring to sit outside the hit area. */
	min-height: 48px;
	padding-inline: 1.5rem;
	padding-block: 0.75rem;
	border: 1px solid transparent;
	border-radius: 999px;
	font-family: var(--cx-display);
	font-size: 0.9375rem;
	font-weight: 700;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.2s var(--cx-ease), border-color 0.2s var(--cx-ease),
		color 0.2s var(--cx-ease), transform 0.2s var(--cx-ease);
}

.cx-btn--solid {
	background: var(--cx-green);
	border-color: var(--cx-green);
	color: #fff;
}

.cx-btn--solid:hover,
.cx-btn--solid:focus-visible {
	background: var(--cx-green-deep);
	border-color: var(--cx-green-deep);
	color: #fff;
	transform: translateY(-1px);
}

.cx-btn--ghost {
	background: transparent;
	border-color: var(--cx-line-2);
	color: var(--cx-ink);
}

.cx-btn--ghost:hover,
.cx-btn--ghost:focus-visible {
	border-color: var(--cx-ink);
	color: var(--cx-ink);
}

.cx-btn--onnight {
	border-color: var(--cx-line-night);
	color: #fff;
}

.cx-btn--onnight:hover,
.cx-btn--onnight:focus-visible {
	border-color: rgba(255, 255, 255, 0.5);
	background: rgba(255, 255, 255, 0.06);
	color: #fff;
}

/* One focus treatment for the whole page. Never removed — only replaced with
   something more visible than the browser default. */
.cx a:focus-visible,
.cx button:focus-visible,
.cx summary:focus-visible,
.cx [tabindex]:focus-visible {
	outline: 3px solid var(--cx-green);
	outline-offset: 3px;
	border-radius: 6px;
}

.cx-band--night a:focus-visible,
.cx-band--night button:focus-visible {
	outline-color: var(--cx-green-lift);
}

/* =========================================================================
   4. HERO
   ====================================================================== */

.cx-hero {
	position: relative;
	isolation: isolate;
	display: flex;
	align-items: flex-end;
	/*
	 * Was 30rem, which put the headline, both buttons and the stat rail into
	 * about 380px of usable height once the veil was accounted for — the type
	 * had nowhere to breathe and the rail read as if it had fallen out of the
	 * layout. The hero is the page's one cinematic moment; it gets the room.
	 */
	min-height: clamp(36rem, 28rem + 26vw, 50rem);
	padding-block: clamp(4rem, 2.5rem + 6vw, 7rem) clamp(2rem, 1.25rem + 2.5vw, 3.25rem);
	background: var(--cx-night);
	color: rgba(255, 255, 255, 0.78);
	overflow: hidden;
}

.cx-hero__media {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.cx-hero__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* No fade-in. This is the LCP element; animating its opacity delays the
	   paint the metric measures. */
}

/*
 * Two stops, not one. A single flat scrim greys the photograph everywhere; a
 * vertical ramp keeps the top of the image legible and buys contrast only
 * where the type actually sits.
 */
.cx-hero__veil {
	position: absolute;
	inset: 0;
	z-index: -1;
	background:
		linear-gradient(to top, rgba(10, 16, 19, 0.94) 0%, rgba(10, 16, 19, 0.72) 38%, rgba(10, 16, 19, 0.25) 72%, rgba(10, 16, 19, 0.35) 100%);
}

.cx-hero__inner {
	position: relative;
	width: min(100% - 2.5rem, 1240px);
	margin-inline: auto;
}

/*
 * The breadcrumb belongs at the TOP of the hero, not floating just above the
 * headline. It is orientation, not content — so it is pinned to the first line
 * of the band and the headline group is pushed to the bottom by the auto
 * margin below. That is what makes the composition read as deliberate rather
 * than as four things stacked in the middle.
 */
.cx-hero__inner {
	display: flex;
	flex-direction: column;
	/*
	 * `align-self: stretch`, not `min-height: inherit`. The hero is a flex row
	 * with `align-items: flex-end`; inheriting the min-height would make the
	 * inner as tall as the hero *plus* the hero's padding and push the band
	 * open by another 7rem. Stretching fills the content box exactly, which is
	 * what the auto margin on the breadcrumb needs to work against.
	 */
	align-self: stretch;
}

.cx-crumbs {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--cx-t-meta);
	color: rgba(255, 255, 255, 0.62);
	margin: 0 0 auto;
	padding-block-end: clamp(2.5rem, 1.5rem + 4vw, 5rem);
}

.cx-crumbs a {
	color: rgba(255, 255, 255, 0.72);
	text-decoration: none;
}

.cx-crumbs a:hover { color: #fff; }

.cx-hero__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--cx-t-meta);
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--cx-green-lift);
	margin: 0 0 1rem;
}

/*
 * `.cx .cx-hero__title`, not `.cx-hero__title`.
 *
 * The base rule in §2 is `.cx h1, .cx h2, .cx h3 { color: var(--cx-ink) }` —
 * one class plus one element, which out-specifies a lone class. The hero
 * headline rendered near-black on a dark photograph and was almost unreadable.
 * Matching the element as well is what fixes it; do not "simplify" this back
 * to a single class.
 */
.cx .cx-hero__title {
	font-size: var(--cx-t-display);
	font-weight: 800;
	color: #fff;
	max-width: 18ch;
	margin: 0;
}

.cx-hero__tagline {
	font-size: var(--cx-t-lede);
	color: rgba(255, 255, 255, 0.78);
	max-width: 46ch;
	margin: 1.125rem 0 0;
}

.cx-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin-top: clamp(1.75rem, 1.2rem + 1.6vw, 2.5rem);
}

/* Stat rail ------------------------------------------------------------- */

.cx-rail {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: 1px;
	margin: clamp(2.75rem, 1.75rem + 3.5vw, 4.5rem) 0 0;
	padding: 0;
	background: var(--cx-line-night);
	border: 1px solid var(--cx-line-night);
	border-radius: var(--cx-radius);
	overflow: hidden;
	/* The photograph behind it stays visible; a solid panel here would waste
	   the hero image the page just paid to preload. */
	backdrop-filter: blur(16px);
	-webkit-backdrop-filter: blur(16px);
}

.cx-rail__item {
	background: rgba(10, 16, 19, 0.5);
	padding: 1.25rem 1.375rem 1.375rem;
}

.cx-rail__label {
	font-size: var(--cx-t-micro);
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
	margin: 0 0 0.375rem;
}

.cx-rail__value {
	font-family: var(--cx-display);
	font-size: clamp(1.5rem, 1.2rem + 1.1vw, 2.125rem);
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.02em;
	color: #fff;
	margin: 0;
	/* Tabular figures stop the rail jittering between cities whose counts have
	   different digit widths. */
	font-variant-numeric: tabular-nums;
}

.cx-rail__unit {
	font-size: 0.5em;
	font-weight: 700;
	color: var(--cx-green-lift);
	margin-inline-end: 0.35em;
	vertical-align: 0.35em;
}

/* =========================================================================
   5. DOCK
   ====================================================================== */

.cx-dock {
	position: sticky;
	/* Under the site header, never over it — hence the offset and the z-index
	   well below the header's 1000. */
	top: var(--cx-header-h);
	z-index: 40;
	background: rgba(255, 255, 255, 0.92);
	backdrop-filter: saturate(180%) blur(12px);
	-webkit-backdrop-filter: saturate(180%) blur(12px);
	border-block-end: 1px solid var(--cx-line);
}

.cx-dock__inner {
	display: flex;
	align-items: center;
	gap: 1rem;
	min-height: var(--cx-dock-h);
}

.cx-dock__list {
	display: flex;
	align-items: center;
	gap: 0.375rem;
	list-style: none;
	margin: 0;
	padding: 0;
	flex: 1 1 auto;
	overflow-x: auto;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

.cx-dock__list::-webkit-scrollbar { display: none; }

.cx-dock__chip {
	display: inline-flex;
	align-items: center;
	min-height: 38px;
	padding-inline: 0.9rem;
	border-radius: 999px;
	font-size: 0.875rem;
	font-weight: 600;
	white-space: nowrap;
	color: var(--cx-body);
	text-decoration: none;
	transition: background-color 0.2s var(--cx-ease), color 0.2s var(--cx-ease);
}

.cx-dock__chip:hover {
	background: var(--cx-mist);
	color: var(--cx-ink);
}

.cx-dock__chip.is-active {
	background: var(--cx-tint);
	color: var(--cx-green-deep);
}

.cx-dock__cta {
	flex: none;
	display: inline-flex;
	align-items: center;
	min-height: 40px;
	padding-inline: 1.125rem;
	border-radius: 999px;
	background: var(--cx-green);
	color: #fff;
	font-size: 0.875rem;
	font-weight: 700;
	text-decoration: none;
	white-space: nowrap;
	transition: background-color 0.2s var(--cx-ease);
}

.cx-dock__cta:hover {
	background: var(--cx-green-deep);
	color: #fff;
}

@media (max-width: 720px) {
	/* The chips need the whole width on a phone; the CTA is repeated at the
	   foot of the page and does not need to be here as well. */
	.cx-dock__cta { display: none; }
}

/* =========================================================================
   6. OVERVIEW
   ====================================================================== */

.cx-lede {
	max-width: 74ch;
	margin-bottom: clamp(2rem, 1.2rem + 2.4vw, 3.5rem);
}

.cx-lede .cx-h2 {
	margin-bottom: 1.25rem;
}

.cx-cards {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
	gap: var(--cx-gap);
	list-style: none;
	margin: 0;
	padding: 0;
}

.cx-card {
	padding: clamp(1.5rem, 1.1rem + 1.2vw, 2rem);
	background: var(--cx-mist);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-radius);
	transition: transform 0.28s var(--cx-ease), box-shadow 0.28s var(--cx-ease);
}

.cx-card:hover {
	transform: translateY(-3px);
	box-shadow: var(--cx-shadow);
}

.cx-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 12px;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	color: var(--cx-green-deep);
	margin-bottom: 1rem;
}

.cx-card__title {
	font-size: var(--cx-t-h3);
	font-weight: 700;
	margin-bottom: 0.5rem;
}

.cx-card__text {
	margin: 0;
	font-size: 0.9375rem;
	color: var(--cx-faint);
}

/* =========================================================================
   7. AREAS — the 3D rail

   A scroll-snap track. Native scrolling gives momentum, touch and trackpad
   gestures and correct RTL for free; JS only adds arrows, the progress bar and
   the depth. With JS off this is a plain horizontal scroller that works.
   ====================================================================== */

.cx-rail3d {
	position: relative;
	/* Full-bleed, so the rail runs to the viewport edge and reads as
	   continuing past it rather than stopping inside a container. */
	margin-inline: calc(50% - 50vw);
	padding-inline: max(1.25rem, calc(50vw - 620px));
}

.cx-rail3d__track {
	display: flex;
	gap: var(--cx-gap);
	list-style: none;
	margin: 0;
	padding: 0 0 1.5rem;
	overflow-x: auto;
	overscroll-behavior-inline: contain;
	scroll-snap-type: x mandatory;
	scroll-padding-inline-start: max(1.25rem, calc(50vw - 620px));
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
	/* The 3D context. Depth is applied per card by JS writing --cx-d. */
	perspective: 1600px;
	perspective-origin: 50% 50%;
}

.cx-rail3d__track::-webkit-scrollbar { display: none; }

.cx-area {
	flex: 0 0 auto;
	width: clamp(228px, 22vw, 300px);
	scroll-snap-align: start;
	/* --cx-d is the card's signed distance from the centre of the viewport,
	   roughly -1 … 1, written by the scroll handler. Everything below is
	   derived from it, so the whole effect is one custom property. */
	--cx-d: 0;
	transform: rotateY(calc(var(--cx-d) * -9deg)) scale(calc(1 - (abs(var(--cx-d)) * 0.05)));
	transform-style: preserve-3d;
	transition: transform 0.45s var(--cx-ease);
	will-change: transform;
}

/* `abs()` is recent. Without it the cards simply sit flat — the rail still
   scrolls, snaps and reads correctly, which is the point of keeping the
   effect in one property. */
@supports not (width: abs(1px)) {
	.cx-area {
		transform: rotateY(calc(var(--cx-d) * -9deg));
	}
}

.cx-area__link {
	position: relative;
	display: block;
	border-radius: var(--cx-radius-lg);
	overflow: hidden;
	background: var(--cx-night);
	text-decoration: none;
	box-shadow: var(--cx-shadow);
	transition: box-shadow 0.3s var(--cx-ease);
}

.cx-area__link:hover {
	box-shadow: var(--cx-shadow-lift);
}

.cx-area__media {
	display: block;
	aspect-ratio: 4 / 5;
	background: var(--cx-night-2);
}

.cx-area__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--cx-ease), opacity 0.3s var(--cx-ease);
	opacity: 0.82;
}

.cx-area__link:hover .cx-area__media img {
	transform: scale(1.05);
	opacity: 1;
}

.cx-area__placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	color: rgba(255, 255, 255, 0.25);
}

.cx-area__placeholder .cx-i {
	width: 48px;
	height: 48px;
}

.cx-area__body {
	position: absolute;
	inset-inline: 0;
	inset-block-end: 0;
	padding: 1.25rem;
	background: linear-gradient(to top, rgba(10, 16, 19, 0.92) 20%, rgba(10, 16, 19, 0) 100%);
	color: #fff;
}

.cx-area__index {
	display: block;
	font-size: var(--cx-t-micro);
	font-weight: 700;
	letter-spacing: 0.14em;
	color: var(--cx-green-lift);
	margin-bottom: 0.35rem;
	font-variant-numeric: tabular-nums;
}

.cx-area__name {
	display: block;
	font-family: var(--cx-display);
	font-size: 1.1875rem;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.015em;
}

.cx-area__count {
	display: block;
	font-size: var(--cx-t-meta);
	color: rgba(255, 255, 255, 0.66);
	margin-top: 0.25rem;
}

.cx-area__go {
	position: absolute;
	inset-block-start: 1rem;
	inset-inline-end: 1rem;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.14);
	backdrop-filter: blur(6px);
	-webkit-backdrop-filter: blur(6px);
	color: #fff;
	opacity: 0;
	transform: translateY(-6px);
	transition: opacity 0.28s var(--cx-ease), transform 0.28s var(--cx-ease), background-color 0.28s var(--cx-ease);
}

/* The arrow mirrors with the document — it points to where "next" is. */
[dir="rtl"] .cx-area__go .cx-i {
	transform: scaleX(-1);
}

.cx-area__link:hover .cx-area__go,
.cx-area__link:focus-visible .cx-area__go {
	opacity: 1;
	transform: translateY(0);
	background: var(--cx-green);
}

/* Rail controls --------------------------------------------------------- */

.cx-railnav {
	display: flex;
	gap: 0.5rem;
	flex: none;
}

.cx-railnav__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 46px;
	border-radius: 50%;
	border: 1px solid var(--cx-line-2);
	background: var(--cx-paper);
	color: var(--cx-ink);
	cursor: pointer;
	transition: background-color 0.2s var(--cx-ease), border-color 0.2s var(--cx-ease), opacity 0.2s var(--cx-ease);
}

.cx-railnav__btn:hover:not(:disabled) {
	background: var(--cx-ink);
	border-color: var(--cx-ink);
	color: #fff;
}

.cx-railnav__btn:disabled {
	opacity: 0.32;
	cursor: default;
}

.cx-railnav__btn svg {
	width: 20px;
	height: 20px;
}

/* Arrow glyphs are directional, so they mirror with the document. */
[dir="rtl"] .cx-railnav__btn svg {
	transform: scaleX(-1);
}

.cx-rail3d__progress {
	height: 3px;
	border-radius: 999px;
	background: var(--cx-line);
	margin-block-start: 0.5rem;
	overflow: hidden;
}

.cx-rail3d__bar {
	display: block;
	height: 100%;
	width: 20%;
	border-radius: 999px;
	background: var(--cx-green);
	transform-origin: inline-start;
	transition: width 0.15s linear, margin 0.15s linear;
}

/* =========================================================================
   8. LISTING GRIDS
   ====================================================================== */

.cx-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
	gap: var(--cx-gap);
	list-style: none;
	margin: 0;
	padding: 0;
}

.cx-tile {
	display: flex;
}

.cx-tile__inner {
	display: flex;
	flex-direction: column;
	width: 100%;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-radius-lg);
	overflow: hidden;
	transition: transform 0.28s var(--cx-ease), box-shadow 0.28s var(--cx-ease), border-color 0.28s var(--cx-ease);
}

.cx-tile:hover .cx-tile__inner {
	transform: translateY(-4px);
	border-color: transparent;
	box-shadow: var(--cx-shadow-lift);
}

.cx-tile--night .cx-tile__inner {
	background: var(--cx-night-2);
	border-color: var(--cx-line-night);
}

.cx-tile__media {
	position: relative;
	display: block;
	aspect-ratio: 4 / 3;
	background: var(--cx-mist);
	overflow: hidden;
}

.cx-tile--night .cx-tile__media {
	background: #0d1519;
}

.cx-tile__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--cx-ease);
}

.cx-tile:hover .cx-tile__media img {
	transform: scale(1.045);
}

.cx-tile__placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	color: var(--cx-line-2);
}

.cx-tile__placeholder .cx-i {
	width: 40px;
	height: 40px;
}

.cx-tag {
	position: absolute;
	inset-block-start: 0.875rem;
	inset-inline-start: 0.875rem;
	display: inline-flex;
	align-items: center;
	height: 28px;
	padding-inline: 0.75rem;
	border-radius: 999px;
	font-family: var(--cx-display);
	font-size: var(--cx-t-micro);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
}

.cx-tag--status {
	background: rgba(255, 255, 255, 0.92);
	color: var(--cx-ink);
	box-shadow: 0 2px 8px rgba(13, 20, 24, 0.14);
}

.cx-tag--offplan {
	background: var(--cx-green);
	color: #fff;
}

.cx-tile__body {
	display: flex;
	flex-direction: column;
	flex: 1;
	padding: 1.25rem 1.375rem 1.375rem;
}

.cx-tile__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
	font-size: var(--cx-t-micro);
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--cx-faint);
	margin: 0 0 0.5rem;
}

.cx-tile--night .cx-tile__meta {
	color: rgba(255, 255, 255, 0.5);
}

.cx-tile__area {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
}

.cx-tile__area .cx-i {
	width: 14px;
	height: 14px;
}

.cx-tile__title {
	font-size: 1.125rem;
	font-weight: 700;
	line-height: 1.35;
	letter-spacing: -0.015em;
	/* Two lines at this size, always — so the price and the spec row sit on
	   the same baseline across every card in a row. */
	min-height: calc(2 * 1.35em);
	margin: 0 0 0.75rem;
	/* Two lines, then ellipsis — a long listing title must not make one card
	   in a row taller than the rest. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.cx-tile__title a {
	color: inherit;
	text-decoration: none;
}

.cx-tile--night .cx-tile__title a { color: #fff; }

.cx-tile__title a:hover { color: var(--cx-green-deep); }
.cx-tile--night .cx-tile__title a:hover { color: var(--cx-green-lift); }

/*
 * PRICE.
 *
 * Three parts on one baseline: an optional "From", the currency mark, and the
 * figure. They were previously one glued string from the theme helper, which
 * printed "19.4MAED" — unreadable at any size. Splitting them is the only way
 * to give the numeral the weight it deserves and the currency the weight it
 * does not.
 */
.cx-tile__price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 0.4em;
	margin: 0 0 1rem;
	min-height: 1.9rem;
}

.cx-tile__fig {
	font-family: var(--cx-display);
	font-size: 1.5rem;
	font-weight: 800;
	line-height: 1;
	letter-spacing: -0.03em;
	color: var(--cx-ink);
	font-variant-numeric: tabular-nums;
}

.cx-tile--night .cx-tile__fig { color: #fff; }

.cx-tile__cur {
	font-family: var(--cx-display);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--cx-green-deep);
	align-self: center;
}

.cx-tile--night .cx-tile__cur { color: var(--cx-green-lift); }

.cx-tile__from {
	font-size: var(--cx-t-micro);
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--cx-faint);
	align-self: center;
}

.cx-tile--night .cx-tile__from { color: rgba(255, 255, 255, 0.5); }

.cx-tile__request {
	font-family: var(--cx-display);
	font-size: 1rem;
	font-weight: 700;
	color: var(--cx-faint);
}

.cx-tile--night .cx-tile__request { color: rgba(255, 255, 255, 0.62); }

/* Off-plan cards close with an explicit affordance — the whole tile is
   clickable, but a project is a bigger commitment than a listing and the card
   should say where it goes. */
.cx-tile__go {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	margin-top: 1rem;
	font-family: var(--cx-display);
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.02em;
	color: var(--cx-green-lift);
	transition: gap 0.24s var(--cx-ease);
}

.cx-tile__go .cx-i {
	width: 16px;
	height: 16px;
}

[dir="rtl"] .cx-tile__go .cx-i { transform: scaleX(-1); }

.cx-tile:hover .cx-tile__go { gap: 0.8rem; }

.cx-specs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.375rem 1.25rem;
	list-style: none;
	margin: auto 0 0;
	padding: 1rem 0 0;
	border-block-start: 1px solid var(--cx-line);
}

.cx-tile--night .cx-specs {
	border-block-start-color: var(--cx-line-night);
}

.cx-specs__item {
	display: inline-flex;
	align-items: center;
	gap: 0.375rem;
	font-size: var(--cx-t-meta);
	color: var(--cx-faint);
}

.cx-tile--night .cx-specs__item { color: rgba(255, 255, 255, 0.6); }

.cx-specs__item .cx-i {
	width: 16px;
	height: 16px;
	color: var(--cx-green-deep);
}

.cx-tile--night .cx-specs__item .cx-i { color: var(--cx-green-lift); }

.cx-specs__value {
	font-weight: 700;
	color: var(--cx-ink);
	font-variant-numeric: tabular-nums;
}

.cx-tile--night .cx-specs__value { color: #fff; }

/* Sort, pagination, empty ------------------------------------------------ */

/* Sort control ----------------------------------------------------------
   Our own, because the theme's depends on a script WP Rocket delays. */

.cx-sort {
	flex: none;
	display: flex;
	align-items: center;
	gap: 0.625rem;
}

.cx-sort__label {
	font-size: var(--cx-t-micro);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--cx-faint);
	white-space: nowrap;
}

.cx-sort__field {
	position: relative;
	display: flex;
	align-items: center;
}

.cx-sort__select {
	appearance: none;
	-webkit-appearance: none;
	min-height: 46px;
	padding-inline: 1rem 2.5rem;
	border: 1px solid var(--cx-line-2);
	border-radius: 999px;
	background: var(--cx-paper);
	font-family: var(--cx-display);
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--cx-ink);
	cursor: pointer;
	transition: border-color 0.2s var(--cx-ease);
}

.cx-sort__select:hover { border-color: var(--cx-ink); }

/* The chevron sits over the select, so it must not swallow the click that
   opens it. */
.cx-sort__field .cx-i {
	position: absolute;
	inset-inline-end: 0.9rem;
	pointer-events: none;
	width: 16px;
	height: 16px;
	color: var(--cx-faint);
}

.cx-sort__go {
	min-height: 46px;
	padding-inline: 1rem;
	border: 1px solid var(--cx-line-2);
	border-radius: 999px;
	background: var(--cx-paper);
	font-weight: 700;
	cursor: pointer;
}

.cx-pagination {
	margin-top: clamp(2rem, 1.4rem + 1.6vw, 3rem);
	display: flex;
	justify-content: center;
}

.cx-empty {
	padding: clamp(2.5rem, 2rem + 2vw, 4rem);
	text-align: center;
	background: var(--cx-mist);
	border: 1px dashed var(--cx-line-2);
	border-radius: var(--cx-radius);
}

.cx-empty p {
	margin: 0 0 1.25rem;
	color: var(--cx-faint);
}

/* Off-plan band ---------------------------------------------------------
   The dark cards were the same component on a darker background, which read
   as an unstyled block rather than a deliberate change of product. These give
   the band its own material. */

.cx-band--night .cx-head {
	align-items: flex-start;
	padding-block-end: clamp(1.25rem, 0.8rem + 1.4vw, 2rem);
	border-block-end: 1px solid var(--cx-line-night);
}

.cx-grid--projects {
	margin-top: clamp(1.75rem, 1.2rem + 1.8vw, 2.75rem);
}

.cx-tile--night .cx-tile__inner {
	background: linear-gradient(180deg, var(--cx-night-2) 0%, #0c1418 100%);
	border-color: var(--cx-line-night);
}

.cx-tile--night:hover .cx-tile__inner {
	border-color: rgba(0, 166, 81, 0.45);
	box-shadow:
		0 2px 6px rgba(0, 0, 0, 0.4),
		0 24px 56px rgba(0, 0, 0, 0.55),
		0 0 0 1px rgba(0, 166, 81, 0.18);
}

/* The image is the only bright thing in the band, so it is held back until
   the card is hovered rather than competing with the type at full strength. */
.cx-tile--night .cx-tile__media img {
	opacity: 0.9;
	transition: transform 0.6s var(--cx-ease), opacity 0.35s var(--cx-ease);
}

.cx-tile--night:hover .cx-tile__media img {
	opacity: 1;
}

.cx-tile--night .cx-tile__meta {
	color: var(--cx-green-lift);
	letter-spacing: 0.12em;
}

/* =========================================================================
   9. BUYER GUIDE
   ====================================================================== */

.cx-split {
	display: grid;
	grid-template-columns: 1fr;
	gap: clamp(1.5rem, 1rem + 2vw, 3rem);
}

@media (min-width: 900px) {
	.cx-split {
		grid-template-columns: 1fr 1fr;
		align-items: start;
	}
}

.cx-facts {
	margin: 0;
	padding: 0;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-radius);
	overflow: hidden;
}

.cx-facts__row {
	display: flex;
	align-items: flex-start;
	gap: 1rem;
	padding: 1.25rem 1.375rem;
}

.cx-facts__row + .cx-facts__row {
	border-block-start: 1px solid var(--cx-line);
}

.cx-facts__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	flex: none;
	border-radius: 10px;
	background: var(--cx-tint);
	color: var(--cx-green-deep);
}

.cx-facts__label {
	font-size: var(--cx-t-micro);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--cx-faint);
	margin: 0 0 0.25rem;
}

.cx-facts__value {
	margin: 0;
	font-family: var(--cx-display);
	font-size: 1.0625rem;
	font-weight: 700;
	color: var(--cx-ink);
	line-height: 1.4;
}

/* Map facade ------------------------------------------------------------ */

.cx-map {
	position: relative;
	aspect-ratio: 4 / 3;
	border-radius: var(--cx-radius);
	overflow: hidden;
	border: 1px solid var(--cx-line);
	background:
		radial-gradient(circle at 30% 30%, rgba(0, 166, 81, 0.1), transparent 60%),
		linear-gradient(140deg, #dfe8e3 0%, #eef3f0 100%);
}

.cx-map iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

.cx-map__load {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.375rem;
	width: 100%;
	border: 0;
	background: transparent;
	cursor: pointer;
	color: var(--cx-ink);
	font-family: var(--cx-display);
}

.cx-map__pin {
	color: var(--cx-green-deep);
}

.cx-map__pin .cx-i {
	width: 36px;
	height: 36px;
}

.cx-map__name {
	font-size: 1.25rem;
	font-weight: 800;
	letter-spacing: -0.02em;
}

.cx-map__hint {
	font-family: var(--cx-text);
	font-size: var(--cx-t-meta);
	color: var(--cx-faint);
}

/* =========================================================================
   10. FAQ

   Native <details>. Accessible, keyboard-operable, and findable by in-page
   search with no script at all.
   ====================================================================== */

.cx-faq {
	border-block-start: 1px solid var(--cx-line);
}

.cx-faq__item {
	border-block-end: 1px solid var(--cx-line);
}

.cx-faq__q {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1.5rem;
	padding-block: 1.375rem;
	font-family: var(--cx-display);
	font-size: var(--cx-t-h3);
	font-weight: 700;
	line-height: 1.4;
	letter-spacing: -0.01em;
	color: var(--cx-ink);
	cursor: pointer;
	list-style: none;
}

.cx-faq__q::-webkit-details-marker { display: none; }

.cx-faq__q:hover { color: var(--cx-green-deep); }

/* The marker is drawn from two pseudo-elements rather than a glyph, so it
   rotates cleanly and needs no icon font. */
.cx-faq__mark {
	position: relative;
	flex: none;
	width: 20px;
	height: 20px;
	margin-block-start: 0.35rem;
}

.cx-faq__mark::before,
.cx-faq__mark::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 0;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: var(--cx-green);
	transition: transform 0.28s var(--cx-ease), opacity 0.28s var(--cx-ease);
}

.cx-faq__mark::after {
	transform: rotate(90deg);
}

.cx-faq__item[open] .cx-faq__mark::after {
	transform: rotate(0deg);
	opacity: 0;
}

.cx-faq__a {
	padding-block-end: 1.5rem;
	max-width: 74ch;
}

.cx-faq__a p {
	margin: 0;
	color: var(--cx-body);
	line-height: 1.75;
}

/* =========================================================================
   11. CLOSING
   ====================================================================== */

.cx-cta {
	background:
		radial-gradient(ellipse at 50% 0%, rgba(0, 166, 81, 0.16), transparent 62%),
		var(--cx-night);
	text-align: center;
}

.cx-cta__inner {
	max-width: 58ch;
	margin-inline: auto;
}

.cx-cta .cx-eyebrow {
	margin-inline: auto;
}

.cx-cta__text {
	font-size: var(--cx-t-lede);
	color: rgba(255, 255, 255, 0.72);
	margin: 1.25rem 0 0;
}

.cx-cta__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 0.75rem;
	margin-top: 2rem;
}

.cx-cta__note {
	font-size: var(--cx-t-meta);
	color: rgba(255, 255, 255, 0.45);
	margin: 1.75rem 0 0;
}

/* =========================================================================
   12. MOTION

   Reveal styles are gated behind `.cx-io`, which the script adds only after it
   has an IntersectionObserver to un-hide them with. Without JS, nothing is
   ever hidden — the class is never added and every element renders at its end
   state. This is why the gate exists rather than hiding by default.
   ====================================================================== */

.cx-io .cx-reveal {
	opacity: 0;
	transform: translateY(18px);
	transition:
		opacity 0.6s var(--cx-ease) var(--cx-delay, 0ms),
		transform 0.6s var(--cx-ease) var(--cx-delay, 0ms);
}

.cx-io .cx-reveal.is-in {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	/*
	 * Hold every end state and remove every transform. The rail keeps
	 * scrolling and snapping — that is navigation, not decoration — but its
	 * depth, the hover lifts and the reveals all stop.
	 */
	.cx *,
	.cx *::before,
	.cx *::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}

	.cx-io .cx-reveal {
		opacity: 1;
		transform: none;
	}

	.cx-area {
		transform: none !important;
	}

	.cx-tile:hover .cx-tile__inner,
	.cx-card:hover,
	.cx-btn:hover {
		transform: none;
	}

	.cx-tile:hover .cx-tile__media img,
	.cx-area__link:hover .cx-area__media img {
		transform: none;
	}
}

/* =========================================================================
   13. THEME CHROME

   The city archive keeps the site header and footer, but the theme prints a
   page title block and a sidebar wrapper on taxonomy templates that this page
   supplies itself.
   ====================================================================== */

.oplus-city-page .page-title-wrap,
.oplus-city-page .listing-tools-wrap,
.oplus-city-page .bt-sidebar-wrap {
	display: none;
}

.oplus-city-page .main-wrap,
.oplus-city-page .content-wrap {
	padding-block: 0;
}

/* =========================================================================
   14. NARROW VIEWPORTS
   ====================================================================== */

@media (max-width: 640px) {

	.cx-wrap,
	.cx-wrap--narrow,
	.cx-hero__inner {
		width: min(100% - 2rem, 100%);
	}

	.cx-hero {
		min-height: 32rem;
		align-items: flex-end;
	}

	.cx-hero__title {
		max-width: none;
	}

	.cx-hero__actions .cx-btn {
		flex: 1 1 100%;
	}

	.cx-rail {
		grid-template-columns: repeat(2, 1fr);
	}

	.cx-head {
		flex-direction: column;
		align-items: stretch;
	}

	.cx-grid {
		grid-template-columns: 1fr;
	}

	/* The label sits above the control on a phone, and the control takes the
	   full width — a 46px pill floating beside a label wastes the row. */
	.cx-sort {
		flex-direction: column;
		align-items: stretch;
		gap: 0.4rem;
	}

	.cx-sort__field,
	.cx-sort__select {
		width: 100%;
	}

	.cx-area {
		width: min(72vw, 280px);
	}

	.cx-faq__q {
		font-size: 1.0625rem;
	}
}

@media (min-width: 641px) and (max-width: 1024px) {
	.cx-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}
