/**
 * CoilX projects showcase.
 *
 * Design direction: the subject is Egyptian gated-compound HVAC, and the
 * native visual language of that world is the developer's parcel plan — the
 * drawing handed to a buyer, with plots, parcel numbers and hairline grids.
 * CoilX's own address text already speaks it ("Parcel 18", "Gr. C4",
 * "كلاستر 17"). So the page is built as a drafting table, not a card grid.
 *
 * The page is deliberately quiet — generous white, restrained type — and
 * spends all of its boldness in one place: the navy drawing stage that holds
 * the site plan. Everything around that stays out of its way.
 *
 * Colour comes from the CoilX brand only. The three series hues are steps of
 * the brand families, chosen with the palette validator rather than by eye:
 * every one clears the lightness band, chroma floor, CVD separation and
 * normal-vision floor on both the navy stage and white cards.
 *
 * RTL is the default (the site's default language is Arabic), so every
 * directional property here is logical, not physical.
 */

/* ── tokens ─────────────────────────────────────────────────────────────── */

:root {
	/* Brand, taken from the CoilX theme options and the logo itself. */
	--cx-navy: #002c50;
	--cx-orange: #f37535;
	--cx-blue: #3973b9;

	/* Neutrals, biased toward the navy rather than pure grey — a flat grey
	   next to this navy reads as unconsidered. */
	--cx-paper: #ffffff;
	--cx-mist: #f4f6f9;
	--cx-line: #dde4ec;
	--cx-ink: #002c50;
	--cx-ink-2: #4a5f74;
	/* 4.77:1 on white. The lighter grey this replaced looked right but failed
	   WCAG AA at the 13px it is actually used at. */
	--cx-ink-3: #64748a;

	/* The brand orange is a graphic accent, not a text colour: at 12px on white
	   it measures 2.84:1. This is the same hue stepped down to 4.77:1, used
	   only where the orange has to carry small type. Full-strength #F37535
	   stays in use for rules, dots and swatches, where contrast rules do not
	   apply. */
	--cx-orange-text: #be5210;

	/* On the navy stage. */
	--cx-stage: #002c50;
	--cx-stage-line: rgba(255, 255, 255, 0.14);
	--cx-stage-grid: rgba(255, 255, 255, 0.075);
	--cx-stage-ink: #eaf1f8;
	--cx-stage-ink-2: #9fb6cb;

	/* Series hues. Validated — do not substitute by eye. */
	--cx-heating: #ea6300;
	--cx-ac: #2f6dd3;
	--cx-dhw: #00a7a8;
	--cx-plot-idle: rgba(255, 255, 255, 0.09);
	--cx-plot-idle-line: rgba(255, 255, 255, 0.16);

	/* The house radius, straight from the parent theme (213 uses of 5px). */
	--cx-r: 5px;
	--cx-r-lg: 10px;

	/* Shadow language: soft, wide, very low opacity, navy-tinted. */
	--cx-shadow: 0 20px 50px rgba(0, 10, 80, 0.05);
	--cx-shadow-2: 0 6px 30px rgba(0, 0, 0, 0.08);
	--cx-shadow-3: 0 22px 27px rgba(0, 5, 36, 0.1);

	--cx-display: "Saira", system-ui, sans-serif;
	--cx-body: "Cairo", system-ui, sans-serif;
	--cx-num: "Saira", system-ui, sans-serif;

	--cx-ease: cubic-bezier(0.24, 0.74, 0.58, 1);

	--cx-gutter: clamp(1.25rem, 5vw, 5rem);
	--cx-max: 1240px;
}

/* Arabic has no Saira, so the display face becomes Cairo — the pairing stays
   within the two faces the site already loads. */
html[lang="ar"] {
	--cx-display: "Cairo", system-ui, sans-serif;
}

/* ── reset ──────────────────────────────────────────────────────────────── */

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
}

body.cx {
	margin: 0;
	background: var(--cx-paper);
	color: var(--cx-ink);
	font-family: var(--cx-body);
	font-size: 16px;
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
	overflow-x: hidden;
}

/* Author `display` always beats the UA sheet's [hidden] rule, regardless of
   specificity. Without this, any hidden element that also has a display value
   stays laid out — and a full-viewport overlay like .cx-panel would keep
   swallowing every click on the page while being invisible. */
.cx [hidden] {
	display: none !important;
}

.cx img {
	max-width: 100%;
	height: auto;
}

.cx h1,
.cx h2,
.cx h3 {
	margin: 0;
	font-family: var(--cx-display);
	font-weight: 700;
	line-height: 1.12;
	text-wrap: balance;
}

.cx p,
.cx dl,
.cx dd,
.cx dt {
	margin: 0;
}

.cx ul,
.cx ol {
	margin: 0;
	padding: 0;
	list-style: none;
}

.cx a {
	color: inherit;
	text-decoration: none;
}

.cx button {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	cursor: pointer;
}

/* No border-radius here.
 *
 * Setting it inside a :focus-visible rule changes the ELEMENT's own radius,
 * not the outline's — so the round close button squared off the moment it was
 * focused. Modern browsers already draw the outline following whatever radius
 * the element has, so the correct fix is to say nothing about radius at all.
 * The ring is also softer than the full-strength brand orange, which read as
 * an alert rather than a focus cue. */
.cx :focus-visible {
	outline: 2px solid color-mix(in srgb, var(--cx-orange) 78%, transparent);
	outline-offset: 3px;
}

/* On the navy stage the same ring needs to be lighter to stay visible. */
.cx-stage :focus-visible {
	outline-color: color-mix(in srgb, #fff 72%, transparent);
}

.cx-num {
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
}

.cx-skip {
	position: absolute;
	inset-block-start: -100%;
	inset-inline-start: 1rem;
	z-index: 60;
	padding: 0.6rem 1rem;
	background: var(--cx-navy);
	color: #fff;
	border-radius: var(--cx-r);
}

.cx-skip:focus {
	inset-block-start: 1rem;
}

/* ── inside a theme page ────────────────────────────────────────────────── */

/* The showcase now renders inside a normal WordPress page, under the theme's
   own title banner. That banner already announces the page, so the hero starts
   closer to it instead of opening the huge standalone gap it used to need. */
.cx-showcase .cx-hero {
	padding-block-start: 0;
}

/* The theme's page title is the document's h1; this is the thesis under it, so
   it is a paragraph carrying heading styling rather than a second h1. */
.cx-showcase .cx-hero__headline {
	margin: 0;
	font-family: var(--cx-display);
	font-weight: 700;
	line-height: 1.12;
	text-wrap: balance;
}

/* The stage stays inside the theme's content container.
 *
 * It was briefly broken out to full width with `100vw` and negative inline
 * margins — the technique the child theme uses on the home page hero. Inside
 * this template it clipped: the containing block is narrower than the
 * viewport, so the stage's overflow was cut and the plan's own heading and
 * left-hand plots disappeared off the edge, in both writing directions. A
 * contained stage that shows all of its content beats an edge-to-edge one
 * that hides some. */

/* ── topbar ─────────────────────────────────────────────────────────────── */

.cx-topbar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.1rem var(--cx-gutter);
	border-block-end: 1px solid var(--cx-line);
}

.cx-topbar__brand img {
	display: block;
	width: 132px;
	height: auto;
}

.cx-topbar__lang {
	font-family: var(--cx-display);
	font-size: 0.8rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	padding: 0.45rem 0.9rem;
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	transition: border-color 0.25s var(--cx-ease), color 0.25s var(--cx-ease);
}

.cx-topbar__lang:hover {
	border-color: var(--cx-orange);
	color: var(--cx-orange-text);
}

/* ── hero ───────────────────────────────────────────────────────────────── */

.cx-hero {
	padding: clamp(3rem, 9vw, 7rem) var(--cx-gutter) 0;
}

/* The hero is centred as a block: the thesis line is the page's one big
   statement, so it sits in the middle of the measure rather than hugging the
   reading edge. */
/* `justify-items: center` was the wrong tool and it silently broke the phone.
   It stops grid children stretching and sizes them to MAX-content instead, so
   the stats row — auto-fit, minmax(165px, 1fr) — laid out all four columns at
   703px inside a 320px hero and the page simply clipped it: two of the four
   figures, and both edges of the headline, were off screen on a phone.

   Children stretch to the container again; the centring is done with
   text-align, which centres the words without lying to the layout about how
   much room there is. */
.cx-hero__inner {
	max-width: var(--cx-max);
	margin-inline: auto;
	display: grid;
	/* minmax(0, …) not 1fr: an implicit `auto` track refuses to shrink below
	   its content's min-content width, which is how the hero stayed wider than
	   the phone even after the children were told to stretch. The 0 minimum is
	   what actually lets the column fit the screen. */
	grid-template-columns: minmax(0, 1fr);
	justify-items: stretch;
	text-align: center;
	gap: 1.1rem;
}

.cx-eyebrow {
	font-family: var(--cx-display);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--cx-orange-text);
}

.cx-hero__headline {
	font-size: clamp(2.1rem, 5.6vw, 4.1rem);
	letter-spacing: -0.02em;
	max-width: 18ch;
}

html[lang="ar"] .cx-hero__headline {
	letter-spacing: 0;
	line-height: 1.3;
	max-width: 22ch;
}

.cx-hero__lede {
	max-width: 62ch;
	font-size: clamp(1rem, 1.5vw, 1.14rem);
	color: var(--cx-ink-2);
}

/* Each figure gets its own card so the four read as a set of facts rather than
   four numbers floating in space. */
.cx-stats {
	display: grid;
	/* min() so the track can never demand more than the container has: on a
	   360px phone this gives two columns, not four that overflow. */
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 150px), 1fr));
	gap: 0.9rem;
	inline-size: 100%;
	max-width: 900px;
	margin-inline: auto;
	margin-block-start: clamp(1.5rem, 3vw, 2.5rem);
}

.cx-stat {
	position: relative;
	overflow: hidden;
	display: grid;
	gap: 0.35rem;
	padding: 1.6rem 1rem 1.4rem;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: 14px;
	box-shadow: var(--cx-shadow);
	transition: transform 0.3s var(--cx-ease), box-shadow 0.3s var(--cx-ease),
		border-color 0.3s var(--cx-ease);
}

/* A single sheen that crosses the card once, on the beat after it lands. */
.cx-stat::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-start: -60%;
	inline-size: 50%;
	background: linear-gradient(
		100deg,
		transparent,
		color-mix(in srgb, var(--cx-orange) 10%, transparent),
		transparent
	);
	transform: skewX(-18deg);
	animation: cx-sheen 1.4s ease-out backwards;
	animation-delay: calc(var(--cx-i, 0) * 150ms + 900ms);
	pointer-events: none;
}

@keyframes cx-sheen {
	from {
		inset-inline-start: -60%;
		opacity: 0;
	}

	20% {
		opacity: 1;
	}

	to {
		inset-inline-start: 130%;
		opacity: 0;
	}
}

/* A hairline of brand colour along the top edge, drawn once the card lands. */
.cx-stat::before {
	content: "";
	position: absolute;
	inset-block-start: 0;
	inset-inline: 0;
	block-size: 3px;
	background: linear-gradient(
		90deg,
		var(--cx-orange),
		color-mix(in srgb, var(--cx-orange) 30%, var(--cx-blue))
	);
	transform: scaleX(0);
	transform-origin: inline-start;
	animation: cx-rule 0.6s var(--cx-ease) forwards;
	animation-delay: calc(var(--cx-i, 0) * 150ms + 700ms);
}

@keyframes cx-rule {
	to {
		transform: scaleX(1);
	}
}

@media (hover: hover) and (pointer: fine) {
	.cx-stat:hover {
		transform: translateY(-4px);
		box-shadow: var(--cx-shadow-3);
		border-color: color-mix(in srgb, var(--cx-orange) 40%, transparent);
	}
}

@media (prefers-reduced-motion: reduce) {
	.cx-stat::after {
		animation: none;
		opacity: 0;
	}

	.cx-stat::before {
		animation: none;
		transform: scaleX(1);
	}
}

.cx-stat__value {
	display: block;
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-size: clamp(2.4rem, 5vw, 3.6rem);
	font-weight: 700;
	line-height: 1;
	letter-spacing: -0.03em;
	color: var(--cx-navy);
}

.cx-stat__label {
	margin-block-start: 0.5rem;
	font-size: 0.83rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--cx-ink-3);
}

html[lang="ar"] .cx-stat__label {
	letter-spacing: 0;
	text-transform: none;
	font-size: 0.9rem;
}

/* Centred hero wants a centred rule. */
.cx-hero__rule {
	max-width: var(--cx-max);
	margin: clamp(2.5rem, 6vw, 4rem) auto clamp(1rem, 2vw, 1.5rem);
	height: 3px;
	background: linear-gradient(to right, var(--cx-line) 0 38%, var(--cx-orange) 38% 62%, var(--cx-line) 62% 100%);
}

/* ── step rail ──────────────────────────────────────────────────────────── */

/* Numbered because the drill-down genuinely is a sequence — city, then
   compound, then plan. The numbers carry information, they are not decoration. */
/* The bottom padding used to be 0, which put the step rail flat against
   whatever came next. On the plan step that next thing is the dark stage, so
   the numbers looked stuck to the edge of a navy box. */
.cx-rail {
	padding: clamp(2rem, 4vw, 3rem) var(--cx-gutter) clamp(1.5rem, 3vw, 2.25rem);
}

.cx-rail__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem 1.5rem;
	max-width: var(--cx-max);
	margin-inline: auto;
}

.cx-rail__step {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	font-size: 0.86rem;
	color: var(--cx-ink-3);
	transition: color 0.3s var(--cx-ease);
}

.cx-rail__num {
	display: grid;
	place-items: center;
	inline-size: 1.6rem;
	block-size: 1.6rem;
	border: 1px solid var(--cx-line);
	border-radius: 50%;
	font-family: var(--cx-num);
	font-size: 0.76rem;
	font-weight: 600;
	transition: border-color 0.3s var(--cx-ease), background-color 0.3s var(--cx-ease), color 0.3s var(--cx-ease);
}

.cx-rail__step.is-current {
	color: var(--cx-navy);
}

.cx-rail__step.is-current .cx-rail__num {
	background: var(--cx-navy);
	border-color: var(--cx-navy);
	color: #fff;
}

.cx-rail__step.is-done .cx-rail__num {
	border-color: var(--cx-orange);
	color: var(--cx-orange);
}

/* ── sections & cards ───────────────────────────────────────────────────── */

 /* Sections lay their children out with grid + gap rather than margins.
  *
  * The reset above (`.cx ul { margin: 0 }`) has higher specificity than any
  * single-class component rule, so a `margin-block-start` on `.cx-grid` was
  * silently zeroed — the section heading ended up flush against its cards.
  * Owning the spacing at the container removes the collision entirely instead
  * of escalating specificity to win it. */
.cx-section {
	display: grid;
	gap: clamp(1.5rem, 3vw, 2.25rem);
	align-content: start;
	padding: clamp(2.5rem, 5vw, 3.5rem) var(--cx-gutter) clamp(3rem, 7vw, 5rem);
	max-width: calc(var(--cx-max) + var(--cx-gutter) * 2);
	margin-inline: auto;
}

.cx-section__head {
	display: grid;
	justify-items: start;
	gap: 0.9rem;
}

.cx-section__title {
	font-size: clamp(1.4rem, 2.6vw, 1.9rem);
	letter-spacing: -0.015em;
}

.cx-section__scope {
	font-style: normal;
	color: var(--cx-orange-text);
}

.cx-grid {
	display: grid;
	gap: 1.1rem;
}

.cx-grid--city {
	grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

.cx-grid--compound {
	grid-template-columns: repeat(auto-fill, minmax(255px, 1fr));
}

.cx-card {
	display: flex;
	flex-direction: column;
	gap: 0.65rem;
	block-size: 100%;
	padding: 1.4rem 1.5rem 1.5rem;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	transition: transform 0.35s var(--cx-ease), box-shadow 0.35s var(--cx-ease), border-color 0.35s var(--cx-ease);
	will-change: auto;
}

.cx-card:hover,
.cx-card:focus-visible {
	transform: translateY(-3px);
	border-color: transparent;
	box-shadow: var(--cx-shadow-3);
}

.cx-card__title {
	font-family: var(--cx-display);
	font-size: 1.12rem;
	font-weight: 600;
	line-height: 1.25;
	letter-spacing: -0.01em;
}

.cx-card__meta {
	display: flex;
	align-items: baseline;
	gap: 0.4rem;
	font-size: 0.88rem;
	color: var(--cx-ink-2);
}

.cx-card__meta .cx-num {
	font-size: 1.5rem;
	color: var(--cx-navy);
	line-height: 1;
}

.cx-card__years {
	margin-inline-start: auto;
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-size: 0.78rem;
	color: var(--cx-ink-3);
}

.cx-card__sub,
.cx-card__note {
	font-size: 0.82rem;
	color: var(--cx-ink-3);
	margin-block-start: auto;
}

.cx-card--other {
	background: var(--cx-mist);
	border-style: dashed;
}

/* Service split bar on the city cards. A 2px surface gap keeps adjacent
   segments legible without a border. */
.cx-bar {
	display: flex;
	gap: 2px;
	block-size: 6px;
	border-radius: 3px;
	overflow: hidden;
}

.cx-bar__seg {
	inline-size: var(--seg);
	background: var(--cx-svc, var(--cx-ink-3));
	border-radius: 2px;
}

.cx-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.cx-chip {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-size: 0.75rem;
	font-weight: 600;
	color: var(--cx-ink-2);
	padding: 0.15rem 0.5rem 0.15rem 0.4rem;
	background: var(--cx-mist);
	border-radius: 3px;
}

.cx-chip--dot::before {
	content: "";
	inline-size: 7px;
	block-size: 7px;
	border-radius: 2px;
	background: var(--cx-svc, var(--cx-ink-3));
}

/* Service colour is bound to the service, never to its position in a list. */
[data-service="heating"] {
	--cx-svc: var(--cx-heating);
}

[data-service="ac"] {
	--cx-svc: var(--cx-ac);
}

[data-service="dhw"] {
	--cx-svc: var(--cx-dhw);
}

/* ── back button ────────────────────────────────────────────────────────── */

/* A real pill, not bare text. Tag-qualified because the theme paints every
   <button> with its own gradient and white label, which is why this used to
   render as flat unstyled text with no background at all. */
button.cx-back,
.cx-back {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	font-size: 0.84rem;
	font-weight: 600;
	color: var(--cx-ink-2);
	padding: 0.55rem 1.05rem;
	background-color: color-mix(in srgb, var(--cx-ink-2) 7%, transparent);
	background-image: none;
	border: 1px solid color-mix(in srgb, var(--cx-ink-2) 16%, transparent);
	border-radius: 999px;
	transition: color 0.25s var(--cx-ease), background-color 0.25s var(--cx-ease),
		border-color 0.25s var(--cx-ease);
}

button.cx-back:hover,
.cx-back:hover {
	color: var(--cx-orange-text);
	background-color: color-mix(in srgb, var(--cx-orange) 12%, transparent);
	border-color: color-mix(in srgb, var(--cx-orange) 45%, transparent);
}

/* On the dark stage the same pill needs the light treatment. */
button.cx-back--light,
.cx-back--light {
	color: #fff;
	background-color: rgba(255, 255, 255, 0.1);
	border-color: rgba(255, 255, 255, 0.24);
}

button.cx-back--light:hover,
.cx-back--light:hover {
	color: #fff;
	background-color: color-mix(in srgb, var(--cx-orange) 78%, transparent);
	border-color: transparent;
}

/* The arrow sits in its own disc so the control reads as a button at a glance. */
.cx-back__arrow {
	flex: none;
}

/* An inline SVG, mirrored whole in RTL.
 *
 * This replaces a CSS chevron built from `border-inline-start` (logical, flips
 * itself in RTL) rotated about `transform-origin: left top` (physical, does
 * not) — the two disagreed, so the arrow pointed wrongly in Arabic and sat at
 * the wrong angle in English. One shape flipped by one transform has no such
 * halves to fall out of step. */
.cx-back__arrow {
	flex: none;
	transition: transform 0.25s var(--cx-ease);
}

/* Scoped through .cx to outrank the theme, which resets transforms on inline
   SVG inside page content — the rule matched but lost the cascade, so the
   Arabic arrow silently stopped mirroring once the page moved inside the
   theme. */
html[dir="rtl"] .cx .cx-back__arrow {
	transform: scaleX(-1);
}

.cx .cx-back:hover .cx-back__arrow,
.cx .cx-back:focus-visible .cx-back__arrow {
	transform: translateX(-3px);
}

/* Same nudge, still "backwards": the mirror decides which way that is. */
html[dir="rtl"] .cx .cx-back:hover .cx-back__arrow,
html[dir="rtl"] .cx .cx-back:focus-visible .cx-back__arrow {
	transform: scaleX(-1) translateX(-3px);
}

.cx-back--light {
	color: var(--cx-stage-ink-2);
}

.cx-back--light:hover {
	color: #fff;
}

/* ── the stage: a navy drawing board ────────────────────────────────────── */

.cx-stage {
	background: var(--cx-stage);
	color: var(--cx-stage-ink);
	padding: clamp(2.25rem, 5vw, 4rem) var(--cx-gutter) clamp(3rem, 6vw, 4.5rem);
	/* A hairline drafting grid, drawn in CSS so it costs no requests. */
	/* No grid painted here. It is drawn inside the plan's own SVG instead, which
	   is the only way it can stay aligned with the plots at every width and
	   scroll position. */
}

.cx-stage__inner {
	max-width: var(--cx-max);
	margin-inline: auto;
	display: flex;
	flex-direction: column;
	gap: 1.75rem;
}

.cx-stage__head {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.5rem;
}

.cx-stage__title {
	font-size: clamp(1.7rem, 3.6vw, 2.6rem);
	letter-spacing: -0.02em;
	color: #fff;
}

.cx-stage__meta {
	font-size: 0.9rem;
	color: var(--cx-stage-ink-2);
}

/* Two labelled questions and a view switch on one line. `align-items: center`
   was wrong once the groups gained headings — it centred a two-line group
   against a one-line one, so the labels no longer lined up with each other.
   Top-aligned, with enough gap that the two questions read as two. */
.cx-controls {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem 2.25rem;
	align-items: flex-start;
}

/* The view switch is not a filter, so it sits apart from the two questions. */
.cx-controls .cx-viewtoggle {
	margin-inline-start: auto;
	align-self: center;
}

.cx-filters {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

/* The status filter is a separate group so the two axes never read as one
   long row of interchangeable chips. */
.cx-filters--status {
	position: relative;
	padding-inline-start: 0.85rem;
	margin-inline-start: 0.35rem;
}

.cx-filters--status::before {
	content: "";
	position: absolute;
	inset-block: 0.2rem;
	inset-inline-start: 0;
	inline-size: 1px;
	background: var(--cx-stage-line);
}

.cx-filter {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0.45rem 0.9rem;
	font-size: 0.82rem;
	font-weight: 600;
	color: var(--cx-stage-ink-2);
	border: 1px solid var(--cx-stage-line);
	border-radius: var(--cx-r);
	transition: color 0.25s var(--cx-ease), border-color 0.25s var(--cx-ease), background-color 0.25s var(--cx-ease);
}

.cx-filter:hover {
	color: #fff;
	border-color: rgba(255, 255, 255, 0.4);
}

.cx-filter.is-active {
	color: var(--cx-navy);
	background: #fff;
	border-color: #fff;
}

.cx-filter__dot {
	inline-size: 8px;
	block-size: 8px;
	border-radius: 2px;
	background: var(--cx-svc, currentColor);
}

/* ── the plan itself ────────────────────────────────────────────────────── */

.cx-plan {
	position: relative;
	min-block-size: 260px;
}

/* A wide plan scrolls, and nothing said so. The fade on the trailing edge is
   the only hint a touch user gets that there is more drawing to the side. */
.cx-plan {
	--cx-fade: color-mix(in srgb, var(--cx-stage) 92%, transparent);
}

.cx-plan__canvas::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-end: 0;
	inline-size: 48px;
	pointer-events: none;
	background: linear-gradient(to left, var(--cx-fade), transparent);
	opacity: 0;
	transition: opacity 0.25s var(--cx-ease);
}

html[dir="rtl"] .cx-plan__canvas::after {
	background: linear-gradient(to right, var(--cx-fade), transparent);
}

.cx-plan__canvas.is-scrollable::after {
	opacity: 1;
}

.cx-plan__canvas.is-scrolled-end::after {
	opacity: 0;
}

.cx-plan__canvas {
	position: relative;
	/* Wide plans scroll inside their own container — the page body never
	   scrolls sideways. */
	overflow-x: auto;
	overflow-y: hidden;
	-webkit-overflow-scrolling: touch;
	padding-block: 0.5rem;
}

/* Rendered at its natural size, never stretched to the container: a plot must
   be the same size in every compound, so a small compound cannot inflate its
   units into something that reads as more important. Wide plans overflow into
   the canvas's own horizontal scroll. */
.cx-plan__svg {
	display: block;
	inline-size: auto;
	max-inline-size: none;
	block-size: auto;
	touch-action: pan-x pan-y pinch-zoom;
}

/* ── list view ──────────────────────────────────────────────────────────── */

/* The plan's counterpart: every unit as rows. It is the mobile fallback for a
   plan too wide to take in at a glance, the keyboard- and screen-reader-
   friendly reading of the same data, and the non-colour route to the service
   of each unit. */
.cx-viewtoggle {
	display: inline-flex;
	gap: 2px;
	padding: 2px;
	border: 1px solid var(--cx-stage-line);
	border-radius: var(--cx-r);
	margin-inline-start: auto;
}

.cx-viewtoggle__btn {
	padding: 0.35rem 0.8rem;
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--cx-stage-ink-2);
	border-radius: 3px;
	transition: color 0.25s var(--cx-ease), background-color 0.25s var(--cx-ease);
}

.cx-viewtoggle__btn.is-active {
	color: var(--cx-navy);
	background: #fff;
}

.cx-list {
	inline-size: 100%;
	overflow-x: auto;
}

.cx-list__table {
	inline-size: 100%;
	min-inline-size: 460px;
	border-collapse: collapse;
	font-size: 0.88rem;
}

.cx-list__table th {
	text-align: start;
	font-family: var(--cx-display);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--cx-stage-ink-2);
	padding: 0 0.9rem 0.6rem;
	border-block-end: 1px solid var(--cx-stage-line);
}

html[lang="ar"] .cx-list__table th {
	letter-spacing: 0;
	text-transform: none;
	font-size: 0.82rem;
}

.cx-list__table td {
	padding: 0.65rem 0.9rem;
	border-block-end: 1px solid rgba(255, 255, 255, 0.07);
}

.cx-list__row {
	cursor: pointer;
	transition: background-color 0.2s var(--cx-ease);
}

.cx-list__row:hover,
.cx-list__row:focus-visible {
	background: rgba(255, 255, 255, 0.05);
}

.cx-list__unit {
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	color: #fff;
	direction: ltr;
	text-align: start;
}

.cx-list__year {
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	color: var(--cx-stage-ink-2);
}

.cx-list__svc {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.cx-list__tag {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-size: 0.78rem;
	white-space: nowrap;
}

.cx-list__dot {
	inline-size: 9px;
	block-size: 9px;
	border-radius: 2px;
	background: var(--cx-svc);
	flex: none;
}

/* Plots. Only transform and opacity are animated. */
.cx-plot {
	cursor: pointer;
}

.cx-plot__shape {
	fill: var(--cx-plot-idle);
	stroke: var(--cx-plot-idle-line);
	stroke-width: 1;
	transition: opacity 0.22s var(--cx-ease);
}

.cx-plot--coilx .cx-plot__shape {
	fill: var(--cx-svc);
	stroke: rgba(255, 255, 255, 0.55);
}

/* Work still under way: the same hue, drawn as an open dashed outline rather
   than a solid block. Finished work reads as filled-in; a job in progress
   reads as pencilled-in. No fourth colour is spent on it, so the legend still
   maps hue to service and nothing else. */
.cx-plot--wip .cx-plot__shape {
	fill: color-mix(in srgb, var(--cx-svc) 22%, transparent);
	stroke: var(--cx-svc);
	stroke-width: 1.6;
	stroke-dasharray: 3.5 2.5;
}

.cx-plot--wip .cx-plot__label {
	fill: rgba(255, 255, 255, 0.82);
}

.cx-plot--coilx {
	transform-box: fill-box;
	transform-origin: center;
	transition: transform 0.18s var(--cx-ease);
}

.cx-plot--coilx:hover,
.cx-plot--coilx:focus-visible {
	transform: scale(1.18);
}

/* A ring in the stage colour separates the lifted plot from its neighbours,
   which otherwise sit only 6px away. */
.cx-plot--coilx:hover .cx-plot__shape,
.cx-plot--coilx:focus-visible .cx-plot__shape {
	stroke: #fff;
	stroke-width: 1.6;
}

.cx-plot__label {
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-size: 8px;
	font-weight: 600;
	fill: rgba(255, 255, 255, 0.92);
	pointer-events: none;
	text-anchor: middle;
	dominant-baseline: middle;
	direction: ltr;
}

.cx-plot.is-dimmed .cx-plot__shape,
.cx-plot.is-dimmed .cx-plot__label {
	opacity: 0.16;
}

.cx-parcel__label {
	font-family: var(--cx-display);
	font-size: 10px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	fill: var(--cx-stage-ink-2);
	direction: ltr;
}

.cx-parcel__frame {
	fill: none;
	stroke: var(--cx-stage-line);
	stroke-width: 1;
}

/* Corner ticks — the drafting-table detail that makes a block read as a
   surveyed parcel rather than a rounded card. */
.cx-parcel__tick {
	stroke: rgba(255, 255, 255, 0.28);
	stroke-width: 1;
}

/* The entrance itself is driven by the Web Animations API in schematic.js, not
   by a class here. That is deliberate: a plot's resting state must be VISIBLE,
   so that if the animation never runs — reduced motion, a stalled frame loop,
   a browser that cancels it — the plan still shows every unit. An entrance
   built on `opacity: 0` plus `forwards` would hide the entire point of the
   page the moment anything went wrong with it. */

/* ── tooltip ────────────────────────────────────────────────────────────── */

.cx-tip {
	position: fixed;
	z-index: 40;
	pointer-events: none;
	padding: 0.5rem 0.7rem;
	background: #fff;
	color: var(--cx-navy);
	border-radius: var(--cx-r);
	box-shadow: var(--cx-shadow-2);
	font-size: 0.8rem;
	line-height: 1.45;
	white-space: nowrap;
	opacity: 0;
	transform: translateY(4px);
	transition: opacity 0.14s var(--cx-ease), transform 0.14s var(--cx-ease);
}

.cx-tip.is-visible {
	opacity: 1;
	transform: translateY(0);
}

.cx-tip__unit {
	font-family: var(--cx-num);
	font-weight: 700;
}

.cx-tip__svc {
	display: flex;
	gap: 0.35rem;
	margin-block-start: 0.25rem;
}

.cx-tip__wip {
	margin-block-start: 0.3rem;
	padding-block-start: 0.3rem;
	border-block-start: 1px solid var(--cx-line);
	font-size: 0.74rem;
	font-weight: 600;
	color: var(--cx-ink-2);
}

.cx-tip__dot {
	inline-size: 8px;
	block-size: 8px;
	border-radius: 2px;
	background: var(--cx-svc);
}

/* ── legend ─────────────────────────────────────────────────────────────── */

.cx-legend {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.6rem 1.4rem;
	padding-block-start: 0.5rem;
	border-block-start: 1px solid var(--cx-stage-line);
}

.cx-legend__title {
	font-family: var(--cx-display);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--cx-stage-ink-2);
	padding-block-start: 0.9rem;
}

html[lang="ar"] .cx-legend__title {
	letter-spacing: 0;
	text-transform: none;
	font-size: 0.82rem;
}

.cx-legend__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem 1.4rem;
	padding-block-start: 0.9rem;
}

.cx-legend__item {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-size: 0.84rem;
}

.cx-legend__item--muted {
	color: var(--cx-stage-ink-2);
	font-size: 0.79rem;
}

.cx-legend__swatch {
	inline-size: 12px;
	block-size: 12px;
	border-radius: 2px;
	background: var(--cx-svc, var(--cx-plot-idle));
}

.cx-legend__swatch--other {
	background: var(--cx-plot-idle);
	border: 1px solid var(--cx-plot-idle-line);
}

/* Legend keys for the two states, drawn the same way the plots are. */
.cx-legend__swatch--done {
	background: var(--cx-stage-ink-2);
}

.cx-legend__swatch--wip {
	background: color-mix(in srgb, var(--cx-stage-ink-2) 22%, transparent);
	border: 1.5px dashed var(--cx-stage-ink-2);
}

.cx-legend__group {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem 1.4rem;
	padding-block-start: 0.9rem;
}

/* ── unnumbered tray & other-locations list ─────────────────────────────── */

.cx-tray {
	padding-block-start: 0.5rem;
	border-block-start: 1px solid var(--cx-stage-line);
}

.cx-tray__title {
	font-size: 1rem;
	font-weight: 600;
	color: #fff;
	padding-block-start: 1.25rem;
}

.cx-tray__note {
	font-size: 0.82rem;
	color: var(--cx-stage-ink-2);
	max-width: 60ch;
	margin-block-start: 0.3rem;
}

.cx-tray__list {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-block-start: 1rem;
}

.cx-tray__item {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.45rem 0.8rem;
	border: 1px solid var(--cx-stage-line);
	border-radius: var(--cx-r);
	font-size: 0.82rem;
	cursor: pointer;
	transition: border-color 0.25s var(--cx-ease), background-color 0.25s var(--cx-ease);
}

.cx-tray__item:hover {
	border-color: rgba(255, 255, 255, 0.4);
	background: rgba(255, 255, 255, 0.05);
}

.cx-tray__dots {
	display: inline-flex;
	gap: 3px;
}

.cx-tray__dot {
	inline-size: 7px;
	block-size: 7px;
	border-radius: 2px;
	background: var(--cx-svc);
}

/* ── detail panel ───────────────────────────────────────────────────────── */

/* The panel is portalled to <body> by showcase.js — see portalPanel() — because
   the theme's transform on .site-content otherwise makes `fixed` measure
   against the page rather than the screen. */
.cx-panel {
	position: fixed;
	inset: 0;
	z-index: 50;
}

.cx-panel__scrim {
	position: absolute;
	inset: 0;
	background: rgba(0, 20, 40, 0.38);
	opacity: 0;
	transition: opacity 0.28s var(--cx-ease);
}

.cx-panel.is-open .cx-panel__scrim {
	opacity: 1;
}

/* A card beside the unit you tapped, not a drawer at the edge of the screen.
   Position comes from placeCard(); everything here is size and motion. */
.cx-panel__card {
	position: absolute;
	inline-size: min(360px, calc(100vw - 2rem));
	max-block-size: min(80vh, 620px);
	overflow-y: auto;
	padding: clamp(1.25rem, 3vw, 1.75rem);
	background: var(--cx-paper);
	color: var(--cx-ink);
	border-radius: 16px;
	box-shadow: var(--cx-shadow-3);
	opacity: 0;
	transform: scale(0.94);
	transform-origin: center;
	transition: opacity 0.22s var(--cx-ease), transform 0.22s var(--cx-ease);
}

.cx-panel.is-open .cx-panel__card {
	opacity: 1;
	transform: scale(1);
}

/* No room beside the unit (phones, mostly): a sheet at the bottom, still
   within reach of the thumb that tapped. */
.cx-panel__card.is-sheet {
	inset-block-end: 0;
	inset-inline: 0;
	inline-size: 100%;
	max-block-size: 78vh;
	border-radius: 18px 18px 0 0;
	transform: translateY(14px);
}

.cx-panel.is-open .cx-panel__card.is-sheet {
	transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
	.cx-panel__card,
	.cx-panel__card.is-sheet {
		transition: none;
		transform: none;
	}
}

.cx-panel__close {
	position: absolute;
	inset-block-start: 1rem;
	inset-inline-end: 1rem;
	inline-size: 2.25rem;
	block-size: 2.25rem;
	padding: 0;
	border-radius: 50%;
	/* No ring and no fill — just the mark. Both are stated explicitly because
	   the theme paints its own background and border on every <button>. */
	border: 0;
	background: transparent;
	color: var(--cx-ink-2);
	transition: color 0.2s var(--cx-ease), transform 0.2s var(--cx-ease);
}

.cx-panel__close::before,
.cx-panel__close::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	inline-size: 12px;
	block-size: 1.5px;
	background: var(--cx-ink-2);
}

.cx-panel__close::before {
	transform: translate(-50%, -50%) rotate(45deg);
}

.cx-panel__close::after {
	transform: translate(-50%, -50%) rotate(-45deg);
}

.cx-panel__close:hover {
	color: var(--cx-orange);
	transform: rotate(90deg);
}

/* Beat the theme's generic button painting without touching anything else.
 *
 * Two traps here, both learned the hard way:
 *  - `background-image` has to be named explicitly. The theme paints its
 *    buttons with a linear-gradient, not a colour, so clearing
 *    background-color alone left an orange disc behind the mark.
 *  - the selector must NOT depend on `.cx`. The panel is moved to <body> when
 *    it opens, so any `.cx …` rule silently stops matching it — which is
 *    exactly how the disc came back after the move.
 */
.cx-panel button.cx-panel__close,
.cx-panel button.cx-panel__close:hover,
.cx-panel button.cx-panel__close:focus {
	background-color: transparent;
	background-image: none;
	border: 0;
	box-shadow: none;
	color: var(--cx-ink-2);
}

.cx-panel button.cx-panel__close:hover {
	color: var(--cx-orange);
}

/* The focus ring lives on `.cx :focus-visible`, which the portalled panel is no
   longer inside. */
.cx-panel :focus-visible {
	outline: 2px solid color-mix(in srgb, var(--cx-orange) 78%, transparent);
	outline-offset: 3px;
}

.cx-panel[hidden] {
	display: none !important;
}

.cx-panel__eyebrow {
	font-family: var(--cx-display);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--cx-orange-text);
}

html[lang="ar"] .cx-panel__eyebrow {
	letter-spacing: 0;
	text-transform: none;
	font-size: 0.85rem;
}

.cx-panel__title {
	margin-block-start: 0.5rem;
	font-size: clamp(1.6rem, 4vw, 2.1rem);
	letter-spacing: -0.02em;
}

.cx-panel__facts {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 0.85rem 1.25rem;
	margin-block-start: 2rem;
	padding-block-start: 1.5rem;
	border-block-start: 1px solid var(--cx-line);
	font-size: 0.92rem;
}

.cx-panel__facts dt {
	font-size: 0.78rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--cx-ink-3);
	padding-block-start: 0.15rem;
}

html[lang="ar"] .cx-panel__facts dt {
	letter-spacing: 0;
	text-transform: none;
	font-size: 0.85rem;
}

.cx-panel__facts dd {
	font-weight: 600;
}

.cx-panel__svc {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}

.cx-panel__svcitem {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
}

.cx-panel__svcdot {
	inline-size: 10px;
	block-size: 10px;
	border-radius: 2px;
	background: var(--cx-svc);
}

.cx-panel__sub {
	display: block;
	font-weight: 400;
	font-size: 0.85rem;
	color: var(--cx-ink-3);
}

/* ── empty states ───────────────────────────────────────────────────────── */

.cx-empty {
	text-align: center;
	color: var(--cx-ink-2);
}

.cx-empty--page {
	padding: clamp(3rem, 10vw, 7rem) var(--cx-gutter);
	max-width: 46ch;
	margin-inline: auto;
}

.cx-empty--page h2 {
	font-size: 1.5rem;
	margin-block-end: 0.75rem;
}

.cx-empty--filter {
	padding: 3.5rem 1rem;
	color: var(--cx-stage-ink-2);
}

.cx-linkbtn {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
	margin-inline-start: 0.4rem;
}

/* ── footer ─────────────────────────────────────────────────────────────── */

.cx-footer {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.5rem 1.5rem;
	padding: 2.5rem var(--cx-gutter);
	border-block-start: 1px solid var(--cx-line);
	font-size: 0.8rem;
	color: var(--cx-ink-3);
}

.cx-footer__brand {
	font-family: var(--cx-display);
	font-weight: 700;
	letter-spacing: 0.18em;
	color: var(--cx-navy);
}

/* ── scroll reveal ──────────────────────────────────────────────────────── */

.cx-reveal {
	opacity: 0;
	transform: translateY(14px);
}

.cx-reveal.is-in {
	opacity: 1;
	transform: none;
	transition: opacity 0.5s var(--cx-ease), transform 0.5s var(--cx-ease);
	transition-delay: var(--cx-delay, 0ms);
}

/* Without JavaScript the reveal must never hide content. */
.no-js .cx-reveal {
	opacity: 1;
	transform: none;
}

/* ── mobile ─────────────────────────────────────────────────────────────── */

@media (max-width: 640px) {
	.cx-panel__card {
		inline-size: 100%;
		block-size: auto;
		max-block-size: 88%;
		margin-block-start: auto;
		transform: translateY(100%);
		border-start-start-radius: var(--cx-r-lg);
		border-start-end-radius: var(--cx-r-lg);
	}

	html[dir="rtl"] .cx-panel__card {
		transform: translateY(100%);
	}

	.cx-panel {
		align-items: flex-end;
	}

	.cx-panel.is-open .cx-panel__card {
		transform: translateY(0);
	}


}

/* ── reduced motion ─────────────────────────────────────────────────────── */

/* Every animation above becomes an instant state change. Counters jump to
   their final value (handled in showcase.js), plots appear in place, and the
   panel and cards simply are where they belong. */
@media (prefers-reduced-motion: reduce) {
	.cx *,
	.cx *::before,
	.cx *::after {
		animation-duration: 0.001ms !important;
		animation-delay: 0ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		transition-delay: 0ms !important;
		scroll-behavior: auto !important;
	}

	.cx-reveal {
		opacity: 1;
		transform: none;
	}

	.cx-card:hover,
	.cx-card:focus-visible {
		transform: none;
	}

	.cx-plot--coilx:hover,
	.cx-plot--coilx:focus-visible {
		transform: none;
	}
}

/* ── richer city cards ──────────────────────────────────────────────────── */

/* The colour bar alone told a visitor nothing — orange, blue and teal mean
   nothing without a key. Each card now names its services and counts them, so
   the hue is confirmation rather than the only carrier of meaning. */

.cx-grid--city {
	grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
}

.cx-card--city {
	gap: 0.85rem;
	padding: 1.5rem 1.5rem 1.35rem;
}

.cx-card__head {
	display: grid;
	gap: 0.3rem;
}

.cx-card__services {
	display: grid;
	gap: 0.4rem;
}

.cx-card__service {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 0.5rem;
	font-size: 0.86rem;
	color: var(--cx-ink-2);
}

.cx-card__dot {
	inline-size: 9px;
	block-size: 9px;
	border-radius: 2px;
	background: var(--cx-svc, var(--cx-ink-3));
}

.cx-card__svcnum {
	font-size: 0.92rem;
	color: var(--cx-navy);
}

.cx-card__foot {
	display: grid;
	gap: 0.45rem;
	margin-block-start: auto;
	padding-block-start: 0.85rem;
	border-block-start: 1px solid var(--cx-line);
}

.cx-card__status {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.cx-card__state {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-size: 0.78rem;
	font-weight: 600;
	padding: 0.15rem 0.55rem;
	border-radius: 3px;
}

.cx-card__state--done {
	color: var(--cx-navy);
	background: var(--cx-mist);
}

.cx-card__state--wip {
	color: var(--cx-orange-text);
	background: color-mix(in srgb, var(--cx-orange) 12%, transparent);
}

/* ── find: two typeable fields ──────────────────────────────────────────── */

.cx-find {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
	gap: 1rem;
	align-items: start;
}

.cx-find__status {
	grid-column: 1 / -1;
	margin: 0;
	min-height: 1.25rem;
	font-size: 0.87rem;
	color: var(--cx-ink-soft, #4a5b6b);
}

.cx-combo {
	display: grid;
	gap: 0.4rem;
	position: relative;
}

.cx-combo__label {
	font-size: 0.85rem;
	font-weight: 600;
}

.cx-combo__box {
	display: flex;
	align-items: center;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	transition: border-color 0.2s var(--cx-ease), box-shadow 0.2s var(--cx-ease);
}

.cx-combo__box:focus-within {
	border-color: var(--cx-orange);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--cx-orange) 16%, transparent);
}

/* Tag and ancestor qualified: the theme styles bare inputs harder than a lone
   class, which is how the text in the old search box ended up #888 on white. */
.cx input.cx-combo__input,
.cx-combo__input {
	flex: 1;
	inline-size: 100%;
	min-inline-size: 0;
	font: inherit;
	font-size: 1rem;
	color: var(--cx-ink, #002c50);
	padding: 0.8rem 1rem;
	background: transparent;
	border: 0;
	outline: none;
}

.cx input.cx-combo__input::placeholder,
.cx-combo__input::placeholder {
	color: #6b7684;
	opacity: 1;
}

.cx input.cx-combo__input:disabled,
.cx-combo__input:disabled {
	color: #6b7684;
	cursor: not-allowed;
}

.cx-combo__toggle {
	display: grid;
	place-items: center;
	padding: 0 0.9rem;
	align-self: stretch;
	color: var(--cx-ink, #002c50);
	background: transparent;
	border: 0;
	cursor: pointer;
}

.cx-combo__input:disabled ~ .cx-combo__toggle {
	opacity: 0.4;
	cursor: not-allowed;
}

.cx-combo__list {
	position: absolute;
	inset-inline: 0;
	top: 100%;
	z-index: 30;
	margin-block-start: 0.35rem;
	max-height: 17rem;
	overflow-y: auto;
	padding: 0.3rem;
	list-style: none;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	box-shadow: 0 14px 34px rgba(0, 20, 40, 0.14);
}

.cx-combo__option {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.75rem;
	padding: 0.6rem 0.75rem;
	border-radius: calc(var(--cx-r) - 2px);
	cursor: pointer;
}

.cx-combo__option.is-active,
.cx-combo__option:hover {
	background: color-mix(in srgb, var(--cx-orange) 12%, transparent);
}

.cx-combo__name {
	font-weight: 600;
}

.cx-combo__meta {
	font-size: 0.8rem;
	color: var(--cx-ink-soft, #4a5b6b);
	white-space: nowrap;
}

.cx-combo__none {
	padding: 0.7rem 0.75rem;
	color: var(--cx-ink-soft, #4a5b6b);
}


/* Tag and ancestor qualified deliberately: the theme styles form inputs at a
   higher specificity than a lone class, so `color` here was losing and the text
   a visitor types came out #888 on white — 3.54:1, below the minimum. */
.cx input.cx-find__input,
.cx-find__input {
	inline-size: 100%;
	font: inherit;
	font-size: 1rem;
	color: var(--cx-ink, #002c50);
	padding: 0.85rem 1rem 0.85rem 2.85rem;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	transition: border-color 0.2s var(--cx-ease), box-shadow 0.2s var(--cx-ease);
}

html[dir="rtl"] .cx-find__input {
	padding: 0.85rem 2.85rem 0.85rem 1rem;
}

.cx-find__input:focus {
	outline: none;
	border-color: var(--cx-orange);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--cx-orange) 16%, transparent);
}

.cx-find__input::-webkit-search-cancel-button {
	display: none;
}

/* The theme's placeholder grey is #888 on white — 3.54:1, under the 4.5:1
   minimum. The placeholder here carries real instruction ("compound, city or
   unit number"), so it has to be readable, not decorative. 4.62:1. */
.cx input.cx-find__input::placeholder,
.cx-find__input::placeholder {
	color: #6b7684;
	opacity: 1;
}

.cx-find__clear {
	position: absolute;
	inset-inline-end: 0.6rem;
	inline-size: 1.9rem;
	block-size: 1.9rem;
	border-radius: 50%;
	font-size: 1.15rem;
	line-height: 1;
	color: var(--cx-ink-3);
}

.cx-find__clear:hover {
	color: var(--cx-ink);
	background: var(--cx-mist);
}

.cx-find__pickers {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
	gap: 0.75rem;
}

.cx-find__field {
	display: grid;
	gap: 0.35rem;
}

.cx-find__label {
	font-size: 0.76rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--cx-ink-3);
}

html[lang="ar"] .cx-find__label {
	letter-spacing: 0;
	text-transform: none;
	font-size: 0.84rem;
}

.cx-find__select {
	font: inherit;
	font-size: 0.94rem;
	color: var(--cx-ink);
	padding: 0.7rem 0.9rem;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	cursor: pointer;
}

.cx-find__select:disabled {
	color: var(--cx-ink-3);
	background: var(--cx-mist);
	cursor: default;
}

.cx-find__results {
	position: absolute;
	inset-inline: 0;
	inset-block-start: calc(100% + 0.4rem);
	z-index: 30;
	max-block-size: 340px;
	overflow-y: auto;
	background: var(--cx-paper);
	border: 1px solid var(--cx-line);
	border-radius: var(--cx-r);
	box-shadow: var(--cx-shadow-3);
}

.cx-find__result {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	gap: 0.6rem;
	inline-size: 100%;
	padding: 0.7rem 1rem;
	text-align: start;
	border-block-end: 1px solid var(--cx-line);
	cursor: pointer;
}

.cx-find__result:last-child {
	border-block-end: 0;
}

.cx-find__result:hover,
.cx-find__result.is-active {
	background: var(--cx-mist);
}

.cx-find__rtype {
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--cx-ink-3);
	padding: 0.15rem 0.45rem;
	background: var(--cx-mist);
	border-radius: 3px;
}

html[lang="ar"] .cx-find__rtype {
	letter-spacing: 0;
	text-transform: none;
}

.cx-find__rname {
	font-weight: 600;
}

.cx-find__rmeta {
	font-size: 0.82rem;
	color: var(--cx-ink-3);
}

.cx-find__empty {
	padding: 1rem;
	color: var(--cx-ink-3);
	text-align: center;
}

.cx-tray__summary {
	font-size: 0.92rem;
	font-weight: 600;
	color: var(--cx-stage-ink);
	margin-block-start: 0.35rem;
}

/* The drafting grid, drawn in the plan's own coordinate system. */
.cx-plan__gridline {
	fill: none;
	stroke: var(--cx-stage-grid);
	stroke-width: 1;
}

/* Shown in place of the plan when a compound has no numbered units at all. */
.cx-empty--plan {
	margin: 0;
	padding: clamp(2rem, 5vw, 3rem) 1.5rem;
	text-align: center;
	color: var(--cx-ink-soft);
	border: 1px dashed var(--cx-stage-line, rgba(255, 255, 255, 0.22));
	border-radius: 12px;
}

/* ---------------------------------------------------------------------------
   Country overview map
   ------------------------------------------------------------------------ */

/* Full-bleed: the map is the one element on the page that gains from every
   pixel, so it escapes the reading column and spans the viewport.
   `50% - 50vw` on each side is the standard break-out and is direction
   agnostic, so it behaves the same in Arabic and English. The ancestors
   already carry overflow-x: hidden, which absorbs the scrollbar width that
   100vw would otherwise add. */
.cx-map {
	display: grid;
	gap: 1rem;
	inline-size: 100vw;
	max-inline-size: 100vw;
	margin-inline: calc(50% - 50vw);
	/* No side padding and no rounding: the frame runs edge to edge. The
	   caption and tools carry their own gutter so the words stay in the
	   measure while the map takes the whole width. */
	padding-block: clamp(1rem, 3vw, 1.75rem);
	padding-inline: 0;
	background: color-mix(in srgb, var(--cx-navy) 3%, transparent);
	border-block: 1px solid var(--cx-line);
	border-inline: 0;
	border-radius: 0;
}


.cx-map__caption,
.cx-map__tools {
	/* The frame goes wide; the words stay in the measure. */
	inline-size: min(100%, var(--cx-max));
	margin-inline: auto;
	padding-inline: var(--cx-gutter);
}

.cx-map__caption {
	display: grid;
	gap: 0.35rem;
}

.cx-map__title {
	font-weight: 700;
	font-size: 1.05rem;
}

.cx-map__note {
	font-size: 0.85rem;
	line-height: 1.6;
	color: var(--cx-ink-soft, #4a5b6b);
	max-width: 68ch;
}

.cx-map__frame {
	block-size: min(72vh, 620px);
	border-radius: 0;
	overflow: hidden;
	/* Leaflet measures its container, so it must have a height before it
	   initialises — a percentage height here would resolve to zero. */
	background: color-mix(in srgb, var(--cx-orange) 5%, transparent);
}

/* Leaflet paints its own controls and attribution; these only align them with
   the rest of the page rather than restyling the map. */
.cx-map__frame .leaflet-container {
	block-size: 100%;
	font: inherit;
	background: color-mix(in srgb, var(--cx-orange) 5%, transparent);
}

.cx-map__frame .leaflet-control-attribution {
	font-size: 0.7rem;
}

/* Leaflet lays its panes out left-to-right; letting the page's RTL direction
   through mirrors the controls onto the wrong side of the map. */
.cx-map__frame .leaflet-container,
.cx-map__frame .leaflet-popup-content {
	direction: ltr;
}

html[dir="rtl"] .cx-map__frame .leaflet-popup-content,
html[dir="rtl"] .cx-map__frame .leaflet-tooltip {
	direction: rtl;
	text-align: right;
}

.cx-map__frame .leaflet-popup-content {
	margin: 0.85rem 1rem;
	line-height: 1.6;
}

.cx-pop__svc {
	color: var(--cx-ink-soft, #4a5b6b);
	font-size: 0.85em;
}

.cx-pop__go {
	display: inline-block;
	margin-block-start: 0.6rem;
	padding: 0.4rem 0.85rem;
	font: inherit;
	font-size: 0.85rem;
	font-weight: 600;
	color: #fff;
	background: var(--cx-orange);
	border: 0;
	border-radius: 999px;
	cursor: pointer;
}

.cx-pop__go:hover {
	background: color-mix(in srgb, var(--cx-orange) 84%, #000);
}

.cx-map__tools {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem 1rem;
	justify-content: space-between;
}

button.cx-map__zoom,
.cx-map__zoom {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.6rem 1.15rem;
	font: inherit;
	font-size: 0.9rem;
	font-weight: 600;
	/* Every one of these is pinned. The theme repaints button text white and
	   fills the background with its orange gradient, so a half-specified rule
	   here produced a white label on a white pill — invisible. */
	color: var(--cx-ink, #002c50);
	background-color: color-mix(in srgb, var(--cx-orange) 10%, transparent);
	background-image: none;
	border: 1px solid color-mix(in srgb, var(--cx-orange) 42%, transparent);
	border-radius: 999px;
	cursor: pointer;
	transition: background-color 0.18s ease, border-color 0.18s ease,
		transform 0.18s ease;
}

button.cx-map__zoom:hover,
.cx-map__zoom:hover {
	transform: translateY(-1px);
}

button.cx-map__zoom:hover,
button.cx-map__zoom:focus-visible,
.cx-map__zoom:hover,
.cx-map__zoom:focus-visible {
	color: var(--cx-ink, #002c50);
	background-color: color-mix(in srgb, var(--cx-orange) 22%, transparent);
	border-color: color-mix(in srgb, var(--cx-orange) 70%, transparent);
}

.cx-map__scale {
	font-size: 0.82rem;
	color: var(--cx-ink-soft, #4a5b6b);
}

/* Shorter frame on a phone, where a tall map pushes the cards off screen. */
@media (max-width: 640px) {
	.cx-map__frame {
		block-size: min(58vh, 380px);
	}
}

/* ---------------------------------------------------------------------------
   Motion — the entrance for the headline figures, and the card turn
   ------------------------------------------------------------------------ */

/* Each figure turns in, one after the next. `backwards` matters: it means the
   resting state of a stat card is simply "visible", so if the animation never
   runs — old browser, reduced motion, JS off — the numbers are still there.
   Animating INTO a visible state rather than out of an invisible one is the
   only version that cannot hide content. */
@keyframes cx-stat-in {
	from {
		opacity: 0;
		transform: translateY(18px);
	}

	to {
		opacity: 1;
		transform: translateY(0);
	}
}

.cx-stat {
	transform-origin: 50% 50%;
	animation: cx-stat-in 0.7s cubic-bezier(0.22, 0.68, 0.3, 1) backwards;
	animation-delay: calc(var(--cx-i, 0) * 150ms + 150ms);
}

/* Hovering lifts the card. No entrance animation on the card itself — see the
   note further down. Gated on a real pointer: on a phone a tap sets :hover and
   leaves it stuck, so a hover effect there never comes back off. */
@media (hover: hover) and (pointer: fine) {
	.cx-card--city,
	.cx-card--compound {
		transition: transform 0.3s var(--cx-ease), box-shadow 0.3s var(--cx-ease),
			border-color 0.3s var(--cx-ease);
	}

	.cx-card--city:hover,
	.cx-card--compound:hover {
		transform: translateY(-4px);
		box-shadow: var(--cx-shadow-3);
		border-color: color-mix(in srgb, var(--cx-orange) 40%, transparent);
	}
}

/* The cards have NO entrance animation of their own, deliberately.
 *
 * They used to, and it fought the one on the <li> that wraps them: the wrapper
 * faded the card in, then the card's own animation restarted it from
 * opacity 0 — so every card appeared, vanished and appeared again. One
 * entrance per element. The wrapper's `.cx-reveal` fade is the one that
 * stays. */

@media (prefers-reduced-motion: reduce) {
	.cx-stat {
		animation: none;
	}

	.cx-card--city:hover,
	.cx-card--compound:hover {
		animation: none;
	}
}

/* Leaflet's own controls are 30px; a finger needs more. */
@media (hover: none) {
	.cx-map__frame .leaflet-control-zoom a {
		inline-size: 44px;
		block-size: 44px;
		line-height: 44px;
		font-size: 22px;
	}
}

/* Shown only when a single finger tries to drag the map — see egypt-map.js. */
.cx-map__gesture {
	position: absolute;
	inset: 0;
	z-index: 1000;
	display: grid;
	place-items: center;
	padding: 1rem;
	text-align: center;
	font-weight: 600;
	color: #fff;
	background: rgba(0, 44, 80, 0.62);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.2s ease, visibility 0.2s ease;
	pointer-events: none;
}

.cx-map__gesture.is-on {
	opacity: 1;
	visibility: visible;
}

.cx-map__frame {
	position: relative;
}


/* ---------------------------------------------------------------------------
   Touch sizing
   ------------------------------------------------------------------------ */

/* 37px controls are fine under a cursor and awkward under a thumb. */
@media (hover: none) {
	.cx-back,
	.cx-viewtoggle__btn,
	.cx-filter {
		min-block-size: 44px;
	}

	.cx-viewtoggle__btn,
	.cx-filter {
		display: inline-flex;
		align-items: center;
	}
}

/* The plan is drawn at 1 unit = 1 pixel, which puts a villa square at 26px —
   accurate, and too small to hit reliably with a finger between its
   neighbours. On a touch screen the whole drawing is scaled up; it already
   scrolls sideways, so the only cost is a little more scrolling. The viewBox
   makes this exact, not a blur. */
@media (hover: none) and (max-width: 820px) {
	.cx-plan__canvas > svg {
		inline-size: calc(var(--cx-plan-w, 100%) * 1.4);
		block-size: auto;
		max-inline-size: none;
	}
}

/* A label over each filter row. Without one, three orange pills and three
   grey ones sat side by side with nothing saying what either row filters. */
/* Each filter row is a labelled group.
 *
 * The label used to be 0.78rem in the muted stage grey, which on a navy
 * background put it below the pills it was supposed to introduce — it read as
 * a footnote, so people saw six buttons and no question. It is now the size of
 * body copy, in the bright stage ink, with a short orange rule leading into it
 * so the eye lands on the question before the answers. */
.cx-controlgroup {
	display: grid;
	gap: 0.7rem;
	padding-block-end: 0.25rem;
}

.cx-controlgroup__label {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	font-family: var(--cx-display);
	font-size: 0.95rem;
	font-weight: 700;
	letter-spacing: 0.01em;
	color: var(--cx-stage-ink);
}

.cx-controlgroup__label::before {
	content: "";
	inline-size: 18px;
	block-size: 3px;
	border-radius: 999px;
	background: var(--cx-orange);
	flex: none;
}

/* The icon badge above each figure. */
.cx-stat__icon {
	display: grid;
	place-items: center;
	inline-size: 56px;
	block-size: 56px;
	margin-inline: auto;
	margin-block-end: 0.7rem;
	color: var(--cx-orange-text);
	background: color-mix(in srgb, var(--cx-orange) 12%, transparent);
	border-radius: 16px;
}

.cx-stat__icon svg {
	display: block;
}

/* Map pins: a filled disc that states its own number. */
.cx-pin {
	display: grid;
	place-items: center;
	box-sizing: border-box;
	border-radius: 50%;
	background: color-mix(in srgb, var(--cx-orange) 92%, transparent);
	border: 2px solid #fff;
	box-shadow: 0 2px 8px rgba(0, 20, 40, 0.28);
	color: #fff;
	font-family: var(--cx-num);
	font-variant-numeric: tabular-nums;
	font-weight: 700;
	font-size: 12px;
	line-height: 1;
	cursor: pointer;
	transition: transform 0.16s ease, background-color 0.16s ease;
}

.cx-pin--city {
	font-size: 13px;
}

.leaflet-marker-icon:hover .cx-pin,
.leaflet-marker-icon:focus .cx-pin {
	transform: scale(1.12);
	background: var(--cx-orange);
}

/* Larger discs can carry larger digits. */
.cx-pin[style*="width:4"],
.cx-pin[style*="width:5"],
.cx-pin[style*="width:6"] {
	font-size: 14px;
}

/* ---------------------------------------------------------------------------
   Find bar — TRIAL PLACEMENT
   The two fields sat inside step one, under "Choose the city". This lifts them
   to the top of the page, directly under the hero, so they are the first thing
   a visitor can act on. If the trial is rejected, move the .cx-find block back
   inside #cx-step-city (above .cx-grid--city) and delete this block.
   ------------------------------------------------------------------------ */

.cx-findbar {
	padding: clamp(1.25rem, 3vw, 2rem) var(--cx-gutter) clamp(1.5rem, 3vw, 2.25rem);
}

.cx-findbar .cx-find {
	max-width: var(--cx-max);
	margin-inline: auto;
}

/* ---------------------------------------------------------------------------
   Theme furniture this page does without
   ------------------------------------------------------------------------ */

/* The sticky mobile bar (Home · Services · Reels · Blog · Contact), hidden on
   this page only. This stylesheet is enqueued nowhere else, and the body class
   is added only here, so nothing outside the showcase can be affected.

   The matching bottom padding in the child theme stands down for the same body
   class — otherwise removing the bar would leave the 70px gap that was there to
   clear it. */
body.cx-hide-bottombar .e-con.hide-float.elementor-hidden-desktop {
	display: none;
}

/* The two floating buttons — the SalesIQ chat bubble (bottom right) and the
   theme's back-to-top arrow (bottom left) — are placed by three different
   people in three different places, and both were pushed up to clear the
   sticky bar this page no longer has:

     chat   #zsiq_float    bottom 80px   Customizer → Additional CSS
                                         (62px bar + an 18px gap above it)
     arrow  .scroll-top    bottom 30px   parent theme functions.php,
                           desktop       rami_fix_scroll_top_position()
     arrow  .scroll-top    bottom 60px   Insert Headers & Footers plugin,
                           ≤767px        !important, overriding that same
                                         function's intended 20px — and its
                                         margin-block-end: 30px still stacks
                                         on top, so the arrow ends up 90px up

   The result on this page was one button left hovering over empty space while
   the other sat low: on desktop the arrow at 30px against the chat at 80px, on
   mobile the chat at 18px against the arrow at 90px. So put both back on the
   values their own authors intended for a page with no bar — 20px on phones,
   30px from the tablet breakpoint up — which also lines their bottom edges up
   with each other.

   Scoped to this page by the body class and by this stylesheet being enqueued
   nowhere else; every other page keeps the bar and keeps the clearance.
   `!important` and the extra specificity are needed because both site rules are
   themselves !important and print after this stylesheet.

   `:not(.zsiq-toggle)` mirrors the site rule: when the chat window opens,
   SalesIQ turns the bubble into the close toggle and positions it itself — that
   state stays untouched, as does the bubble's transform (scale 1.06, origin
   bottom right), which SalesIQ animates. */
body.cx-hide-bottombar #zsiq_float.zsiq-float:not(.zsiq-toggle) {
	bottom: 30px !important;
}

@media (max-width: 767px) {
	body.cx-hide-bottombar #zsiq_float.zsiq-float:not(.zsiq-toggle) {
		bottom: 20px !important;
	}

	body.cx-hide-bottombar .scroll-top {
		bottom: 20px !important;
		margin-block-end: 0 !important;
	}
}
