/**
 * Oplus — Project Experience.
 * Single `houzez_project`. Loaded nowhere else.
 *
 * WHAT CHANGED, AND WHY
 * ---------------------
 * The page it replaces put six tabs under the hero. Tabs hid five sixths of
 * the project behind a click nobody made: gallery, floor plans, payment plan
 * and amenities were all one interaction away and all invisible to a scroller.
 * This is one continuous document with a floating anchor dock, which is the
 * shape every serious off-plan page has converged on.
 *
 * COLOUR
 * ------
 * Light editorial body, dark cinematic bands. Not a dark theme — the rest of
 * the site is light and a page that inverts wholesale reads as a different
 * website. The dark bands are used deliberately and only four times: hero,
 * payment, advisor, closing. Each is a moment where the page asks for
 * something, and the surface change is what marks it.
 *
 * Green is load-bearing, never decorative. It paints CTAs, the active dock
 * chip, and key numerals. Nothing else.
 *
 * MOTION
 * ------
 * Native CSS scroll-driven animations (`animation-timeline: view()`), with an
 * IntersectionObserver fallback that JS switches on only where the native
 * timeline is missing. No library. Consequences worth knowing:
 *
 *   - with JS off and no native support, nothing is hidden — the reveal styles
 *     are gated behind either `@supports` or `html.px-io`, never applied bare;
 *   - `prefers-reduced-motion` kills every transform and holds the end state.
 *
 * DIRECTION
 * ---------
 * Written logical-first (inline-start/end, padding-inline, text-align: start)
 * so the Arabic build needs no mirrored stylesheet. The four places that must
 * mirror physically — the dock's scroll direction, the gallery rail, the plan
 * viewer's pan, the parallax offsets — are handled in JS via `oplusPx.rtl`.
 *
 * SCOPE
 * -----
 * Every rule is under `.px` or a `px-` class so nothing can leak into the
 * header, footer, or the Houzez chrome. Tokens are the one exception and live on
 * :root — see the note above §1. `project-styles.css` is dequeued here.
 */

/* =========================================================================
   1. TOKENS

   On :root, not on `.px`. The four overlays — brochure, amenity list, lightbox,
   plan viewer — are printed at the end of the document, outside `<main class="px">`,
   because a `transform` on any ancestor would make their `position: fixed`
   resolve against that ancestor instead of the viewport. Custom properties
   inherit down the tree, so tokens declared on `.px` never reached them: the
   lightbox came out with `z-index: auto` and no colours at all.

   Declaring variables here leaks nothing — every *rule* in this file is still
   scoped to `.px` or to a `px-` class.
   ====================================================================== */

:root {
	/* Ink */
	--px-ink: #0d1418;
	--px-body: #4a5560;
	--px-faint: #737f89;

	/* Brand */
	--px-green: #00a651;
	--px-green-deep: #00813f;
	--px-green-lift: #16c368;
	--px-tint: #edf7f1;

	/* Surfaces */
	--px-paper: #ffffff;
	--px-mist: #f5f8f6;
	--px-night: #0a1013;
	--px-night-2: #111a1e;

	/* Lines */
	--px-line: #e3e9e5;
	--px-line-2: #cfd8d3;
	--px-line-night: rgba(255, 255, 255, 0.14);

	/*
	 * TYPE.
	 * Manrope for Latin, Tajawal for Arabic — loaded per direction, see
	 * `oplus_px_font_url()`. Until this was added the page inherited the theme
	 * stack and every heading read as large body copy: no weight above 700, no
	 * variable axis, and no tracking worth the name at 84px.
	 *
	 * The stack lists both families in both directions on purpose. Manrope has
	 * no Arabic glyphs and Tajawal no Latin, so a mixed string — "Q1 2028",
	 * "AED", a developer's Latin name inside an Arabic sentence — falls through
	 * to whichever family actually has the glyph, rather than to a system font
	 * that does not match either.
	 */
	--px-display: "Manrope", "Tajawal", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
	--px-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. */
	--px-t-display: clamp(2.75rem, 1.3rem + 6.2vw, 6rem);
	--px-t-h2: clamp(1.875rem, 1.3rem + 2.4vw, 3.25rem);
	--px-t-h3: clamp(1.3125rem, 1.08rem + 0.95vw, 1.75rem);
	--px-t-h4: clamp(1.0625rem, 1rem + 0.3vw, 1.25rem);
	--px-t-body: clamp(1rem, 0.97rem + 0.14vw, 1.0625rem);
	--px-t-lede: clamp(1.0625rem, 0.96rem + 0.48vw, 1.3125rem);
	--px-t-meta: 0.8125rem;
	--px-t-micro: 0.6875rem;

	/*
	 * Optical tracking. Tracking is a function of size, not of role: the same
	 * -0.04em that makes a 96px headline cohere makes 13px metadata illegible.
	 * One token per optical size, applied by the type step that uses it.
	 */
	--px-track-display: -0.045em;
	--px-track-h2: -0.032em;
	--px-track-h3: -0.022em;
	--px-track-body: -0.011em;
	--px-track-caps: 0.14em;

	/* Numerals: the figures on this page are money and dates. They get their
	   own scale and tighter tracking than the prose. */
	--px-t-figure: clamp(1.5rem, 1.15rem + 1.5vw, 2.25rem);

	/* Space */
	--px-gap: clamp(1rem, 0.6rem + 1.6vw, 2rem);
	--px-band: clamp(3.5rem, 2rem + 6vw, 7rem);
	--px-shell: 1280px;
	--px-pad: clamp(1.125rem, 0.5rem + 2.6vw, 3rem);

	/* Radii — small and consistent. Nothing on this page is a pill except
	   the dock and the chips, which are pills because they are controls. */
	--px-r: 4px;
	--px-r-2: 12px;
	--px-r-3: 20px;

	/* Elevation. Two shadows: one tight for contact, one wide and faint for
	   the floating dock, which has to read as above the document. */
	--px-sh: 0 1px 2px rgba(13, 20, 24, 0.07), 0 2px 8px rgba(13, 20, 24, 0.04);
	--px-sh-float: 0 1px 3px rgba(13, 20, 24, 0.16), 0 0 48px rgba(13, 20, 24, 0.14);

	--px-ease: cubic-bezier(0.16, 1, 0.3, 1);
	--px-dock-h: 56px;

	/*
	 * The site header is `position: sticky; z-index: 1000`. Every overlay on
	 * this page has to clear that or the header paints on top of the backdrop —
	 * so the stack is expressed here rather than as scattered magic numbers.
	 */
	--px-z-dock: 900;
	--px-z-bar: 950;
	--px-z-over: 2000;
	--px-z-modal: 2100;
}

/* =========================================================================
   2. SHELL
   ====================================================================== */

.px {
	color: var(--px-body);
	background: var(--px-paper);
	font-family: var(--px-text);
	font-size: var(--px-t-body);
	font-weight: 400;
	line-height: 1.72;
	letter-spacing: var(--px-track-body);
	overflow-x: clip;
	/* Numbers on this page are money, areas and dates that sit in columns and
	   in tables, and they have to line up. Set once here rather than on the
	   fourteen elements that carry a figure. */
	font-variant-numeric: tabular-nums;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;

	/* Numbers the bands, in document order, for the section chrome. See
	   `.px-eyebrow::after` — no PHP has to know its own index. */
	counter-reset: px-sec;
}

/*
 * The overlays are printed at the end of the document, OUTSIDE
 * `<main class="px">`, so a reset scoped to `.px` alone never reached them.
 * That is not cosmetic: every dialog input is `width: 100%` with padding and a
 * border, so under the theme's `content-box` they overflowed their column by
 * ~30px and stood ~74px tall instead of 48. The forms looked broken because
 * they were.
 *
 * Same trap as the design tokens, which is why those live on :root. Any new
 * overlay root has to be added here as well.
 */
.px *,
.px *::before,
.px *::after,
.px-modal,
.px-modal *,
.px-modal *::before,
.px-modal *::after,
.px-lb,
.px-lb *,
.px-lb *::before,
.px-lb *::after,
.px-viewer,
.px-viewer *,
.px-viewer *::before,
.px-viewer *::after {
	box-sizing: border-box;
}

/*
 * And the handful of element defaults the overlays need for the same reason.
 * Kept to what a dialog actually contains — headings, links, images, lists —
 * rather than duplicating the whole base layer.
 */
.px-modal h2,
.px-modal h3,
.px-modal h4 {
	color: var(--px-ink);
	font-family: var(--px-display);
	font-weight: 700;
	line-height: 1.16;
	letter-spacing: var(--px-track-h3);
	margin: 0;
}

.px-modal p {
	margin: 0 0 1em;
}

.px-modal p:last-child {
	margin-bottom: 0;
}

.px-modal img {
	max-width: 100%;
	display: block;
}

.px-modal a {
	color: var(--px-green-deep);
	text-decoration: none;
}

.px-modal a:hover {
	color: var(--px-green);
}

.px-modal :focus-visible,
.px-lb :focus-visible,
.px-viewer :focus-visible {
	outline: 2px solid var(--px-green);
	outline-offset: 3px;
	border-radius: 2px;
}

/*
 * `[hidden]` is a UA-stylesheet rule, so ANY author `display` beats it. This
 * page hides tab panels with the attribute and then styles them with
 * `display: grid` — which silently un-hid every panel at once, stacking all
 * three floor-plan layouts down the page on the live site. Restating it here
 * with `!important` is the one place that flag is the correct tool: the whole
 * point of the attribute is that it outranks layout.
 */
.px [hidden],
.px-modal[hidden],
.px-lb[hidden],
.px-viewer[hidden] {
	display: none !important;
}

.px h1,
.px h2,
.px h3,
.px h4,
.px h5 {
	color: var(--px-ink);
	font-family: var(--px-display);
	font-weight: 800;
	line-height: 1.1;
	letter-spacing: var(--px-track-h3);
	margin: 0;
	/* Long project names ("Mira Ocean Estates by Mira Developments, Salalah")
	   otherwise leave one orphaned word on the last line at every width. */
	text-wrap: balance;
}

/* Arabic sets at a heavier optical weight than Latin at the same nominal
   weight, and Tajawal's descenders need more room than Manrope's. */
[dir="rtl"] .px h1,
[dir="rtl"] .px h2,
[dir="rtl"] .px h3,
[dir="rtl"] .px h4,
[dir="rtl"] .px h5 {
	font-weight: 700;
	line-height: 1.3;
	letter-spacing: 0;
}

[dir="rtl"] .px {
	letter-spacing: 0;
	line-height: 1.9;
}

.px p {
	margin: 0 0 1em;
}

.px p:last-child {
	margin-bottom: 0;
}

.px img {
	max-width: 100%;
	height: auto;
	display: block;
}

.px a {
	color: var(--px-green-deep);
	text-decoration: none;
	transition: color 0.18s ease;
}

.px a:hover {
	color: var(--px-green);
}

.px :focus-visible {
	outline: 2px solid var(--px-green);
	outline-offset: 3px;
	border-radius: 2px;
}

.px-shell {
	width: 100%;
	max-width: var(--px-shell);
	margin-inline: auto;
	padding-inline: var(--px-pad);
}

.px-band {
	position: relative;
	padding-block: var(--px-band);
	scroll-margin-top: 90px;
}

.px-band--mist {
	background: var(--px-mist);
}

/* The dark bands. `isolation` so the media layer's z-index cannot escape into
   the next section. */
.px-band--night {
	background: var(--px-night);
	color: rgba(255, 255, 255, 0.74);
	isolation: isolate;
}

/* `.px` is carried on the selector so these outrank the base `.px h1…h5` ink
   rule on specificity rather than on source order. Tied specificity that happens
   to resolve correctly is a trap for whoever reorders this file next — the
   headline on the hero was already lost to exactly that. */
.px .px-band--night h2,
.px .px-band--night h3,
.px .px-band--night h4 {
	color: #fff;
}

.px-band--night a {
	color: #fff;
}

.px-band--hair {
	border-top: 1px solid var(--px-line);
}

/* Section chrome: a rule, an eyebrow, a heading, an optional aside. Repeated
   verbatim in every band — that repetition is the thing that makes eight very
   different sections read as one page. */
.px-head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--px-gap);
	margin-bottom: clamp(1.75rem, 1rem + 2.4vw, 3rem);
}

.px-head-copy {
	max-width: 62ch;
}

/* Bands with an id are the ones the dock links to, and the ones worth
   numbering. Hero and ledger carry no id and so are skipped. */
.px-band[id] {
	counter-increment: px-sec;
}

.px-eyebrow {
	display: flex;
	align-items: center;
	gap: 12px;
	margin: 0 0 16px;
	font-family: var(--px-display);
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-green-deep);
}

/* The rule draws itself when the band arrives — a 26px static dash is a
   decoration, a rule that grows is the section opening. */
.px-eyebrow::before {
	content: "";
	width: 34px;
	height: 2px;
	background: currentColor;
	flex: none;
	transform-origin: left center;
}

[dir="rtl"] .px-eyebrow::before {
	transform-origin: right center;
}

/* The index. `decimal-leading-zero` gives 01…09 without a PHP str_pad, and the
   counter tracks document order, so inserting a band renumbers everything
   after it automatically. */
.px-band[id] .px-eyebrow::after {
	content: counter(px-sec, decimal-leading-zero);
	margin-inline-start: auto;
	padding-inline-start: 16px;
	font-size: 0.75rem;
	font-weight: 800;
	letter-spacing: 0;
	color: var(--px-line-2);
}

/* Centred heads (FAQ) would otherwise push the index to the far right of a
   centred column. */
.px-head-copy[style*="auto"] .px-eyebrow::after,
.px-eyebrow[style*="center"]::after {
	margin-inline-start: 0;
}

.px-band--night .px-eyebrow {
	color: var(--px-green-lift);
}

.px-band--night .px-eyebrow::after {
	color: rgba(255, 255, 255, 0.26);
}

.px-h2 {
	font-size: var(--px-t-h2);
	letter-spacing: var(--px-track-h2);
	line-height: 1.06;
}

[dir="rtl"] .px-h2 {
	letter-spacing: 0;
	line-height: 1.32;
}

.px-sub {
	margin: 14px 0 0;
	font-size: var(--px-t-lede);
	color: var(--px-faint);
	line-height: 1.62;
}

.px-band--night .px-sub {
	color: rgba(255, 255, 255, 0.62);
}

/* =========================================================================
   3. CONTROLS
   ====================================================================== */

.px-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
	min-height: 48px;
	padding: 0 26px;
	border: 1px solid transparent;
	border-radius: var(--px-r);
	font-size: 0.9375rem;
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: -0.005em;
	text-align: center;
	cursor: pointer;
	transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s var(--px-ease);
}

.px-btn:active {
	transform: translateY(1px);
}

.px-btn--solid {
	background: var(--px-green);
	border-color: var(--px-green);
	color: #fff !important;
}

.px-btn--solid:hover {
	background: var(--px-green-deep);
	border-color: var(--px-green-deep);
	color: #fff !important;
}

.px-btn--line {
	background: transparent;
	border-color: var(--px-line-2);
	color: var(--px-ink) !important;
}

.px-btn--line:hover {
	border-color: var(--px-ink);
	color: var(--px-ink) !important;
}

/* On a dark surface a grey outline disappears. */
.px-band--night .px-btn--line,
.px-hero .px-btn--line {
	border-color: rgba(255, 255, 255, 0.34);
	color: #fff !important;
	backdrop-filter: blur(6px);
}

.px-band--night .px-btn--line:hover,
.px-hero .px-btn--line:hover {
	border-color: #fff;
	background: rgba(255, 255, 255, 0.1);
}

.px-btn--ghost {
	background: transparent;
	border-color: transparent;
	color: var(--px-green-deep) !important;
	padding-inline: 0;
	min-height: 40px;
}

.px-btn--ghost:hover {
	color: var(--px-green) !important;
	gap: 14px;
}

.px-actions {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

/* Chip rails — used by the gallery filter, the unit switcher and the dock.
   One implementation, three contexts. */
.px-chips {
	display: flex;
	gap: 8px;
	overflow-x: auto;
	scrollbar-width: none;
	padding-block: 4px;
	scroll-snap-type: x proximity;
	-webkit-overflow-scrolling: touch;
}

.px-chips::-webkit-scrollbar {
	display: none;
}

.px-chip {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	flex: none;
	min-height: 44px;
	padding: 0 18px;
	border: 1px solid var(--px-line);
	border-radius: 999px;
	background: var(--px-paper);
	color: var(--px-body);
	font-size: 0.875rem;
	font-weight: 600;
	white-space: nowrap;
	cursor: pointer;
	scroll-snap-align: start;
	transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.px-chip:hover {
	border-color: var(--px-line-2);
	color: var(--px-ink);
}

.px-chip[aria-selected="true"],
.px-chip.is-on {
	background: var(--px-ink);
	border-color: var(--px-ink);
	color: #fff;
}

.px-chip-n {
	font-size: var(--px-t-micro);
	font-weight: 700;
	opacity: 0.6;
	font-variant-numeric: tabular-nums;
}

.px-i {
	flex: none;
}

/* =========================================================================
   4. MOTION PRIMITIVES
   ====================================================================== */

@keyframes px-rise {
	from {
		opacity: 0;
		transform: translateY(26px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes px-fade {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

/* Hero media drifts up and de-scales as the hero leaves. Range is `cover` so
   it runs for the whole time the element intersects the viewport. */
@keyframes px-drift {
	from {
		transform: scale(1.12) translateY(0);
	}
	to {
		transform: scale(1) translateY(-6%);
	}
}

@keyframes px-sink {
	from {
		opacity: 1;
		transform: none;
	}
	to {
		opacity: 0.25;
		transform: translateY(38px);
	}
}

@supports (animation-timeline: view()) {

	.px-rise {
		animation: px-rise 1s linear both;
		animation-timeline: view();
		animation-range: entry 6% entry 62%;
	}

	/* Stagger by nth-child rather than per-element inline delay: a scroll
	   timeline ignores `animation-delay` in time units, so the offset has to be
	   expressed as a shifted range. */
	[data-px-stagger] > * {
		animation: px-rise 1s linear both;
		animation-timeline: view();
	}

	[data-px-stagger] > :nth-child(1) { animation-range: entry 6% entry 58%; }
	[data-px-stagger] > :nth-child(2) { animation-range: entry 10% entry 64%; }
	[data-px-stagger] > :nth-child(3) { animation-range: entry 14% entry 70%; }
	[data-px-stagger] > :nth-child(4) { animation-range: entry 18% entry 76%; }
	[data-px-stagger] > :nth-child(5) { animation-range: entry 22% entry 82%; }
	[data-px-stagger] > :nth-child(n + 6) { animation-range: entry 26% entry 88%; }

	.px-hero-media img {
		animation: px-drift 1s linear both;
		animation-timeline: view();
		animation-range: cover;
	}

	.px-hero-inner {
		animation: px-sink 1s linear both;
		animation-timeline: view();
		animation-range: exit -10% exit 70%;
	}
}

/* Fallback, switched on by JS only when the native timeline is absent. */
html.px-io .px-rise,
html.px-io [data-px-stagger] > * {
	opacity: 0;
	transform: translateY(26px);
	transition: opacity 0.8s var(--px-ease), transform 0.8s var(--px-ease);
}

html.px-io .px-rise.is-in,
html.px-io [data-px-stagger] > .is-in {
	opacity: 1;
	transform: none;
}

/* =========================================================================
   4b. OVERLAY HEADER

   The site header is a shared component: `position: sticky`, solid white, in
   the flow. On this template it floats over the hero instead, and turns solid
   once the hero is behind it. Everything is behind `body.px-overlay-header`,
   so no other template is touched and removing the body class restores the
   stock header exactly.
   ====================================================================== */

body.px-overlay-header .oplus-header {
	position: fixed;
	inset-inline: 0;
	top: 0;
	background: transparent;
	box-shadow: none;
	border-bottom-color: transparent;
	transition: background-color 0.35s ease, box-shadow 0.35s ease, border-color 0.35s ease;
}

/* Leaving the flow would collapse the 80px the header used to occupy and pull
   every page up under it. The hero *wants* that — it should start at the top of
   the viewport — so the space is given back only above the hero. */
body.px-overlay-header .px-hero {
	margin-top: calc(-1 * var(--px-header-h, 80px));
}

/* A scrim, not a colour. The header sits over a photograph whose top edge is
   the brightest part of the image on a daylight render, and white marks need
   something behind them. It fades out with the solid state. */
body.px-overlay-header .oplus-header::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: 0;
	height: 180%;
	z-index: -1;
	pointer-events: none;
	background: linear-gradient(to bottom, rgba(5, 9, 11, 0.62), transparent);
	transition: opacity 0.35s ease;
}

/* White marks while transparent. Scoped tightly to the header's own BEM
   children so nothing inside a mega-menu panel — which is its own white
   surface — gets dragged to white with it. */
body.px-overlay-header:not(.px-header-solid) .oplus-header__link,
body.px-overlay-header:not(.px-header-solid) .oplus-header__lang,
body.px-overlay-header:not(.px-header-solid) .oplus-header__toggle,
body.px-overlay-header:not(.px-header-solid) .oplus-header__burger {
	color: #fff;
}

body.px-overlay-header:not(.px-header-solid) .oplus-header__chevron {
	border-color: rgba(255, 255, 255, 0.85);
	color: rgba(255, 255, 255, 0.85);
}

/*
 * The logo is a single colour-on-transparent mark. `brightness(0) invert(1)`
 * flattens it to white regardless of its own palette, which is the only
 * treatment that works without shipping a second logo file the client would
 * have to maintain.
 */
body.px-overlay-header:not(.px-header-solid) .oplus-header__logo-img {
	filter: brightness(0) invert(1);
	transition: filter 0.35s ease;
}

/* The burger's bars are usually drawn with background-color, not color. */
body.px-overlay-header:not(.px-header-solid) .oplus-header__burger span,
body.px-overlay-header:not(.px-header-solid) .oplus-header__toggle span {
	background-color: #fff;
}

/* ---- Solid state, once the hero is behind us ---- */

body.px-overlay-header.px-header-solid .oplus-header {
	background: #fff;
	box-shadow: 0 2px 20px rgba(0, 0, 0, 0.08);
	border-bottom-color: #f0f0f0;
}

body.px-overlay-header.px-header-solid .oplus-header::before {
	opacity: 0;
}

/*
 * An open mega-menu needs a readable surface whatever the header is doing, and
 * a transparent header with a white dropdown hanging off it reads as broken.
 * Any hover/focus inside the nav forces the solid state.
 */
body.px-overlay-header .oplus-header__nav:hover ~ *,
body.px-overlay-header .oplus-header:hover,
body.px-overlay-header .oplus-header:focus-within {
	background: #fff;
}

body.px-overlay-header .oplus-header:hover .oplus-header__link,
body.px-overlay-header .oplus-header:focus-within .oplus-header__link,
body.px-overlay-header .oplus-header:hover .oplus-header__lang,
body.px-overlay-header .oplus-header:focus-within .oplus-header__lang {
	color: var(--px-ink);
}

body.px-overlay-header .oplus-header:hover .oplus-header__logo-img,
body.px-overlay-header .oplus-header:focus-within .oplus-header__logo-img {
	filter: none;
}

body.px-overlay-header .oplus-header:hover::before,
body.px-overlay-header .oplus-header:focus-within::before {
	opacity: 0;
}

/* Touch devices have no hover, so the mobile menu opening is the signal. */
body.px-overlay-header.px-menu-open .oplus-header {
	background: #fff;
}

body.px-overlay-header.px-menu-open .oplus-header__logo-img {
	filter: none;
}

body.px-overlay-header.px-menu-open .oplus-header__link,
body.px-overlay-header.px-menu-open .oplus-header__lang {
	color: var(--px-ink);
}

/* =========================================================================
   5. HERO
   ====================================================================== */

.px-hero {
	position: relative;
	isolation: isolate;
	display: flex;
	align-items: flex-end;
	/* vh first so a browser without svh still gets a full stage. */
	min-height: 88vh;
	min-height: 88svh;
	max-height: 980px;
	overflow: hidden;
	background: var(--px-night);
	color: #fff;
}

.px-hero-media {
	position: absolute;
	inset: 0;
	z-index: 0;
	overflow: hidden;
}

.px-hero-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* The drift keyframe starts at 1.12; without it here the un-animated
	   fallback would show the image at its natural scale and the reveal would
	   pop on browsers that do support the timeline. */
	transform: scale(1.06);
}

/* Two scrims, not one. A single flat overlay greys the photograph; a vertical
   ramp plus a wash from the copy side keeps the sky readable as a photograph and
   still gets white text to AA over it.
   The ramp is heavy through the bottom 55% on purpose — the hero is bottom
   aligned, so that is exactly the band the headline and lede occupy. Measured
   against a bright daylight render (white render, glazing, pale stone), which is
   the worst case in the library: at 0.82 the 15px lede was failing. */
.px-hero-media::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(to top,
			rgba(5, 9, 11, 0.96) 0%,
			rgba(5, 9, 11, 0.9) 30%,
			rgba(5, 9, 11, 0.66) 55%,
			rgba(5, 9, 11, 0.3) 78%,
			rgba(5, 9, 11, 0.42) 100%),
		linear-gradient(to right, rgba(5, 9, 11, 0.62), rgba(5, 9, 11, 0.1) 58%, transparent 78%);
}

/* The wash has to follow the copy, and a gradient direction is physical — there
   is no logical `to inline-start`. This is the one place in the file that needs
   a mirrored declaration. */
[dir="rtl"] .px-hero-media::after {
	background:
		linear-gradient(to top,
			rgba(5, 9, 11, 0.96) 0%,
			rgba(5, 9, 11, 0.9) 30%,
			rgba(5, 9, 11, 0.66) 55%,
			rgba(5, 9, 11, 0.3) 78%,
			rgba(5, 9, 11, 0.42) 100%),
		linear-gradient(to left, rgba(5, 9, 11, 0.62), rgba(5, 9, 11, 0.1) 58%, transparent 78%);
}

/* Pulls the eye off the corners and toward the copy. Separate from the scrim
   because the scrim is a contrast tool and this is a compositional one — they
   need to be tuned against different things. */
.px-hero-vignette {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	background: radial-gradient(120% 90% at 50% 38%, transparent 40%, rgba(4, 8, 10, 0.55) 100%);
}

/* Large smooth gradients band visibly on 8-bit panels, and the hero is one of
   the largest on the web. A little noise breaks the bands up. It is a data URI
   because a request for 400 bytes of PNG is not worth a round trip. */
.px-hero-grain {
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	opacity: 0.055;
	mix-blend-mode: overlay;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

.px-hero-inner {
	position: relative;
	z-index: 2;
	width: 100%;
	max-width: var(--px-shell);
	margin-inline: auto;
	/* The slab carries its own padding now, so the stage only has to clear the
	   floating header at the top and leave a margin at the bottom. */
	padding: calc(var(--px-header-h, 80px) + clamp(2rem, 1rem + 5vw, 5rem)) var(--px-pad) clamp(1.5rem, 1rem + 2.5vw, 3rem);
}

/* ---- The glass slab ----------------------------------------------------
   Real glass is three things, and most attempts only do the first: a blur, a
   tint that is not flat, and a lit edge. The top border is brighter than the
   bottom one because light comes from above — without that the panel reads as
   a grey rectangle with a blur filter on it. */

.px-hero-slab {
	position: relative;
	padding: clamp(1.5rem, 1rem + 2.4vw, 2.75rem);
	border-radius: var(--px-r-3);
	background:
		linear-gradient(160deg, rgba(255, 255, 255, 0.13), rgba(255, 255, 255, 0.04) 42%, rgba(255, 255, 255, 0.07));
	backdrop-filter: blur(26px) saturate(1.35);
	-webkit-backdrop-filter: blur(26px) saturate(1.35);
	box-shadow:
		inset 0 1px 0 rgba(255, 255, 255, 0.34),
		inset 0 -1px 0 rgba(255, 255, 255, 0.08),
		inset 1px 0 0 rgba(255, 255, 255, 0.1),
		inset -1px 0 0 rgba(255, 255, 255, 0.1),
		0 24px 60px rgba(3, 7, 9, 0.42);
}

/*
 * Without backdrop-filter the panel would be a barely-tinted rectangle over a
 * photograph and the copy would fail contrast outright. Firefox has shipped it
 * for years and Safari needs the prefix above, so this is a genuine fallback
 * rather than a courtesy: a solid dark panel, no blur.
 */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {

	.px-hero-slab {
		background: rgba(8, 13, 16, 0.82);
	}
}

.px-hero-grid {
	display: grid;
	gap: clamp(1.5rem, 0.8rem + 2.6vw, 3rem);
	align-items: end;
}

@media (min-width: 62rem) {
	.px-hero-grid {
		grid-template-columns: minmax(0, 1.5fr) minmax(300px, 0.8fr);
	}

}

.px-hero-eyebrow {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 14px;
	margin: 0 0 20px;
	font-size: var(--px-t-meta);
	font-weight: 600;
	letter-spacing: 0.01em;
	color: rgba(255, 255, 255, 0.82);
}

.px-hero-eyebrow > span {
	display: inline-flex;
	align-items: center;
	gap: 6px;
}

.px-hero-eyebrow .px-dot {
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.42);
}

.px-hero-eyebrow a {
	color: #fff;
	border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}

.px-flag {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 6px 14px 6px 10px;
	border-radius: 999px;
	background: rgba(0, 166, 81, 0.16);
	border: 1px solid rgba(22, 195, 104, 0.42);
	color: #7fe8ac;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.px-flag::before {
	content: "";
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--px-green-lift);
	box-shadow: 0 0 0 0 rgba(22, 195, 104, 0.7);
	animation: px-pulse 2.4s ease-out infinite;
}

@keyframes px-pulse {
	70% {
		box-shadow: 0 0 0 8px rgba(22, 195, 104, 0);
	}
	100% {
		box-shadow: 0 0 0 0 rgba(22, 195, 104, 0);
	}
}

/* `.px h1` (0,1,1) outranks a bare `.px-hero-title` (0,1,0), so the base ink
   colour won and the headline rendered near-black on the photograph. Scoped to
   `.px-hero` to take the specificity back. */
.px-hero .px-hero-title {
	color: #fff;
	font-size: var(--px-t-display);
	font-weight: 800;
	letter-spacing: var(--px-track-display);
	line-height: 0.98;
	margin: 0 0 22px;
	text-wrap: balance;
}

[dir="rtl"] .px-hero .px-hero-title {
	font-weight: 700;
	letter-spacing: 0;
	line-height: 1.24;
}

/* ---- Masked line reveal ----------------------------------------------
   JS wraps each rendered line (it can only know where they break after
   layout). The outer span is the mask; the inner one is what moves. Nothing
   here applies until `.is-split` is set, so a browser that never runs the
   script shows an ordinary heading. */

.px-line {
	display: block;
	overflow: hidden;
	/* The descenders of a masked line get clipped without slack, and the
	   negative margin takes the slack back out of the line box. */
	padding-bottom: 0.14em;
	margin-bottom: -0.14em;
}

.px-line > span {
	display: block;
	will-change: transform;
}

.px-hero-title.is-split .px-line > span {
	transform: translateY(105%);
	opacity: 0;
}

.px-hero-title.is-split.is-lit .px-line > span {
	transform: none;
	opacity: 1;
	transition: transform 1.05s var(--px-ease), opacity 0.7s ease;
	transition-delay: calc(var(--px-line-i, 0) * 90ms);
}

/* Everything else in the hero follows the headline in, on the same curve. */
.px-hero .px-lift {
	opacity: 0;
	transform: translateY(20px);
}

.px-hero.is-lit .px-lift {
	opacity: 1;
	transform: none;
	transition: opacity 0.8s ease var(--px-lift-d, 0s), transform 0.9s var(--px-ease) var(--px-lift-d, 0s);
}

.px-hero-lede {
	max-width: 56ch;
	font-size: var(--px-t-lede);
	line-height: 1.62;
	color: rgba(255, 255, 255, 0.8);
	margin: 0 0 28px;
}

.px-hero-call {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	margin-top: 22px;
	font-size: 0.9375rem;
	color: rgba(255, 255, 255, 0.78) !important;
}

.px-hero-call strong {
	color: #fff;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

/* The figures column. It no longer carries its own glass — it sits inside the
   slab now, and glass on glass produces a muddy double-blur with two competing
   edges. */
.px-hero-card {
	padding: 0;
	border: 0;
	background: none;
}

/*
 * The divider between the copy and the figures, declared here rather than in
 * the earlier `min-width: 62rem` block. It was in that block first, and the
 * `border: 0` reset directly above — same specificity, later in the file — won
 * and silently erased it at every width.
 */
@media (min-width: 62rem) {

	.px-hero-card {
		border-inline-start: 1px solid rgba(255, 255, 255, 0.16);
		padding-inline-start: clamp(1.5rem, 1rem + 2vw, 2.5rem);
	}
}

.px-hero-figs {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
	gap: 18px 24px;
	margin-bottom: 20px;
}

.px-fig-k {
	display: block;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.58);
	margin-bottom: 7px;
}

.px-fig-v {
	display: block;
	font-size: var(--px-t-figure);
	font-weight: 700;
	letter-spacing: -0.03em;
	line-height: 1.05;
	color: #fff;
	font-variant-numeric: tabular-nums;
}

.px-fig-v small {
	font-size: 0.5em;
	font-weight: 700;
	letter-spacing: 0.06em;
	color: var(--px-green-lift);
	margin-inline-end: 4px;
	vertical-align: 0.35em;
}

.px-hero-card .px-actions {
	flex-direction: column;
}

.px-hero-card .px-btn {
	width: 100%;
}

/* Scroll cue. Deliberately small; a full-height hero needs to admit there is
   more below it, and nothing more. */
.px-cue {
	position: absolute;
	inset-inline-start: 50%;
	bottom: 14px;
	z-index: 2;
	transform: translateX(-50%);
	width: 1px;
	height: 42px;
	background: linear-gradient(to bottom, transparent, rgba(255, 255, 255, 0.6));
	overflow: hidden;
}

.px-cue::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: -100%;
	height: 100%;
	background: #fff;
	animation: px-cue 2.6s var(--px-ease) infinite;
}

@keyframes px-cue {
	to {
		top: 100%;
	}
}

/* =========================================================================
   6. LEDGER  —  the term-sheet strip under the hero
   ====================================================================== */

.px-ledger {
	position: relative;
	z-index: 3;
	margin: 0;
	background: var(--px-paper);
	border-bottom: 1px solid var(--px-line);
}

.px-ledger-row {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	max-width: var(--px-shell);
	margin-inline: auto;
	padding-inline: var(--px-pad);
}

.px-ledger-cell {
	padding: clamp(1.1rem, 0.8rem + 1vw, 1.75rem) 20px;
	border-inline-start: 1px solid var(--px-line);
}

.px-ledger-cell:first-child {
	border-inline-start: 0;
	padding-inline-start: 0;
}

.px-ledger-cell dt {
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--px-faint);
	margin-bottom: 8px;
}

.px-ledger-cell dd {
	margin: 0;
	font-size: clamp(1.125rem, 1rem + 0.6vw, 1.5rem);
	font-weight: 700;
	letter-spacing: -0.026em;
	line-height: 1.1;
	color: var(--px-ink);
	font-variant-numeric: tabular-nums;
}

.px-ledger-cell--key dd {
	color: var(--px-green-deep);
}

.px-cur {
	font-size: 0.6em;
	letter-spacing: 0.05em;
	color: var(--px-faint);
	margin-inline-end: 4px;
	vertical-align: 0.2em;
}

.px-unit {
	font-size: 0.62em;
	font-weight: 600;
	color: var(--px-faint);
	letter-spacing: 0;
}

/* =========================================================================
   7. DOCK  —  the floating anchor nav
   ====================================================================== */

.px-dock {
	position: fixed;
	z-index: var(--px-z-dock);
	inset-inline: 0;
	bottom: max(20px, env(safe-area-inset-bottom));
	display: flex;
	justify-content: center;
	pointer-events: none;
	/* Held out of the way until the hero is behind us: a nav that overlaps a
	   full-bleed hero on load looks like a mistake. JS adds .is-up. */
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 0.4s var(--px-ease), transform 0.4s var(--px-ease);
}

.px-dock.is-up {
	opacity: 1;
	transform: none;
	pointer-events: auto;
}

.px-dock-inner {
	position: relative;
	display: flex;
	align-items: center;
	max-width: calc(100vw - 2 * var(--px-pad));
	padding: 5px;
	border-radius: var(--px-r-2);
	background: rgba(255, 255, 255, 0.9);
	backdrop-filter: blur(18px) saturate(1.4);
	-webkit-backdrop-filter: blur(18px) saturate(1.4);
	box-shadow: var(--px-sh-float);
}

.px-dock-track {
	display: flex;
	gap: 2px;
	overflow-x: auto;
	scrollbar-width: none;
	scroll-behavior: smooth;
}

.px-dock-track::-webkit-scrollbar {
	display: none;
}

.px-dock-link {
	flex: none;
	min-height: 42px;
	padding: 0 16px;
	border: 0;
	border-radius: 8px;
	background: transparent;
	color: var(--px-body);
	font-size: 0.875rem;
	font-weight: 600;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease;
}

.px-dock-link:hover {
	background: var(--px-mist);
	color: var(--px-ink);
}

.px-dock-link[aria-current="true"] {
	background: var(--px-ink);
	color: #fff;
}

/* The dock's own CTA, fused to the right of the rail. This is the reason the
   dock earns a fixed position at all — it keeps one live conversion control on
   screen for the whole page without a second sticky element. */
.px-dock-cta {
	flex: none;
	min-height: 42px;
	margin-inline-start: 6px;
	padding: 0 18px;
	border: 0;
	border-radius: 8px;
	background: var(--px-green);
	color: #fff !important;
	font-size: 0.875rem;
	font-weight: 700;
	white-space: nowrap;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	transition: background-color 0.2s ease;
}

.px-dock-cta:hover {
	background: var(--px-green-deep);
	color: #fff !important;
}

/* Reading progress, drawn on the dock's own edge. */
.px-dock-bar {
	position: absolute;
	inset-inline: 5px;
	bottom: 1px;
	height: 2px;
	border-radius: 2px;
	background: var(--px-green);
	transform-origin: left center;
	transform: scaleX(0);
	transition: transform 0.15s linear;
}

.px [dir="rtl"] .px-dock-bar,
[dir="rtl"] .px .px-dock-bar {
	transform-origin: right center;
}

/* Under 62rem the dock loses its CTA label and the mobile action bar takes
   over the conversion job — two fixed CTAs on a 375px screen is one too many. */
@media (max-width: 61.99rem) {
	.px-dock {
		bottom: calc(64px + max(0px, env(safe-area-inset-bottom)));
	}

	.px-dock-cta {
		display: none;
	}
}

/* =========================================================================
   8. OVERVIEW
   ====================================================================== */

.px-crumbs {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-bottom: clamp(2rem, 1.4rem + 2vw, 3rem);
	font-size: var(--px-t-meta);
	color: var(--px-faint);
}

.px-crumbs a {
	color: var(--px-faint);
}

.px-crumbs a:hover {
	color: var(--px-ink);
}

.px-crumbs span[aria-hidden] {
	opacity: 0.5;
}

.px-crumbs [aria-current] {
	color: var(--px-ink);
	font-weight: 600;
}

.px-split {
	display: grid;
	gap: clamp(2rem, 1rem + 4vw, 4.5rem);
	align-items: start;
}

@media (min-width: 62rem) {
	.px-split {
		grid-template-columns: minmax(0, 1.6fr) minmax(300px, 0.9fr);
	}
}

/*
 * The definition block. Set larger than the body and marked with a rule so it
 * reads as the page's own summary rather than as the first paragraph of the
 * marketing copy underneath it — which is the distinction that makes it worth
 * quoting.
 */
.px-define {
	margin: 0 0 24px;
	padding-inline-start: 18px;
	border-inline-start: 2px solid var(--px-green);
	font-size: var(--px-t-lede);
	font-weight: 500;
	line-height: 1.6;
	letter-spacing: var(--px-track-body);
	color: var(--px-ink);
	text-wrap: pretty;
}

/* Long-form project copy. The editor output is unpredictable — h2/h3/ul/blockquote
   in any order — so it is styled by element inside one scope rather than by class. */
.px-prose {
	font-size: var(--px-t-body);
	line-height: 1.78;
	color: var(--px-body);
}

.px-prose > :first-child {
	margin-top: 0;
}

.px-prose h2,
.px-prose h3,
.px-prose h4 {
	margin: 2em 0 0.7em;
	font-size: var(--px-t-h3);
	letter-spacing: -0.02em;
}

.px-prose h4 {
	font-size: var(--px-t-h4);
}

.px-prose strong {
	color: var(--px-ink);
	font-weight: 700;
}

.px-prose ul,
.px-prose ol {
	margin: 0 0 1.4em;
	padding-inline-start: 0;
	list-style: none;
}

.px-prose ol {
	counter-reset: px-o;
}

.px-prose li {
	position: relative;
	padding-inline-start: 30px;
	margin-bottom: 0.7em;
}

.px-prose ul li::before {
	content: "";
	position: absolute;
	inset-inline-start: 6px;
	top: 0.72em;
	width: 7px;
	height: 7px;
	border: 1.5px solid var(--px-green);
	border-radius: 50%;
}

.px-prose ol li {
	counter-increment: px-o;
}

.px-prose ol li::before {
	content: counter(px-o);
	position: absolute;
	inset-inline-start: 0;
	top: 0;
	font-size: var(--px-t-meta);
	font-weight: 700;
	color: var(--px-green-deep);
	font-variant-numeric: tabular-nums;
}

.px-prose blockquote {
	margin: 1.6em 0;
	padding-inline-start: 22px;
	border-inline-start: 2px solid var(--px-green);
	font-size: var(--px-t-lede);
	color: var(--px-ink);
}

.px-prose img {
	border-radius: var(--px-r-2);
	margin-block: 1.6em;
}

/* Truncated story with a real disclosure. Editors write 900 words; the fold is
   a max-height rather than a line count because the copy contains lists and
   sub-headings whose line-height differs. */
.px-clamp {
	position: relative;
	overflow: hidden;
	transition: max-height 0.5s var(--px-ease);
}

.px-clamp[data-px-clamp="on"] {
	max-height: 27em;
}

.px-clamp[data-px-clamp="on"]::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	height: 8em;
	background: linear-gradient(to bottom, transparent, var(--px-paper) 82%);
	pointer-events: none;
}

.px-clamp-btn {
	margin-top: 18px;
}

/* Spec table. Label→value rows, hairlines, no card. The reference uses exactly
   this and it is right: a buyer scans it, they do not read it. */
.px-specs {
	margin: 0;
	border-top: 1px solid var(--px-line);
}

.px-specs div {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 20px;
	padding: 15px 0;
	border-bottom: 1px solid var(--px-line);
}

.px-specs dt {
	font-size: var(--px-t-meta);
	color: var(--px-faint);
	flex: none;
}

.px-specs dd {
	margin: 0;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--px-ink);
	text-align: end;
}

.px-specs dd a {
	border-bottom: 1px solid currentColor;
}

.px-aside {
	position: sticky;
	top: 96px;
}

.px-aside-card {
	padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	box-shadow: var(--px-sh);
}

.px-aside-card + .px-aside-card {
	margin-top: 16px;
}

.px-aside-card h3 {
	font-size: var(--px-t-h4);
	margin-bottom: 6px;
}

.px-aside-note {
	font-size: var(--px-t-meta);
	color: var(--px-faint);
	margin-bottom: 18px;
}

@media (max-width: 61.99rem) {
	.px-aside {
		position: static;
	}
}

/* Highlights: the legacy sentence-length feature fields. */
.px-hl {
	display: grid;
	gap: 12px;
	margin-top: clamp(2rem, 1.4rem + 2vw, 3rem);
	padding-top: clamp(2rem, 1.4rem + 2vw, 3rem);
	border-top: 1px solid var(--px-line);
	list-style: none;
	padding-inline-start: 0;
}

@media (min-width: 40rem) {
	.px-hl {
		grid-template-columns: 1fr 1fr;
		gap: 12px 32px;
	}
}

.px-hl li {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	font-size: 0.9375rem;
	color: var(--px-ink);
	line-height: 1.55;
}

.px-hl .px-i {
	flex: none;
	margin-top: 2px;
	color: var(--px-green);
}

/* =========================================================================
   9. GALLERY
   ====================================================================== */

.px-gallery {
	overflow: hidden;
}

/* Full-bleed rail. The first frame lines up with the shell's inline padding so
   the rail reads as part of the page, then runs off the edge — the cue that
   there is more to the right without an arrow saying so. */
.px-rail {
	display: flex;
	gap: 14px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	scrollbar-width: none;
	padding-inline: max(var(--px-pad), calc((100vw - var(--px-shell)) / 2 + var(--px-pad)));
	padding-block: 4px;
	-webkit-overflow-scrolling: touch;
}

.px-rail::-webkit-scrollbar {
	display: none;
}

.px-shot {
	position: relative;
	flex: none;
	width: min(74vw, 620px);
	aspect-ratio: 4 / 3;
	margin: 0;
	border: 0;
	padding: 0;
	overflow: hidden;
	border-radius: var(--px-r-2);
	background: var(--px-mist);
	scroll-snap-align: start;
	cursor: zoom-in;
}

/* The lead frame is wider. An even rail of identical rectangles reads as a
   contact sheet; one dominant frame reads as a photograph. */
.px-shot:first-child {
	width: min(92vw, 880px);
	aspect-ratio: 16 / 10;
}

.px-shot img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.7s var(--px-ease);
}

.px-shot:hover img {
	transform: scale(1.04);
}

.px-shot-tag {
	position: absolute;
	inset-inline-start: 12px;
	top: 12px;
	padding: 5px 11px;
	border-radius: 999px;
	background: rgba(10, 16, 19, 0.6);
	backdrop-filter: blur(8px);
	color: #fff;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.px-shot-zoom {
	position: absolute;
	inset-inline-end: 12px;
	bottom: 12px;
	width: 38px;
	height: 38px;
	display: grid;
	place-items: center;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.92);
	color: var(--px-ink);
	opacity: 0;
	transform: translateY(6px);
	transition: opacity 0.25s ease, transform 0.25s var(--px-ease);
}

.px-shot:hover .px-shot-zoom,
.px-shot:focus-visible .px-shot-zoom {
	opacity: 1;
	transform: none;
}

.px-rail-foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin-top: 22px;
}

.px-rail-nav {
	display: flex;
	gap: 8px;
}

.px-round {
	width: 44px;
	height: 44px;
	display: grid;
	place-items: center;
	border: 1px solid var(--px-line-2);
	border-radius: 50%;
	background: var(--px-paper);
	color: var(--px-ink);
	cursor: pointer;
	transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease;
}

.px-round:hover:not([disabled]) {
	background: var(--px-ink);
	border-color: var(--px-ink);
	color: #fff;
}

.px-round[disabled] {
	opacity: 0.34;
	cursor: default;
}

.px-round--prev .px-i {
	transform: rotate(180deg);
}

[dir="rtl"] .px-round--prev .px-i {
	transform: none;
}

[dir="rtl"] .px-round--next .px-i {
	transform: rotate(180deg);
}

/* Lightbox. Custom rather than Fancybox: Fancybox is loaded inconsistently
   across this theme and the old gallery silently fell back to no lightbox at
   all when it was missing. 60 lines of JS has no such failure mode. */
.px-lb {
	position: fixed;
	inset: 0;
	z-index: var(--px-z-over);
	display: none;
	background: rgba(4, 8, 10, 0.96);
	backdrop-filter: blur(4px);
}

.px-lb.is-open {
	display: grid;
	grid-template-rows: auto 1fr auto;
	animation: px-fade 0.25s ease both;
}

.px-lb-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 16px var(--px-pad);
	color: rgba(255, 255, 255, 0.75);
	font-size: var(--px-t-meta);
	font-variant-numeric: tabular-nums;
}

.px-lb-stage {
	position: relative;
	display: grid;
	place-items: center;
	padding: 0 clamp(8px, 3vw, 64px);
	min-height: 0;
}

.px-lb-stage img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
	border-radius: var(--px-r);
}

.px-lb-thumbs {
	display: flex;
	gap: 8px;
	overflow-x: auto;
	scrollbar-width: none;
	padding: 16px var(--px-pad) max(16px, env(safe-area-inset-bottom));
}

.px-lb-thumbs::-webkit-scrollbar {
	display: none;
}

.px-lb-thumb {
	flex: none;
	width: 74px;
	aspect-ratio: 4 / 3;
	padding: 0;
	border: 1px solid transparent;
	border-radius: 6px;
	overflow: hidden;
	background: none;
	cursor: pointer;
	opacity: 0.44;
	transition: opacity 0.2s ease, border-color 0.2s ease;
}

.px-lb-thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.px-lb-thumb[aria-current="true"] {
	opacity: 1;
	border-color: var(--px-green);
}

.px-lb-x,
.px-lb-arrow {
	width: 46px;
	height: 46px;
	display: grid;
	place-items: center;
	border: 1px solid rgba(255, 255, 255, 0.22);
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.06);
	color: #fff;
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.px-lb-x:hover,
.px-lb-arrow:hover {
	background: rgba(255, 255, 255, 0.16);
}

.px-lb-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
}

.px-lb-arrow--prev {
	inset-inline-start: 6px;
}

.px-lb-arrow--next {
	inset-inline-end: 6px;
}

.px-lb-arrow--prev .px-i {
	transform: rotate(180deg);
}

[dir="rtl"] .px-lb-arrow--prev .px-i {
	transform: none;
}

[dir="rtl"] .px-lb-arrow--next .px-i {
	transform: rotate(180deg);
}

/* =========================================================================
   9b. KEY POINTS  —  the editorial band
   ====================================================================== */

.px-keys {
	padding-bottom: clamp(2rem, 1rem + 4vw, 4rem);
	overflow: hidden;
}

.px-key {
	position: relative;
	padding-block: clamp(1.5rem, 0.8rem + 3vw, 3.5rem);
}

.px-key-grid {
	display: grid;
	gap: clamp(1.5rem, 0.8rem + 3vw, 4rem);
	align-items: center;
}

@media (min-width: 48rem) {
	.px-key-grid {
		grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
	}

	/* The flip is a column-order swap, not a direction-flip, so it behaves the
	   same in Arabic — the alternation should read the same either way. */
	.px-key--flip .px-key-media {
		order: 2;
	}
}

.px-key-media {
	margin: 0;
	/* The frame is a separate element so the mask and the image can move
	   against each other: the frame reveals, the image inside counter-moves.
	   One element cannot do both. */
	overflow: hidden;
	border-radius: var(--px-r-2);
}

.px-key-frame {
	display: block;
	overflow: hidden;
	border-radius: var(--px-r-2);
	background: var(--px-mist);
	aspect-ratio: 5 / 4;
}

.px-key-frame img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transform: scale(1.14);
}

@media (min-width: 62rem) {
	.px-key-frame {
		aspect-ratio: 4 / 3;
	}
}

.px-key-copy {
	position: relative;
	padding-inline-start: clamp(0px, 2vw, 40px);
}

.px-key-n {
	margin: 0 0 18px;
	font-family: var(--px-display);
	font-size: clamp(2.5rem, 1.4rem + 4.4vw, 5rem);
	font-weight: 800;
	line-height: 0.8;
	letter-spacing: var(--px-track-display);
	/* Outlined rather than filled: at this size a solid numeral competes with
	   the claim next to it, which is the thing that should be read. */
	color: transparent;
	-webkit-text-stroke: 1.5px var(--px-line-2);
}

.px-key-t {
	font-size: var(--px-t-h2);
	letter-spacing: var(--px-track-h2);
	line-height: 1.1;
	max-width: 20ch;
}

[dir="rtl"] .px-key-t {
	letter-spacing: 0;
	line-height: 1.4;
}

.px-key-rule {
	width: 0;
	height: 2px;
	margin: 26px 0 0;
	background: var(--px-green);
}

.px-key-cta {
	margin: clamp(1.5rem, 1rem + 2vw, 2.5rem) 0 0;
	text-align: center;
}

/* Scroll-driven: the frame wipes open, the image inside settles back to 1,
   the numeral and the rule follow. All four are one timeline per band. */
@supports (animation-timeline: view()) {

	.px-key-frame {
		clip-path: inset(0 0 0 0);
		animation: px-wipe 1s linear both;
		animation-timeline: view();
		animation-range: entry 8% entry 62%;
	}

	.px-key-frame img {
		animation: px-settle 1s linear both;
		animation-timeline: view();
		animation-range: entry 8% cover 70%;
	}

	.px-key-rule {
		animation: px-draw 1s linear both;
		animation-timeline: view();
		animation-range: entry 22% entry 76%;
	}

	.px-eyebrow::before {
		animation: px-draw-x 1s linear both;
		animation-timeline: view();
		animation-range: entry 10% entry 55%;
	}
}

@keyframes px-wipe {
	from {
		clip-path: inset(0 0 100% 0);
	}
	to {
		clip-path: inset(0 0 0 0);
	}
}

@keyframes px-settle {
	from {
		transform: scale(1.14);
	}
	to {
		transform: scale(1);
	}
}

@keyframes px-draw {
	from {
		width: 0;
	}
	to {
		width: 78px;
	}
}

@keyframes px-draw-x {
	from {
		transform: scaleX(0);
	}
	to {
		transform: scaleX(1);
	}
}

html.px-io .px-key-rule {
	transition: width 0.8s var(--px-ease) 0.2s;
}

html.px-io .px-key.is-in .px-key-rule {
	width: 78px;
}

html.px-io .px-key-frame img {
	transition: transform 1.4s var(--px-ease);
}

html.px-io .px-key.is-in .px-key-frame img {
	transform: scale(1);
}

/* =========================================================================
   10. RESIDENCES
   ====================================================================== */

.px-unit-body {
	display: grid;
	gap: clamp(1.75rem, 1rem + 3vw, 3.5rem);
	margin-top: clamp(1.75rem, 1.2rem + 2vw, 2.75rem);
	align-items: start;
}

@media (min-width: 62rem) {
	.px-unit-body {
		grid-template-columns: minmax(0, 1.5fr) minmax(280px, 1fr);
	}
}

.px-plan {
	position: relative;
	margin: 0;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-mist);
	overflow: hidden;
	/* Floor plans are line art on white; a grid behind the mount makes the
	   drawing read as a drawing rather than as a photo that failed to load. */
	background-image: linear-gradient(var(--px-line) 1px, transparent 1px),
		linear-gradient(90deg, var(--px-line) 1px, transparent 1px);
	background-size: 26px 26px;
	background-position: center;
}

.px-plan img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: contain;
	padding: clamp(14px, 2vw, 30px);
	cursor: zoom-in;
}

.px-plan-none {
	display: grid;
	place-items: center;
	gap: 8px;
	aspect-ratio: 4 / 3;
	padding: 24px;
	text-align: center;
	color: var(--px-faint);
	font-size: 0.9375rem;
}

.px-plan-zoom {
	position: absolute;
	inset-inline-end: 14px;
	top: 14px;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 38px;
	padding: 0 14px;
	border: 1px solid var(--px-line);
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.94);
	color: var(--px-ink);
	font-size: var(--px-t-meta);
	font-weight: 600;
	cursor: zoom-in;
}

.px-unit-card {
	padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	box-shadow: var(--px-sh);
}

.px-unit-card h3 {
	font-size: var(--px-t-h3);
	margin-bottom: 4px;
}

.px-unit-kind {
	font-size: var(--px-t-meta);
	color: var(--px-faint);
	margin-bottom: 20px;
}

.px-unit-specs {
	margin: 0 0 22px;
	border-top: 1px solid var(--px-line);
}

.px-unit-specs div {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	padding: 14px 0;
	border-bottom: 1px solid var(--px-line);
}

.px-unit-specs dt {
	display: inline-flex;
	align-items: center;
	gap: 9px;
	font-size: var(--px-t-meta);
	color: var(--px-faint);
}

.px-unit-specs dt .px-i {
	color: var(--px-line-2);
}

.px-unit-specs dd {
	margin: 0;
	font-size: 1.0625rem;
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--px-ink);
	font-variant-numeric: tabular-nums;
	text-align: end;
}

.px-unit-specs dd.is-key {
	color: var(--px-green-deep);
	font-size: 1.25rem;
}

/* ---- The layout comparison ---------------------------------------------
   Rows that expand, not a switcher. Every figure stays readable without any
   interaction, because the question this section answers is comparative and a
   control that hides five options to show one makes the buyer memorise. The
   expansion adds only what a row cannot hold: the drawing and the CTA. */

.px-layouts {
	margin-top: clamp(1.5rem, 1rem + 2vw, 2.5rem);
	border-top: 1px solid var(--px-line);
}

/* Column labels. Hidden below the table breakpoint, where each cell carries its
   own label from `data-k` instead. */
.px-layouts-head {
	display: none;
	padding: 0 clamp(1rem, 0.6rem + 1vw, 1.5rem) 12px;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-faint);
}

.px-layout {
	border-bottom: 1px solid var(--px-line);
}

.px-layout-h {
	margin: 0;
	font-size: inherit;
	font-weight: inherit;
}

.px-layout-btn {
	display: grid;
	gap: 6px 16px;
	width: 100%;
	padding: clamp(1rem, 0.7rem + 1vw, 1.35rem) clamp(1rem, 0.6rem + 1vw, 1.5rem);
	border: 0;
	background: none;
	text-align: start;
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.px-layout-btn:hover {
	background: var(--px-mist);
}

.px-layout-name {
	display: flex;
	flex-direction: column;
	gap: 2px;
	font-family: var(--px-display);
	font-size: 1.0625rem;
	font-weight: 700;
	letter-spacing: var(--px-track-h3);
	color: var(--px-ink);
}

.px-layout-name em {
	font-family: var(--px-text);
	font-size: var(--px-t-meta);
	font-style: normal;
	font-weight: 500;
	letter-spacing: 0;
	color: var(--px-faint);
}

/* Availability, on the row. A sold-out layout has to say so before someone
   reads its price and calls about it. */
.px-layout-flag {
	display: inline-block;
	margin-inline-start: 6px;
	padding: 1px 7px;
	border-radius: 999px;
	font-size: 0.625rem;
	font-weight: 800;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	vertical-align: 1px;
}

.px-layout-flag--soldout {
	background: #fdeaea;
	color: #a32020;
}

.px-layout-flag--limited {
	background: #fff4e0;
	color: #8a5a00;
}

.px-layout-cell {
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--px-ink);
	font-variant-numeric: tabular-nums;
}

.px-layout-cell--price {
	color: var(--px-green-deep);
	font-weight: 700;
}

/* On a phone every cell prints its own label, so the row still reads as data
   rather than as four orphan numbers. */
.px-layout-cell::before {
	content: attr(data-k) " ";
	display: block;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-faint);
	margin-bottom: 2px;
}

.px-layout-toggle {
	position: relative;
	justify-self: end;
	align-self: center;
	width: 30px;
	height: 30px;
	border-radius: 50%;
	border: 1px solid var(--px-line-2);
	flex: none;
	transition: background-color 0.2s ease, border-color 0.2s ease, transform 0.3s var(--px-ease);
}

/* A drawn plus that becomes a minus — two rules, no icon font, and it animates
   as one object. */
.px-layout-toggle::before,
.px-layout-toggle::after {
	content: "";
	position: absolute;
	inset-inline-start: 50%;
	top: 50%;
	width: 11px;
	height: 1.5px;
	background: currentColor;
	transform: translate(-50%, -50%);
	transition: opacity 0.25s ease, transform 0.3s var(--px-ease);
}

[dir="rtl"] .px-layout-toggle::before,
[dir="rtl"] .px-layout-toggle::after {
	transform: translate(50%, -50%);
}

.px-layout-toggle::after {
	transform: translate(-50%, -50%) rotate(90deg);
}

[dir="rtl"] .px-layout-toggle::after {
	transform: translate(50%, -50%) rotate(90deg);
}

.px-layout-btn[aria-expanded="true"] .px-layout-toggle {
	background: var(--px-ink);
	border-color: var(--px-ink);
	color: #fff;
}

.px-layout-btn[aria-expanded="true"] .px-layout-toggle::after {
	opacity: 0;
	transform: translate(-50%, -50%) rotate(0deg);
}

/* grid-rows, so the drawing's height never has to be known in advance. */
.px-layout-panel {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.4s var(--px-ease);
}

.px-layout-panel > .px-layout-panel-inner {
	overflow: hidden;
	min-height: 0;
}

/*
 * Keyed off a class on the row, not `button[aria-expanded] + panel`. The button
 * is wrapped in an <h3> for the document outline, so it is not the panel's
 * sibling and the adjacent combinator matched nothing — every panel stayed
 * collapsed however the state changed. `:has()` would also work but is not
 * universal yet, and this has to be right everywhere.
 */
.px-layout.is-open .px-layout-panel {
	grid-template-rows: 1fr;
}

/*
 * The bottom padding is animated, not static. `overflow: hidden` clips the
 * element's content but not its own padding, so a collapsed row still stood
 * 36px tall — a visible gap under every closed layout. Horizontal padding is
 * safe to leave; only the vertical axis is being collapsed.
 */
.px-layout-panel-inner {
	display: grid;
	gap: clamp(1.25rem, 0.8rem + 2vw, 2.5rem);
	padding: 0 clamp(1rem, 0.6rem + 1vw, 1.5rem);
	transition: padding-bottom 0.4s var(--px-ease);
}

.px-layout.is-open .px-layout-panel-inner {
	padding-bottom: clamp(1.5rem, 1rem + 2vw, 2.25rem);
}

.px-layout-detail h4 {
	font-size: var(--px-t-h3);
	margin-bottom: 16px;
}

.px-layout-cta {
	width: 100%;
	margin-top: 18px;
}

@media (min-width: 52rem) {

	.px-layouts-head,
	.px-layout-btn {
		display: grid;
		align-items: center;
		grid-template-columns: minmax(0, 2fr) 0.7fr 1.1fr 1.2fr 44px;
	}

	.px-layout--psf .px-layout-btn,
	.px-layouts-head:has(~ .px-layout--psf) {
		grid-template-columns: minmax(0, 2fr) 0.7fr 1.1fr 1.2fr 1fr 44px;
	}

	/* The labels live in the header row at this width. */
	.px-layout-cell::before {
		display: none;
	}

	.px-layout-panel-inner {
		grid-template-columns: minmax(0, 1.35fr) minmax(280px, 1fr);
		align-items: start;
	}

	.px-layout-cta {
		width: auto;
	}
}

/* `:has()` is not universal yet; without it the header row keeps five columns
   while the data rows have six, which misaligns every heading. Falling back to
   the phone layout for the header — labels on the cells — is wrong-looking but
   never *mis*-labelled, and that is the right way round. */
@supports not selector(:has(*)) {

	.px-layouts-head {
		display: none;
	}

	.px-layout-cell::before {
		display: block;
	}
}

/* Plan viewer. Pan by drag, zoom by button — a pinch-zoom surface inside a
   scrolling page fights the page, so the scale is explicit. */
.px-viewer {
	position: fixed;
	inset: 0;
	z-index: var(--px-z-over);
	display: none;
	grid-template-rows: auto 1fr;
	background: rgba(248, 250, 249, 0.98);
	backdrop-filter: blur(4px);
}

.px-viewer.is-open {
	display: grid;
	animation: px-fade 0.22s ease both;
}

.px-viewer-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 14px var(--px-pad);
	border-bottom: 1px solid var(--px-line);
	background: var(--px-paper);
}

.px-viewer-title {
	font-size: var(--px-t-h4);
	font-weight: 700;
	color: var(--px-ink);
}

.px-viewer-tools {
	display: flex;
	align-items: center;
	gap: 8px;
}

.px-viewer-stage {
	overflow: hidden;
	display: grid;
	place-items: center;
	cursor: grab;
	touch-action: none;
}

.px-viewer-stage.is-grabbing {
	cursor: grabbing;
}

.px-viewer-stage img {
	max-width: 100%;
	max-height: 100%;
	transform-origin: center;
	transition: transform 0.25s var(--px-ease);
	user-select: none;
	-webkit-user-drag: none;
}

.px-viewer-stage.is-grabbing img {
	transition: none;
}

/* =========================================================================
   11. PAYMENT
   ====================================================================== */

.px-pay {
	display: grid;
	gap: clamp(2rem, 1.2rem + 4vw, 4.5rem);
	align-items: start;
}

@media (min-width: 62rem) {
	.px-pay {
		grid-template-columns: minmax(0, 1fr) minmax(340px, 0.95fr);
	}
}

.px-plan-badge {
	display: inline-flex;
	align-items: baseline;
	gap: 2px;
	margin-bottom: 22px;
	font-size: clamp(2.25rem, 1.6rem + 2.6vw, 3.5rem);
	font-weight: 700;
	letter-spacing: -0.04em;
	line-height: 1;
	color: #fff;
	font-variant-numeric: tabular-nums;
}

.px-plan-badge span {
	color: var(--px-green-lift);
}

/* Stage timeline. A vertical rule with nodes, not a row of cards: a payment
   plan is a sequence in time and the layout should say so. */
.px-stages {
	position: relative;
	margin: 0;
	padding-inline-start: 30px;
	list-style: none;
}

.px-stages::before {
	content: "";
	position: absolute;
	inset-inline-start: 5px;
	top: 10px;
	bottom: 10px;
	width: 1px;
	background: var(--px-line-night);
}

.px-stage {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 6px 20px;
	padding-block: 16px;
	border-bottom: 1px solid var(--px-line-night);
}

.px-stage:last-child {
	border-bottom: 0;
}

.px-stage::before {
	content: "";
	position: absolute;
	inset-inline-start: -30px;
	top: 24px;
	width: 11px;
	height: 11px;
	border: 2px solid var(--px-green-lift);
	border-radius: 50%;
	background: var(--px-night);
}

.px-stage-k {
	font-size: 1rem;
	font-weight: 600;
	color: #fff;
}

.px-stage-when {
	display: block;
	font-size: var(--px-t-meta);
	font-weight: 400;
	color: rgba(255, 255, 255, 0.52);
	margin-top: 3px;
}

.px-stage-v {
	display: flex;
	align-items: baseline;
	gap: 14px;
	margin-inline-start: auto;
	text-align: end;
}

.px-stage-pc {
	font-size: 1.5rem;
	font-weight: 700;
	letter-spacing: -0.03em;
	color: var(--px-green-lift);
	font-variant-numeric: tabular-nums;
}

.px-stage-aed {
	min-width: 8.5ch;
	font-size: 0.9375rem;
	color: rgba(255, 255, 255, 0.72);
	font-variant-numeric: tabular-nums;
}

/* ---- The dated instalment schedule ------------------------------------
   Behind a <details> because it is up to eleven rows on a long plan, and the
   three headline stages above are what a buyer compares between projects.
   Native disclosure rather than a scripted one: it works before JS loads, it is
   keyboard operable for free, and it prints open. */

.px-sched {
	margin-top: clamp(1.5rem, 1rem + 2vw, 2.25rem);
}

.px-sched-note {
	margin: 0 0 14px;
	font-size: 0.9375rem;
	line-height: 1.65;
	color: rgba(255, 255, 255, 0.68);
}

.px-sched-box {
	border: 1px solid var(--px-line-night);
	border-radius: var(--px-r-2);
	background: rgba(255, 255, 255, 0.03);
	overflow: hidden;
}

.px-sched-box summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 14px;
	padding: 15px 18px;
	color: #fff;
	font-size: 0.9375rem;
	font-weight: 700;
	cursor: pointer;
	list-style: none;
	transition: background-color 0.2s ease;
}

/* Safari draws its own triangle unless this is removed. */
.px-sched-box summary::-webkit-details-marker {
	display: none;
}

.px-sched-box summary:hover {
	background: rgba(255, 255, 255, 0.05);
}

.px-sched-box summary .px-i {
	flex: none;
	color: var(--px-green-lift);
	transition: transform 0.3s var(--px-ease);
}

.px-sched-box[open] summary .px-i {
	transform: rotate(180deg);
}

.px-sched-list {
	margin: 0;
	padding: 4px 18px 16px;
	list-style: none;
	counter-reset: none;
}

.px-sched-list li {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 11px 0;
	border-top: 1px solid var(--px-line-night);
	font-size: 0.9375rem;
}

/* The instalment number, so a buyer can say "the fourth payment". */
.px-sched-n {
	flex: none;
	display: inline-grid;
	place-items: center;
	width: 22px;
	height: 22px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.08);
	color: rgba(255, 255, 255, 0.6);
	font-size: var(--px-t-micro);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.px-sched-when {
	color: #fff;
}

/* Leader rule, same device as the travel times — carries the eye from a date
   across to its figure. */
.px-sched-dot {
	flex: 1;
	min-width: 16px;
	height: 1px;
	background: repeating-linear-gradient(to right, var(--px-line-night) 0 2px, transparent 2px 5px);
	transform: translateY(-3px);
}

.px-sched-pc {
	flex: none;
	color: var(--px-green-lift);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.px-sched-aed {
	flex: none;
	min-width: 8.5ch;
	text-align: end;
	color: rgba(255, 255, 255, 0.68);
	font-variant-numeric: tabular-nums;
}

@media (max-width: 30rem) {

	/* The leader and the number go; on a 375px row the date and the two figures
	   are all that fit without wrapping. */
	.px-sched-n,
	.px-sched-dot {
		display: none;
	}

	.px-sched-list li {
		flex-wrap: wrap;
	}

	.px-sched-when {
		flex: 1 1 100%;
	}
}

/* Calculator. The commercial reason this section exists: a buyer who has seen
   their own first instalment in dirhams is a qualified enquiry, and the whole
   thing is derivable from data already on the page. */
.px-calc {
	padding: clamp(1.25rem, 1rem + 1.4vw, 2rem);
	border: 1px solid var(--px-line-night);
	border-radius: var(--px-r-2);
	background: var(--px-night-2);
}

.px-calc h3 {
	font-size: var(--px-t-h4);
	margin-bottom: 6px;
}

.px-calc-note {
	font-size: var(--px-t-meta);
	color: rgba(255, 255, 255, 0.56);
	margin-bottom: 20px;
}

.px-field {
	display: block;
	margin-bottom: 16px;
}

.px-field > span {
	display: block;
	margin-bottom: 8px;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.56);
}

.px-calc select,
.px-calc input {
	width: 100%;
	min-height: 48px;
	padding: 0 14px;
	border: 1px solid var(--px-line-night);
	border-radius: var(--px-r);
	background: rgba(255, 255, 255, 0.05);
	color: #fff;
	font-size: 1rem;
	font-variant-numeric: tabular-nums;
	appearance: none;
}

.px-calc select {
	/* Native arrow is invisible on a dark control in most engines. */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9.5l6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 14px center;
	padding-inline-end: 40px;
}

[dir="rtl"] .px-calc select {
	background-position: left 14px center;
	padding-inline-end: 14px;
	padding-inline-start: 40px;
}

.px-calc select:focus,
.px-calc input:focus {
	border-color: var(--px-green-lift);
	outline: none;
}

.px-calc-total {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	margin-top: 20px;
	padding-top: 18px;
	border-top: 1px solid var(--px-line-night);
}

.px-calc-total dt {
	font-size: var(--px-t-meta);
	color: rgba(255, 255, 255, 0.6);
}

.px-calc-total dd {
	margin: 0;
	font-size: var(--px-t-figure);
	font-weight: 700;
	letter-spacing: -0.03em;
	color: #fff;
	font-variant-numeric: tabular-nums;
}

.px-disclaim {
	margin-top: 16px;
	font-size: var(--px-t-micro);
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.44);
}

/* Editor-only warning when the authored percentages do not sum to 100. */
.px-note-admin--light {
	max-width: 900px;
	margin-inline: auto;
	border-color: #d9c48a;
	background: #fdf7e6;
	color: #7a5c12;
}

.px-note-admin {
	margin-top: 18px;
	padding: 12px 16px;
	border: 1px dashed rgba(255, 200, 80, 0.5);
	border-radius: var(--px-r);
	background: rgba(255, 200, 80, 0.08);
	color: #ffd77a;
	font-size: var(--px-t-meta);
}

/* =========================================================================
   12. AMENITIES

   No 1px-gap-over-background grid here. That trick draws a whole grid's rules
   in one declaration and looks excellent — right up to a partial last row,
   where the empty cells show through as tinted rectangles of nothing. With
   four items in a five-column track that is one visible blank per group, and
   every group had at least one.

   Independent cards with real gaps instead: a short row just ends.
   ====================================================================== */

.px-amen-total {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 2px;
	margin: 0;
	text-align: end;
}

.px-amen-total span {
	font-family: var(--px-display);
	font-size: clamp(2.25rem, 1.6rem + 2.4vw, 3.25rem);
	font-weight: 800;
	letter-spacing: var(--px-track-h2);
	line-height: 1;
	color: var(--px-green-deep);
	font-variant-numeric: tabular-nums;
}

.px-amen-total em {
	font-style: normal;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-faint);
}

.px-amen-groups {
	display: grid;
	gap: clamp(2rem, 1.4rem + 2.4vw, 3.25rem);
}

.px-amen-h {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: 16px;
	font-size: var(--px-t-h4);
}

.px-amen-h > span {
	flex: none;
}

/* The count as a pill, so it reads as metadata rather than as part of the
   heading it sits next to. */
.px-amen-h em {
	flex: none;
	order: 3;
	display: inline-grid;
	place-items: center;
	min-width: 24px;
	height: 22px;
	padding: 0 7px;
	border-radius: 999px;
	background: var(--px-tint);
	color: var(--px-green-deep);
	font-size: var(--px-t-micro);
	font-style: normal;
	font-weight: 800;
	letter-spacing: 0;
	font-variant-numeric: tabular-nums;
}

/* The rule fills whatever is left, between the label and the count. */
.px-amen-h::after {
	content: "";
	order: 2;
	flex: 1;
	height: 1px;
	background: var(--px-line);
}

.px-amen {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.px-amen li {
	display: flex;
	align-items: center;
	gap: 13px;
	padding: 14px 16px;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	font-size: 0.9375rem;
	color: var(--px-ink);
	line-height: 1.4;
	transition: border-color 0.22s ease, box-shadow 0.28s var(--px-ease), transform 0.28s var(--px-ease);
}

.px-amen li:hover {
	border-color: var(--px-line-2);
	box-shadow: var(--px-sh);
	transform: translateY(-2px);
}

/* The glyph tile. Tinted square rather than a bare icon: at 22px on a white
   card the drawings float, and the tile gives each one the same footprint so a
   row of six reads as a row of six rather than as six different sizes. */
.px-amen-ico {
	flex: none;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	border-radius: 10px;
	background: var(--px-tint);
	color: var(--px-green-deep);
	transition: background-color 0.22s ease, color 0.22s ease;
}

.px-amen li:hover .px-amen-ico {
	background: var(--px-green);
	color: #fff;
}

.px-amen-label {
	min-width: 0;
}

/* The overflow cell: same footprint as an amenity, so the grid stays even, but
   clearly a control rather than a facility. */
.px-amen-more-cell {
	padding: 0;
	border: 1px dashed var(--px-line-2);
	background: transparent;
}

.px-amen-more-cell:hover {
	border-color: var(--px-green);
	box-shadow: none;
	transform: none;
}

.px-amen-more-cell button {
	width: 100%;
	height: 100%;
	min-height: 72px;
	padding: 14px 16px;
	border: 0;
	background: none;
	color: var(--px-green-deep);
	font: inherit;
	font-weight: 700;
	cursor: pointer;
	font-variant-numeric: tabular-nums;
}

.px-amen-more {
	margin-top: clamp(1.75rem, 1.2rem + 2vw, 2.5rem);
	text-align: center;
}

/* Inside the dialog the cards lose their hover lift — a list you are reading,
   not a grid you are browsing — and tighten up, because the dialog is narrower
   than the band and a 15rem minimum would drop it to one column. */
.px-modal .px-amen {
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr));
	gap: 8px;
}

.px-modal .px-amen li:hover {
	transform: none;
	box-shadow: none;
}

.px-modal .px-amen-ico {
	width: 36px;
	height: 36px;
	border-radius: 8px;
}

.px-modal .px-amen-group + .px-amen-group {
	margin-top: 26px;
}

@media (max-width: 47.99rem) {

	/* The total moves under the heading rather than beside it; at this width the
	   two-column head row squeezes the h2 to four words a line. */
	.px-amen-total {
		align-items: flex-start;
		text-align: start;
	}

	.px-amen-total span {
		font-size: 2.25rem;
	}

	/* One column, and a smaller tile — two cards across a 375px screen leaves
	   about nine characters for the label, which truncates most of them. */
	.px-amen {
		grid-template-columns: 1fr;
		gap: 8px;
	}

	.px-amen li {
		padding: 12px 14px;
	}

	.px-amen-ico {
		width: 36px;
		height: 36px;
		border-radius: 9px;
	}
}

/* =========================================================================
   13. ADVISOR  —  the mid-page conversion band
   ====================================================================== */

.px-advisor {
	display: grid;
	gap: clamp(2rem, 1.2rem + 4vw, 4rem);
	align-items: center;
}

@media (min-width: 62rem) {
	.px-advisor {
		grid-template-columns: minmax(0, 1fr) minmax(360px, 0.9fr);
	}
}

.px-trust {
	display: grid;
	gap: 14px;
	margin: 28px 0 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 30rem) {
	.px-trust {
		grid-template-columns: 1fr 1fr;
	}
}

.px-trust li {
	display: flex;
	align-items: flex-start;
	gap: 11px;
	font-size: 0.9375rem;
	color: rgba(255, 255, 255, 0.82);
}

.px-trust .px-i {
	flex: none;
	margin-top: 2px;
	color: var(--px-green-lift);
}

/* Form. One column, visible labels, 48px controls. Placeholder-only labelling
   was the old pattern here and it fails the moment a field has content — the
   user can no longer see what they answered. */
.px-form {
	padding: clamp(1.5rem, 1rem + 2vw, 2.25rem);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	box-shadow: var(--px-sh);
}

.px-band--night .px-form {
	border-color: var(--px-line-night);
	background: var(--px-night-2);
}

.px-form h3 {
	font-size: var(--px-t-h3);
	margin-bottom: 6px;
}

.px-form-note {
	font-size: var(--px-t-meta);
	color: var(--px-faint);
	margin-bottom: 22px;
}

.px-band--night .px-form-note {
	color: rgba(255, 255, 255, 0.58);
}

.px-form label {
	display: block;
	margin-bottom: 16px;
}

/*
 * The field caption only. `:not(.px-phone)` matters: the phone row is also a
 * direct span child of the label, and without the exclusion it inherited
 * `text-transform: uppercase` and the micro size into the country list and the
 * number field — country names rendered as UNITED ARAB EMIR… inside the picker.
 */
.px-form label > span:not(.px-phone) {
	display: block;
	margin-bottom: 7px;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--px-faint);
}

.px-band--night .px-form label > span {
	color: rgba(255, 255, 255, 0.56);
}

/* A hairline in --px-line is right for rules between rows of data; on an empty
   input it is too faint to read as a field you can type into. Controls get the
   darker line. */
.px-form input,
.px-form select,
.px-form textarea {
	width: 100%;
	min-height: 48px;
	padding: 12px 14px;
	border: 1px solid var(--px-line-2);
	border-radius: var(--px-r);
	background: var(--px-paper);
	color: var(--px-ink);
	font-size: 1rem;
	font-family: inherit;
	line-height: 1.5;
}

.px-band--night .px-form input,
.px-band--night .px-form select,
.px-band--night .px-form textarea {
	border-color: var(--px-line-night);
	background: rgba(255, 255, 255, 0.05);
	color: #fff;
}

.px-form textarea {
	min-height: 96px;
	resize: vertical;
}

.px-form input:focus,
.px-form select:focus,
.px-form textarea:focus {
	border-color: var(--px-green);
	outline: none;
	box-shadow: 0 0 0 3px rgba(0, 166, 81, 0.14);
}

.px-form input[aria-invalid="true"] {
	border-color: #d64545;
}

.px-form .px-err {
	display: block;
	margin-top: 6px;
	font-size: var(--px-t-meta);
	color: #d64545;
}

.px-band--night .px-form .px-err {
	color: #ff9c9c;
}

/* Phone: a country picker fused to the number field. */
.px-phone {
	display: flex;
	gap: 8px;
}

/* ---- Country combobox -------------------------------------------------
   The native <select> stays in the DOM and stays the submitting control; it is
   only taken out of view and out of the tab order once JS has built the
   combobox in front of it. That is why it is `position:absolute; opacity:0`
   rather than `display:none` — a hidden select cannot be focused by the
   browser's own validation when the form fails to submit. */

.px-cc {
	position: relative;
	flex: none;
	width: 8.25rem;
}

.px-cc-native {
	position: absolute;
	inset: 0;
	width: 100%;
	opacity: 0;
	pointer-events: none;
}

.px-cc-btn {
	display: flex;
	align-items: center;
	gap: 8px;
	width: 100%;
	min-height: 48px;
	padding: 0 10px 0 12px;
	border: 1px solid var(--px-line-2);
	border-radius: var(--px-r);
	background: var(--px-paper);
	color: var(--px-ink);
	font: inherit;
	font-variant-numeric: tabular-nums;
	cursor: pointer;
	transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

.px-cc-btn:hover {
	border-color: var(--px-ink);
}

.px-cc-btn[aria-expanded="true"] {
	border-color: var(--px-green);
	box-shadow: 0 0 0 3px rgba(0, 166, 81, 0.14);
}

.px-band--night .px-cc-btn {
	border-color: var(--px-line-night);
	background: rgba(255, 255, 255, 0.05);
	color: #fff;
}

.px-cc-dial {
	font-weight: 600;
	white-space: nowrap;
}

.px-cc-caret {
	margin-inline-start: auto;
	width: 0;
	height: 0;
	border: 4px solid transparent;
	border-top-color: currentColor;
	opacity: 0.55;
	transform: translateY(2px);
}

/* Flags are 20×15 images from a CDN, lazily. Each falls back to this chip on
   error, so a blocked CDN loses the flag and nothing else. */
.px-flagimg {
	flex: none;
	width: 20px;
	height: 15px;
	border-radius: 2px;
	object-fit: cover;
	box-shadow: 0 0 0 1px rgba(13, 20, 24, 0.12);
}

.px-flagchip {
	flex: none;
	display: inline-grid;
	place-items: center;
	min-width: 22px;
	height: 15px;
	padding: 0 3px;
	border-radius: 2px;
	background: var(--px-mist);
	color: var(--px-faint);
	font-size: 9px;
	font-weight: 800;
	letter-spacing: 0.04em;
	box-shadow: inset 0 0 0 1px var(--px-line);
}

/*
 * `fixed`, with its coordinates written by JS from the trigger's rect.
 *
 * Absolute positioning put the popover inside the dialog's scrolling body, and
 * a container with `overflow-y: auto` computes `overflow-x` to `auto` too — so
 * a popover wider than the 8rem trigger was clipped, scrolled with the form,
 * and added a horizontal scrollbar to the dialog. Fixed positioning escapes the
 * clip entirely; the cost is repositioning on scroll and resize, which the
 * script does.
 */
.px-cc-pop {
	position: fixed;
	z-index: calc(var(--px-z-modal) + 10);
	/* Wider than the trigger: country names do not fit in 8rem, and a popover
	   clipped to its button is the classic unusable country picker. */
	width: min(19rem, 78vw);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	box-shadow: 0 18px 40px rgba(13, 20, 24, 0.18);
	overflow: hidden;
	/*
	 * Fade only — deliberately not the shared `px-pop`, which also scales and
	 * translates. A transform changes what getBoundingClientRect() reports, and
	 * the placement logic measures this element the moment it is shown: with
	 * `scale(0.98)` running, the width came back ~6px short and the RTL
	 * right-edge alignment was consistently off. A popover that appears exactly
	 * where it belongs is worth more than 16px of slide.
	 */
	animation: px-fade 0.16s ease both;
}

.px-cc-search {
	padding: 10px;
	border-bottom: 1px solid var(--px-line);
}

.px-cc-search input {
	width: 100%;
	min-height: 40px;
	padding: 8px 12px;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r);
	background: var(--px-mist);
	color: var(--px-ink);
	font: inherit;
}

.px-cc-search input:focus {
	outline: none;
	border-color: var(--px-green);
	background: var(--px-paper);
}

.px-cc-list {
	max-height: 17rem;
	margin: 0;
	padding: 6px;
	list-style: none;
	overflow-y: auto;
	overscroll-behavior: contain;
}

.px-cc-list li {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 9px 10px;
	border-radius: 6px;
	color: var(--px-ink);
	font-size: 0.9375rem;
	cursor: pointer;
}

.px-cc-list li:hover,
.px-cc-list li.is-on {
	background: var(--px-mist);
}

.px-cc-list li[aria-selected="true"] {
	background: var(--px-tint);
	font-weight: 600;
}

.px-cc-name {
	flex: 1;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.px-cc-list .px-cc-dial {
	color: var(--px-faint);
	font-weight: 500;
}

.px-cc-none {
	margin: 0;
	padding: 18px;
	text-align: center;
	color: var(--px-faint);
	font-size: var(--px-t-meta);
}

/* Inside a dark band the popover stays light — it is a menu, not part of the
   band, and a dark menu over a dark form loses its edge entirely. */
.px-band--night .px-cc-pop {
	color: var(--px-ink);
}

.px-phone select {
	flex: none;
	width: 8.5rem;
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23737f89' stroke-width='2' stroke-linecap='round'%3E%3Cpath d='M6 9.5l6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	padding-inline-end: 34px;
}

[dir="rtl"] .px-phone select {
	background-position: left 12px center;
	padding-inline-end: 14px;
	padding-inline-start: 34px;
}

.px-form .px-btn {
	width: 100%;
	margin-top: 6px;
}

.px-consent {
	margin-top: 14px;
	font-size: var(--px-t-micro);
	line-height: 1.6;
	color: var(--px-faint);
}

.px-band--night .px-consent {
	color: rgba(255, 255, 255, 0.46);
}

.px-consent a {
	text-decoration: underline;
}

/* Post-submit state, in place of the form. */
.px-thanks {
	display: grid;
	place-items: center;
	gap: 12px;
	padding: clamp(2rem, 1.4rem + 2vw, 3rem) 1rem;
	text-align: center;
}

.px-thanks-mark {
	display: grid;
	place-items: center;
	width: 58px;
	height: 58px;
	border-radius: 50%;
	background: var(--px-tint);
	color: var(--px-green-deep);
}

.px-band--night .px-thanks-mark {
	background: rgba(22, 195, 104, 0.14);
	color: var(--px-green-lift);
}

/* =========================================================================
   14. LOCATION
   ====================================================================== */

.px-place-grid {
	display: grid;
	gap: clamp(1.75rem, 1rem + 3vw, 3.25rem);
	align-items: start;
}

@media (min-width: 62rem) {
	.px-place-grid {
		/* The map takes the larger share: it is the thing being examined, and
		   the list beside it is reference. */
		grid-template-columns: minmax(0, 1.25fr) minmax(320px, 1fr);
	}
}

.px-map {
	position: relative;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	overflow: hidden;
	background: var(--px-mist);
	aspect-ratio: 4 / 3;
}

.px-map iframe,
.px-map > div:not(.px-map-none) {
	width: 100% !important;
	height: 100% !important;
	border: 0;
	display: block;
}

.px-map-none {
	display: grid;
	place-items: center;
	align-content: center;
	gap: 12px;
	height: 100%;
	padding: 24px;
	text-align: center;
	color: var(--px-faint);
}

.px-map-none .px-i {
	color: var(--px-line-2);
}

/* The coordinates, over the map's bottom edge. Small, monospaced numerals — it
   is a reference value, not a headline, and an editor uses it to check the pin
   is in the right emirate. */
.px-map-coords {
	position: absolute;
	inset-inline-start: 10px;
	bottom: 10px;
	z-index: 2;
	margin: 0;
	padding: 5px 10px;
	border-radius: var(--px-r);
	background: rgba(255, 255, 255, 0.92);
	backdrop-filter: blur(6px);
	color: var(--px-body);
	font-size: var(--px-t-micro);
	font-weight: 600;
	letter-spacing: 0.02em;
	font-variant-numeric: tabular-nums;
	box-shadow: 0 1px 3px rgba(13, 20, 24, 0.14);
	pointer-events: none;
}

/* ---- Connectivity facts ---- */

.px-place {
	display: grid;
	gap: 10px;
	margin: 0 0 24px;
	padding: 0;
	list-style: none;
}

.px-place li {
	display: flex;
	align-items: flex-start;
	gap: 13px;
	padding: 14px 16px;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
}

.px-place-ico {
	flex: none;
	display: grid;
	place-items: center;
	width: 38px;
	height: 38px;
	border-radius: 9px;
	background: var(--px-tint);
	color: var(--px-green-deep);
}

.px-place-k {
	display: block;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-faint);
	margin-bottom: 3px;
}

.px-place-v {
	font-size: 0.9375rem;
	color: var(--px-ink);
	line-height: 1.5;
}

/* ---- Travel times ----
   A table of durations, set as one. The old version was two bulleted lists with
   a tick against every line; the tick carried no information — the number is
   the entire content, so it gets a column. */

.px-times {
	display: grid;
	gap: 22px;
}

.px-band-times h4 {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 6px;
	font-size: var(--px-t-h4);
}

.px-band-times h4 em {
	order: 3;
	flex: none;
	font-style: normal;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-green-deep);
	font-variant-numeric: tabular-nums;
}

.px-band-times h4::after {
	content: "";
	order: 2;
	flex: 1;
	height: 1px;
	background: var(--px-line);
}

.px-band-times ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.px-band-times li {
	display: flex;
	align-items: baseline;
	gap: 10px;
	padding: 10px 0;
	border-bottom: 1px solid var(--px-line);
	font-size: 0.9375rem;
}

.px-band-times li:last-child {
	border-bottom: 0;
}

.px-time-name {
	color: var(--px-ink);
}

/* A leader rule, so the eye can carry a long place name across to its time
   without the row becoming two disconnected columns. */
.px-time-dot {
	flex: 1;
	min-width: 18px;
	height: 1px;
	background: repeating-linear-gradient(to right, var(--px-line-2) 0 2px, transparent 2px 5px);
	transform: translateY(-3px);
}

.px-time-val {
	flex: none;
	color: var(--px-faint);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

/* =========================================================================
   15. INVESTMENT
   ====================================================================== */

.px-metrics {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
	gap: 1px;
	margin: 0 0 clamp(1.75rem, 1.2rem + 2vw, 2.5rem);
	background: var(--px-line);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	overflow: hidden;
}

.px-metric {
	padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
	background: var(--px-paper);
}

.px-metric dt {
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.13em;
	text-transform: uppercase;
	color: var(--px-faint);
	margin-bottom: 10px;
}

.px-metric dd {
	margin: 0;
	font-size: var(--px-t-figure);
	font-weight: 700;
	letter-spacing: -0.03em;
	line-height: 1.05;
	color: var(--px-green-deep);
	font-variant-numeric: tabular-nums;
}

.px-visa {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 18px;
	padding: clamp(1.25rem, 1rem + 1vw, 1.75rem);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-tint);
}

.px-visa .px-i {
	flex: none;
	color: var(--px-green-deep);
}

.px-visa-copy {
	flex: 1 1 260px;
}

.px-visa h4 {
	font-size: var(--px-t-h4);
	margin-bottom: 5px;
}

.px-visa p {
	font-size: 0.9375rem;
	margin: 0;
}

/* =========================================================================
   16. DEVELOPER
   ====================================================================== */

.px-dev {
	display: grid;
	gap: clamp(1.5rem, 1rem + 2.4vw, 3rem);
	align-items: center;
	padding: clamp(1.5rem, 1rem + 2.4vw, 2.75rem);
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
}

@media (min-width: 48rem) {
	.px-dev {
		grid-template-columns: 180px minmax(0, 1fr) auto;
	}
}

.px-dev-logo {
	display: grid;
	place-items: center;
	padding: 20px;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-mist);
	min-height: 110px;
}

.px-dev-logo img {
	max-height: 68px;
	width: auto;
	object-fit: contain;
	mix-blend-mode: multiply;
}

.px-dev-name {
	font-size: var(--px-t-h3);
	margin-bottom: 8px;
}

/* =========================================================================
   17. FAQ
   ====================================================================== */

.px-faq {
	max-width: 900px;
	margin-inline: auto;
	border-top: 1px solid var(--px-line);
}

.px-faq-item {
	border-bottom: 1px solid var(--px-line);
}

.px-faq-q {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 20px;
	width: 100%;
	padding: 22px 0;
	border: 0;
	background: none;
	color: var(--px-ink);
	font-size: var(--px-t-h4);
	font-weight: 700;
	letter-spacing: -0.015em;
	line-height: 1.4;
	text-align: start;
	cursor: pointer;
}

.px-faq-q:hover {
	color: var(--px-green-deep);
}

.px-faq-q .px-i {
	flex: none;
	margin-top: 3px;
	color: var(--px-faint);
	transition: transform 0.3s var(--px-ease), color 0.2s ease;
}

.px-faq-q[aria-expanded="true"] .px-i {
	transform: rotate(180deg);
	color: var(--px-green);
}

/* Grid-rows animation rather than max-height: the answer's height is unknown
   and a max-height guess either clips long answers or eases from nowhere. */
.px-faq-a {
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.35s var(--px-ease);
}

.px-faq-a > div {
	overflow: hidden;
}

/* Same wrapped-heading problem as the layout rows — see the note there. */
.px-faq-item.is-open .px-faq-a {
	grid-template-rows: 1fr;
}

.px-faq-a p {
	padding-bottom: 24px;
	padding-inline-end: 40px;
	margin: 0;
	color: var(--px-body);
	line-height: 1.75;
}

/* =========================================================================
   18. PROJECT CARDS  —  similar / same developer
   ====================================================================== */

.px-cards {
	display: flex;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x proximity;
	scroll-behavior: smooth;
	scrollbar-width: none;
	padding-block: 4px 8px;
	margin-inline: calc(-1 * var(--px-pad));
	padding-inline: var(--px-pad);
	-webkit-overflow-scrolling: touch;
}

.px-cards::-webkit-scrollbar {
	display: none;
}

.px-card {
	position: relative;
	flex: none;
	width: min(84vw, 380px);
	display: flex;
	flex-direction: column;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	overflow: hidden;
	scroll-snap-align: start;
	transition: border-color 0.25s ease, transform 0.35s var(--px-ease), box-shadow 0.35s var(--px-ease);
}

.px-card:hover {
	border-color: var(--px-line-2);
	transform: translateY(-4px);
	box-shadow: var(--px-sh);
}

.px-card-media {
	position: relative;
	aspect-ratio: 3 / 2;
	overflow: hidden;
	background: var(--px-mist);
}

.px-card-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.7s var(--px-ease);
}

.px-card:hover .px-card-media img {
	transform: scale(1.05);
}

.px-card-price {
	position: absolute;
	inset-inline-start: 12px;
	bottom: 12px;
	padding: 7px 13px;
	border-radius: var(--px-r);
	background: rgba(10, 16, 19, 0.72);
	backdrop-filter: blur(8px);
	color: #fff;
	font-size: var(--px-t-meta);
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

.px-card-body {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 18px 20px 20px;
	flex: 1;
}

.px-card-t {
	font-size: var(--px-t-h4);
}

/* The whole card is the link; the heading anchor is stretched over it so the
   accessible name stays on the anchor and nested links stay clickable. */
.px-card-t a::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

.px-card-meta {
	display: flex;
	align-items: center;
	gap: 7px;
	font-size: var(--px-t-meta);
	color: var(--px-faint);
}

.px-card-meta .px-i {
	color: var(--px-green);
}

.px-card-foot {
	margin-top: auto;
	padding-top: 14px;
	font-size: var(--px-t-meta);
	color: var(--px-faint);
}

/* =========================================================================
   19. CLOSING CTA
   ====================================================================== */

.px-close {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	background: var(--px-night);
	color: rgba(255, 255, 255, 0.76);
}

.px-close-media {
	position: absolute;
	inset: 0;
	z-index: -1;
}

.px-close-media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0.34;
}

.px-close-media::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(to bottom, rgba(8, 13, 15, 0.72), rgba(8, 13, 15, 0.94));
}

.px .px-close h2 {
	color: #fff;
	font-size: var(--px-t-h2);
}

/* =========================================================================
   20. MOBILE ACTION BAR
   ====================================================================== */

.px-actionbar {
	position: fixed;
	inset-inline: 0;
	bottom: 0;
	z-index: var(--px-z-bar);
	display: none;
	background: var(--px-paper);
	border-top: 1px solid var(--px-line);
	padding-bottom: env(safe-area-inset-bottom);
	box-shadow: 0 -2px 14px rgba(13, 20, 24, 0.1);
}

.px-actionbar-row {
	display: grid;
	grid-template-columns: auto auto minmax(0, 1fr);
	align-items: stretch;
}

.px-ab {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 3px;
	min-height: 64px;
	padding: 8px 14px;
	color: var(--px-body) !important;
	font-size: var(--px-t-micro);
	font-weight: 600;
	border-inline-end: 1px solid var(--px-line);
}

.px-ab--cta {
	flex-direction: row;
	gap: 8px;
	background: var(--px-green);
	color: #fff !important;
	font-size: 0.9375rem;
	font-weight: 700;
	border: 0;
}

@media (max-width: 61.99rem) {
	.px-actionbar {
		display: block;
	}

	/* Let the document end above the bar. */
	.px {
		padding-bottom: 64px;
	}
}

/* =========================================================================
   21. MODALS  —  amenities and brochure
   ====================================================================== */

.px-modal {
	position: fixed;
	inset: 0;
	z-index: var(--px-z-modal);
	display: none;
	place-items: center;
	padding: var(--px-pad);
	background: rgba(6, 11, 13, 0.62);
	backdrop-filter: blur(6px);
}

.px-modal.is-open {
	display: grid;
	animation: px-fade 0.2s ease both;
}

.px-modal-box {
	width: 100%;
	max-width: 620px;
	max-height: min(86vh, 760px);
	display: flex;
	flex-direction: column;
	border-radius: var(--px-r-2);
	background: var(--px-paper);
	overflow: hidden;
	box-shadow: 0 24px 60px rgba(6, 11, 13, 0.4);
	animation: px-pop 0.3s var(--px-ease) both;
}

.px-modal-box--wide {
	max-width: 860px;
}

@keyframes px-pop {
	from {
		opacity: 0;
		transform: translateY(16px) scale(0.98);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.px-modal-bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 18px 22px;
	border-bottom: 1px solid var(--px-line);
}

.px-modal-bar h2 {
	font-size: var(--px-t-h4);
}

.px-modal-body {
	padding: 22px;
	overflow-y: auto;
	/* Explicit, because `overflow-y: auto` alone computes overflow-x to `auto`
	   too, and a focus ring or a 1px rounding was enough to put a horizontal
	   scrollbar across the bottom of the dialog. */
	overflow-x: hidden;
	overscroll-behavior: contain;
}

.px-x {
	width: 40px;
	height: 40px;
	display: grid;
	place-items: center;
	border: 1px solid var(--px-line);
	border-radius: 50%;
	background: var(--px-paper);
	color: var(--px-ink);
	cursor: pointer;
	font-size: 1.125rem;
	line-height: 1;
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.px-x:hover {
	background: var(--px-mist);
	border-color: var(--px-line-2);
}

/* The brochure form drops the section chrome — inside a modal it is already
   framed by the modal's own header. */
.px-modal .px-form {
	padding: 0;
	border: 0;
	background: none;
	box-shadow: none;
}

/* ---- The brochure gate ------------------------------------------------ */

.px-modal-box--split {
	max-width: 880px;
}

@media (min-width: 56rem) {
	.px-modal-box--split {
		display: grid;
		/* The cover is fixed-ish and the form takes the rest: a fluid cover
		   would crop the render differently at every width. */
		grid-template-columns: 20rem minmax(0, 1fr);
	}
}

.px-gate-cover {
	position: relative;
	display: none;
	isolation: isolate;
	background: var(--px-night);
	overflow: hidden;
}

@media (min-width: 56rem) {
	.px-gate-cover {
		display: block;
	}
}

.px-gate-cover img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: -2;
}

.px-gate-cover::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(to top, rgba(5, 9, 11, 0.96) 12%, rgba(5, 9, 11, 0.55) 55%, rgba(5, 9, 11, 0.3));
}

.px-gate-cover-copy {
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	padding: 24px;
	color: #fff;
}

.px-gate-kicker {
	margin: 0 0 6px;
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: var(--px-track-caps);
	text-transform: uppercase;
	color: var(--px-green-lift);
}

.px-gate-name {
	margin: 0 0 18px;
	font-family: var(--px-display);
	font-size: 1.5rem;
	font-weight: 800;
	letter-spacing: var(--px-track-h3);
	line-height: 1.12;
	color: #fff;
}

.px-gate-facts {
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.px-gate-facts li {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 9px 0;
	border-bottom: 1px solid rgba(255, 255, 255, 0.16);
	font-size: var(--px-t-meta);
}

.px-gate-facts li:last-child {
	border-bottom: 0;
}

.px-gate-facts span {
	color: rgba(255, 255, 255, 0.62);
}

.px-gate-facts strong {
	color: #fff;
	font-weight: 700;
}

.px-gate-main {
	display: flex;
	flex-direction: column;
	min-height: 0;
}

.px-gate-gets {
	display: grid;
	gap: 9px;
	margin: 0 0 22px;
	padding: 0 0 20px;
	border-bottom: 1px solid var(--px-line);
	list-style: none;
}

.px-gate-gets li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-size: 0.9375rem;
	color: var(--px-ink);
}

.px-gate-gets .px-i {
	flex: none;
	margin-top: 2px;
	color: var(--px-green);
}

.px-gate-note {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	margin: 18px 0 0;
	font-size: var(--px-t-micro);
	line-height: 1.6;
	color: var(--px-faint);
}

.px-gate-note .px-i {
	flex: none;
	margin-top: 1px;
	color: var(--px-green);
}

/* ---- The plan-set gate ------------------------------------------------
   Cover on the inline-end side here, unlike the brochure gate: the preview is
   the argument, and the argument should be the last thing read before the
   submit button rather than the first thing before the form. */

.px-modal-box--flip .px-gate-peek {
	order: 2;
}

/*
 * `order` moves the panel but not the column sizes, so the flipped gate handed
 * the 20rem column to the form and the wide one to the preview — the form came
 * out at ~320px with the fields crushed against the divider. The track has to
 * be reversed too.
 */
@media (min-width: 56rem) {

	.px-modal-box--flip {
		grid-template-columns: minmax(0, 1fr) 20rem;
	}
}

.px-gate-badge {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	margin: 0 0 16px;
	padding: 5px 12px;
	border-radius: 999px;
	background: var(--px-tint);
	color: var(--px-green-deep);
	font-size: var(--px-t-micro);
	font-weight: 700;
	letter-spacing: 0.04em;
}

/*
 * The real drawing, blurred. A padlock over a grey rectangle asks for a phone
 * number in exchange for nothing visible; the actual plan, out of focus, shows
 * exactly what is behind the gate and is the reason this pattern converts.
 */
.px-gate-peek {
	position: relative;
	display: none;
	isolation: isolate;
	overflow: hidden;
	background: var(--px-mist);
	min-height: 260px;
}

@media (min-width: 56rem) {
	.px-gate-peek {
		display: block;
	}
}

.px-gate-peek img {
	position: absolute;
	inset: -8%;
	width: 116%;
	height: 116%;
	object-fit: cover;
	/* The inset overscan exists because `blur()` samples beyond the element and
	   would otherwise fade to transparent at all four edges. */
	filter: blur(9px) saturate(0.85);
	opacity: 0.85;
}

.px-gate-peek::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(140deg, rgba(255, 255, 255, 0.55), rgba(255, 255, 255, 0.2));
}

.px-gate-lock {
	position: absolute;
	inset-inline-start: 50%;
	top: 50%;
	z-index: 2;
	transform: translate(-50%, -50%);
	display: grid;
	place-items: center;
	width: 74px;
	height: 74px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.94);
	color: var(--px-green-deep);
	box-shadow: 0 10px 30px rgba(13, 20, 24, 0.16);
}

[dir="rtl"] .px-gate-lock {
	transform: translate(50%, -50%);
}

/* ---- Availability dialog ---------------------------------------------- */

.px-avail-unit {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 14px;
	padding: 8px 14px;
	border: 1px solid var(--px-line);
	border-radius: var(--px-r);
	background: var(--px-mist);
	color: var(--px-ink);
	font-size: 0.9375rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
}

/* =========================================================================
   22. EMPTY STATES
   ====================================================================== */

.px-empty {
	display: grid;
	place-items: center;
	gap: 12px;
	padding: clamp(2.5rem, 2rem + 3vw, 4rem) 1rem;
	border: 1px dashed var(--px-line-2);
	border-radius: var(--px-r-2);
	text-align: center;
	color: var(--px-faint);
}

.px-empty h3 {
	font-size: var(--px-t-h4);
}

/* =========================================================================
   22b. MICRO-INTERACTIONS

   Every rule here is tied to a state change the user caused. Nothing on this
   page moves to decorate — the anti-pattern the whole build is written against.
   ====================================================================== */

/* Solid buttons take a sheen that sweeps once on hover. It reads as a physical
   surface catching light, which is the whole argument of the page. */
.px-btn--solid {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.px-btn--solid::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, 0.22) 48%, transparent 66%);
	transform: translateX(-120%);
	transition: transform 0.7s var(--px-ease);
}

.px-btn--solid:hover::after {
	transform: translateX(120%);
}

/* Ghost buttons carry an arrow; it steps forward rather than the whole button
   moving, so the hit area never shifts under the cursor. */
.px-btn--ghost .px-i,
.px-btn--line .px-i {
	transition: transform 0.3s var(--px-ease);
}

.px-btn--ghost:hover .px-i,
.px-btn--line:hover .px-i {
	transform: translateX(4px);
}

[dir="rtl"] .px-btn--ghost:hover .px-i,
[dir="rtl"] .px-btn--line:hover .px-i {
	transform: translateX(-4px) rotate(180deg);
}

[dir="rtl"] .px-btn--ghost .px-i,
[dir="rtl"] .px-btn--line .px-i {
	transform: rotate(180deg);
}

/* Inline prose links draw their underline from the leading edge instead of
   toggling `text-decoration`, which pops. */
.px-prose a,
.px-key-copy a,
.px-faq-a a {
	background-image: linear-gradient(currentColor, currentColor);
	background-repeat: no-repeat;
	background-position: 0 100%;
	background-size: 0 1px;
	transition: background-size 0.35s var(--px-ease);
	padding-bottom: 1px;
}

[dir="rtl"] .px-prose a {
	background-position: 100% 100%;
}

.px-prose a:hover,
.px-key-copy a:hover,
.px-faq-a a:hover {
	background-size: 100% 1px;
}

/* Spec rows highlight the row being read. Cheap, and it stops a long
   label→value list from being a wall. */
.px-specs div,
.px-unit-specs div {
	transition: background-color 0.2s ease;
	padding-inline: 6px;
	margin-inline: -6px;
	border-radius: 3px;
}

.px-specs div:hover,
.px-unit-specs div:hover {
	background: var(--px-mist);
}

/* Cards get depth plus an arrow that slides in on the title. */
.px-card-t {
	display: flex;
	align-items: baseline;
	gap: 8px;
}

.px-card-t::after {
	content: "→";
	font-weight: 400;
	color: var(--px-green);
	opacity: 0;
	transform: translateX(-6px);
	transition: opacity 0.3s ease, transform 0.3s var(--px-ease);
}

[dir="rtl"] .px-card-t::after {
	content: "←";
	transform: translateX(6px);
}

.px-card:hover .px-card-t::after {
	opacity: 1;
	transform: none;
}

/* Chips lift very slightly off the rail on hover so the row reads as a set of
   controls rather than a set of labels. */
.px-chip {
	transition: border-color 0.2s ease, background-color 0.2s ease, color 0.2s ease, transform 0.2s var(--px-ease);
}

.px-chip:hover {
	transform: translateY(-2px);
}

/* The counter's own state. `is-counting` suppresses the tracking wobble that
   otherwise shows as digits change width mid-animation — tabular figures fix
   the width, this fixes the settle. */
[data-px-count].is-counting {
	opacity: 0.86;
}

/* Amenity rows sweep their tick to the accent as the row is hovered. */
.px-amen li .px-i {
	transition: transform 0.25s var(--px-ease);
}

.px-amen li:hover .px-i {
	transform: scale(1.18);
}

/* =========================================================================
   22c. RESPONSIVE

   The fluid clamps carry most widths on their own. These are the three places
   a clamp cannot help: where a column count has to change, where a fixed
   element has to move out of another's way, and where the shell would
   otherwise stretch a 20-word line across an ultrawide display.
   ====================================================================== */

/* ---- Tablet, 48–62rem -------------------------------------------------
   The gap that was wrong: every two-column band collapsed straight to one at
   62rem, so a 900px iPad rendered the mobile layout with 200px of dead margin
   either side. */

@media (min-width: 48rem) and (max-width: 61.99rem) {

	.px-hero-grid {
		grid-template-columns: minmax(0, 1fr);
		gap: 2rem;
	}

	/* The figures panel goes horizontal rather than stacking under a
	   full-width headline, which would push the CTA below the fold. */
	.px-hero-card {
		display: grid;
		grid-template-columns: minmax(0, 1fr) minmax(220px, 0.7fr);
		gap: 1.5rem;
		align-items: center;
	}

	.px-hero-card .px-hero-figs {
		margin-bottom: 0;
	}

	.px-hero-card .px-actions {
		flex-direction: column;
	}

	.px-split,
	.px-pay,
	.px-advisor {
		grid-template-columns: minmax(0, 1fr);
	}

	/* The spec sheet reads better as two columns than as one long list when
	   there is width for it but not enough for a true sidebar. */
	.px-specs {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: 32px;
	}

	.px-unit-body {
		grid-template-columns: minmax(0, 1fr);
	}

	.px-metrics {
		grid-template-columns: 1fr 1fr;
	}

	/* auto-fit leaves the sixth cell alone on a second row at this width. Three
	   columns gives two even rows instead of five and an orphan. */
	.px-ledger-row {
		grid-template-columns: repeat(3, 1fr);
	}

	.px-ledger-cell:nth-child(3n + 1) {
		border-inline-start: 0;
		padding-inline-start: 0;
	}

	.px-shot:first-child {
		width: min(72vw, 640px);
	}
}

/* Two up on phones, for the same reason. */
@media (max-width: 47.99rem) {

	.px-ledger-row {
		grid-template-columns: 1fr 1fr;
	}

	.px-ledger-cell:nth-child(odd) {
		border-inline-start: 0;
		padding-inline-start: 0;
	}

	/*
	 * The slab loses its glass on a phone. Stacked, the copy and the figures
	 * fill almost the whole viewport, so the panel stopped being an object on a
	 * photograph and became an opaque screen with a photograph behind it — the
	 * render, which is the reason the hero exists, no longer read at all.
	 * The scrim ramp already guarantees contrast at this width.
	 */
	.px-hero-slab {
		padding: 0;
		border-radius: 0;
		background: none;
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
		box-shadow: none;
	}

	/* A rule instead of the panel edge, to keep the figures visually attached
	   to the copy they belong to. */
	.px-hero-card {
		padding-top: 20px;
		border-top: 1px solid rgba(255, 255, 255, 0.18);
	}

	/* "Or speak to an adviser +971 2 681 0881" broke across three ragged lines
	   in a 375px column. The label goes, the number stays. */
	.px-hero-call span {
		display: none;
	}

	.px-hero-call {
		gap: 8px;
	}
}

/* ---- Short viewports --------------------------------------------------
   A landscape phone or a small laptop has plenty of width and almost no
   height; an 88svh hero fills the whole screen with a photograph and the
   ledger is never discovered. */

@media (max-height: 34rem) and (orientation: landscape) {

	.px-hero {
		min-height: 0;
		padding-block: 4rem;
	}

	.px-cue {
		display: none;
	}
}

/* ---- Large desktop ----------------------------------------------------
   Above the shell the bands keep their measure but the page needs more air,
   or the content reads as a column floating in a field. */

@media (min-width: 100rem) {

	:root {
		--px-shell: 1440px;
		--px-band: clamp(6rem, 4rem + 4vw, 9rem);
	}

	.px-hero {
		max-height: 1100px;
	}

	.px-shot:first-child {
		width: min(64vw, 1040px);
	}
}

/* ---- Fine pointer only ------------------------------------------------
   Hover affordances are noise on touch, where `:hover` sticks after a tap
   until something else is tapped. */

@media (hover: none) {

	.px-shot-zoom {
		opacity: 1;
		transform: none;
	}

	.px-card-t::after {
		opacity: 1;
		transform: none;
	}
}

/* =========================================================================
   23. PREFERENCES
   ====================================================================== */

@media (prefers-reduced-motion: reduce) {

	.px *,
	.px *::before,
	.px *::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}

	/* Hold the end state rather than the start state — a reduced-motion user
	   must not be left looking at `opacity: 0`. */
	.px-rise,
	[data-px-stagger] > *,
	html.px-io .px-rise,
	html.px-io [data-px-stagger] > * {
		opacity: 1 !important;
		transform: none !important;
		animation: none !important;
	}

	.px-hero-media img,
	.px-hero-inner {
		animation: none !important;
		transform: none !important;
		opacity: 1 !important;
	}

	/* The hero choreography holds its END state. A reduced-motion visitor must
	   never be left looking at a masked-out headline because the transition
	   that would have revealed it was suppressed. */
	.px-hero-title.is-split .px-line > span,
	.px-hero .px-lift {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}

	.px-key-frame {
		clip-path: none !important;
		animation: none !important;
	}

	.px-key-frame img {
		transform: none !important;
		animation: none !important;
	}

	.px-key-rule {
		width: 78px !important;
		animation: none !important;
	}

	.px-eyebrow::before {
		transform: none !important;
		animation: none !important;
	}

	.px-btn--solid::after {
		display: none;
	}

	.px-cue,
	.px-hero-grain,
	.px-flag::before {
		display: none;
	}
}

@media print {

	.px-dock,
	.px-actionbar,
	.px-lb,
	.px-viewer,
	.px-modal,
	.px-cue {
		display: none !important;
	}

	.px-hero {
		min-height: auto;
		color: #000;
		background: none;
	}

	.px-hero-media {
		display: none;
	}

	.px-hero-title,
	.px-hero-lede,
	.px-fig-v,
	.px-fig-k {
		color: #000 !important;
	}

	.px-band--night {
		background: none;
		color: #000;
	}

	.px-faq-a {
		grid-template-rows: 1fr !important;
	}
}
