/**
 * PropOffice Designs — Property Media.
 *
 * ONE stylesheet for every surface: the native PropOffice screen, the
 * [propoffice_property_media] shortcode, and the Elementor widget.
 * Hand-authored, no build step, enqueued with filemtime cache-busting
 * (see PropOffice\Designs\PropertyMedia\PropertyMediaAssets).
 *
 * PALETTE. Every colour reads a PropOffice design token with the token's own
 * value as the fallback: `var(--po-ds-color-text)`. Inside the workspace the
 * component inherits the live design system; on a public theme page — where
 * those tokens are not defined — it renders in the identical palette.
 *
 * ISOLATION. Every selector is namespaced under `.po-media`, so the component
 * can never restyle a theme, and it resets the handful of properties themes
 * most often impose on images, lists, figures and buttons.
 *
 * LAYOUT. Intrinsic and container-relative, never viewport-keyed — a media
 * block is placed in full-width heroes and in one-third sidebars, and "desktop
 * means four columns" is wrong in the second. The only viewport rules here are
 * the viewer's (it genuinely occupies the window) and reduced motion.
 */

/*
 * 🚨 THE TOKENS ARE DECLARED ON THE REUSED ROOTS TOO, NOT ONLY ON `.po-media`.
 *
 * The viewer and the grid are deliberately reused OUTSIDE this component:
 * `PropertyGalleryRenderer` composes Gallery Design #1 from
 * `MediaViewerRenderer` and `MediaGridRenderer` so that Fullscreen and Grid are
 * the same code the media block uses. That markup has no `.po-media` ancestor,
 * so every token declared only there resolved to nothing.
 *
 * `background: var(--po-media-stage)` with an undefined custom property is an
 * INVALID declaration, not a missing colour: background-color falls back to its
 * initial value, transparent. Measured on a live gallery - the viewer opened
 * `position: fixed; inset: 0; z-index: 100000` with `rgba(0, 0, 0, 0)` behind
 * it, so the property page showed straight through the dark room, and the
 * chrome text inherited the page's dark ink instead of `--po-media-stage-ink`.
 *
 * Declaring them on the roots that actually get reused makes each one
 * self-sufficient wherever it is mounted. Inside `.po-media` the nearer
 * declaration wins with identical values, so nothing there changes.
 */
.po-media,
.po-media__viewer,
.po-media__grid {
	--po-media-surface: var(--po-ds-color-surface);
	--po-media-border: var(--po-ds-color-border);
	--po-media-ink: var(--po-ds-color-text);
	--po-media-muted: var(--po-ds-color-muted);
	--po-media-radius: 10px;

	/* The grid's shape. Declared here, not only consumed: the renderer supplies
	   these as an inline style (which wins), and a custom property that is only
	   ever set from PHP reads as an undeclared reference to anything auditing
	   the stylesheet. These are the design's defaults. */
	--po-media-columns: 3;
	--po-media-gap: 12px;
	--po-media-ratio: 4/3;

	/* The viewer is a dark room on purpose: a photograph is the content, and
	   surrounding chrome that competes with it is chrome in the way. */
	--po-media-stage: #0b0f19;
	--po-media-stage-ink: #ffffff;
	--po-media-focus: var(--po-ds-color-primary);
}

.po-media {
	font-family: var(--po-ds-font-family);

	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	gap: var(--po-media-gap);
	color: var(--po-media-ink);
	font-size: 14px;
	line-height: 1.45;
}

.po-media *,
.po-media *::before,
.po-media *::after {
	box-sizing: inherit;
}

.po-media ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

.po-media figure,
.po-media p {
	margin: 0;
}

.po-media img {
	display: block;
	max-width: 100%;
}

/* One visible focus treatment for every control, including the ones a theme
   would otherwise strip. Never `outline: none` — a keyboard user who cannot see
   where they are cannot operate a gallery at all. */
.po-media a:focus-visible,
.po-media button:focus-visible,
.po-media [tabindex]:focus-visible {
	outline: 2px solid var(--po-media-focus);
	outline-offset: 2px;
}

/* ────────────────────────────────────────────────────────────────── lead */

.po-media__lead {
	position: relative;
	overflow: hidden;
	border-radius: var(--po-media-radius);
	background: var(--po-ds-color-background);
}

/**
 * 🚨 The grid's click target, hardened the same way and for the same reason.
 *
 * Two classes already won the `background` contest — but specificity only
 * protects a property this stylesheet DECLARES, and the same
 * `.elementor-kit-N button` rule also sets `box-shadow`, `opacity`,
 * `border-radius`, `font-family` and `font-size`. For those there was no
 * contest to win.
 *
 * MEASURED on the acceptance rig, on a real Property Page: pressing the
 * gallery's Grid control revealed thirteen visible 420x689 buttons, each
 * drawing a 14px blue glow and a 12px rounded corner around its photograph.
 * Third instance of this defect class, after the viewer's chrome and
 * `.po-gallery__opener`.
 */
.po-media__grid .po-media__open {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
	opacity: 1;
	font: inherit;
	cursor: pointer;
	position: relative;
	outline-offset: 0;
}

.po-media__lead-image {
	width: 100%;
	/* A hero keeps a stable box so the page does not jump as it loads. The
	   ratio is the grid's, so lead and cells agree about proportion. */
	aspect-ratio: var(--po-media-ratio);
	object-fit: cover;
}

/* The count badge: how many photographs there are, on the one control that
   opens them. Decorative — the button's own accessible name says it too. */
.po-media__count {
	position: absolute;
	right: 12px;
	bottom: 12px;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 4px 10px;
	border-radius: 999px;
	background: rgba(11, 15, 25, 0.72);
	color: #ffffff;
	font-size: 13px;
	font-weight: 600;
}

.po-media__grid .po-media__open-hint {
	position: absolute;
	right: 8px;
	top: 8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	border-radius: 6px;
	background: rgba(11, 15, 25, 0.55);
	color: #ffffff;
	opacity: 0;
	transition: opacity 140ms ease;
}

.po-media__open:hover .po-media__open-hint,
.po-media__open:focus-visible .po-media__open-hint {
	opacity: 1;
}

.po-media__open-icon {
	width: 15px;
	height: 15px;
}

/* ─────────────────────────────────────────────────────────────── actions */

.po-media__action-items {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.po-media__action {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 8px 14px;
	border: 1px solid var(--po-media-border);
	border-radius: 999px;
	background: var(--po-media-surface);
	color: var(--po-media-ink);
	font-family: var(--po-ds-font-family);
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition: background-color 140ms ease;
}

.po-media__action:hover {
	background: var(--po-ds-color-background);
}

.po-media__action-icon {
	width: 16px;
	height: 16px;
	color: var(--po-media-muted);
}

/* ────────────────────────────────────────────────────────────────── grid */

.po-media__grid {
	display: grid;

	/* The track floor is the larger of a readable minimum and an equal share of
	   the CONTAINER, so `auto-fill` can never open more tracks than were asked
	   for — the empty-trailing-column bug in one expression. Below the floor it
	   collapses on its own, with no breakpoint involved. */
	grid-template-columns: repeat(
		auto-fill,
		minmax(
			max(
				140px,
				(100% - ((var(--po-media-columns) - 1) * var(--po-media-gap))) / var(--po-media-columns)
			),
			1fr
		)
	);
	gap: var(--po-media-gap);
}

.po-media__cell {
	min-width: 0;
	overflow: hidden;
	border-radius: 8px;
	background: var(--po-ds-color-background);
}

.po-media__thumb {
	width: 100%;
	aspect-ratio: var(--po-media-ratio);
	object-fit: cover;
	transition: transform 200ms ease;
}

.po-media__cell:hover .po-media__thumb {
	transform: scale(1.03);
}

/* ──────────────────────────────────────────────────────────────── video */

.po-media__videos {
	display: flex;
	flex-direction: column;
	gap: var(--po-media-gap);
}

.po-media__video {
	overflow: hidden;
	border-radius: var(--po-media-radius);
	background: var(--po-media-stage);
}

.po-media__player {
	display: block;
	width: 100%;
	aspect-ratio: 16/9;
	background: var(--po-media-stage);
}

/* The facade. Nothing third-party has loaded at this point — this is a button
   over a coloured box until a visitor asks for the video. */
.po-media__embed {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 16/9;
	background: var(--po-media-stage);
}

.po-media__embed iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
}

.po-media__play {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.16);
	color: #ffffff;
	cursor: pointer;
	transition: background-color 140ms ease, transform 140ms ease;
}

.po-media__play:hover {
	background: rgba(255, 255, 255, 0.28);
	transform: scale(1.05);
}

.po-media__play-icon {
	width: 34px;
	height: 34px;
}

.po-media__play-link {
	color: #ffffff;
}

.po-media__tour {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 14px 18px;
	color: var(--po-media-stage-ink);
	text-decoration: none;
	font-weight: 600;
}

.po-media__tour-icon {
	width: 20px;
	height: 20px;
}

/* ──────────────────────────────────────────────────────────────── viewer */

/**
 * THE PROPERTY MEDIA VIEWER.
 *
 * ## It declares its own palette, and that is load-bearing
 *
 * The viewer is rendered into TWO hosts: the Property Media block (`.po-media`,
 * which defines `--po-media-*`) and the Property Gallery (`.po-gallery`, which
 * defines `--po-gallery-*` and has never defined a single `--po-media-*`).
 * Reading `--po-media-stage` from inside the gallery therefore resolved to
 * NOTHING, and an undefined custom property in `background` is invalid at
 * computed-value time — so the "dark room" was a transparent sheet over the
 * Property Page, which is the host it ships on.
 *
 * Every token the viewer needs is declared HERE, on the viewer itself, with the
 * reference's own value. It cannot be un-themed by the element it is dropped
 * into, and a host that wants to retheme it still can — these are custom
 * properties, and a host-defined value on an ancestor loses to a declaration on
 * the element only because this one is on the element. That is the intent: the
 * viewer establishes its own visual contract rather than inheriting whatever an
 * Elementor kit happens to hold.
 *
 * ## Specificity is deliberate, and `!important` is not used
 *
 * Host themes ship rules shaped like `.elementor-kit-10 button` — (0,1,1). Every
 * control here is written as `.po-media__viewer .po-media__thing` — (0,2,0) —
 * which wins on class count without touching `!important`. That is the same
 * remedy the Property Gallery applied to its own controls, for the same host
 * rule, and it is why the buttons in here cannot be repainted from outside.
 */

.po-media__viewer {
	/* The reference's palette, expressed as ROLES.
	 *
	 * Not literals: a design that names its own brand value looks like a token
	 * and behaves like a hardcoded colour, which is how the same grey drifted to
	 * three values across eight components and why a configured Elementor brand
	 * reached exactly one of them. The boundary already declares the reference's
	 * red as `--po-ds-color-accent` — the two are the same colour — so asking for
	 * the role renders the reference by default AND lets an operator's brand
	 * through. The literals below are the boundary's own published values,
	 * repeated as fallbacks for the case where the design system stylesheet is
	 * genuinely absent. */
	--po-viewer-chrome: var(--po-ds-color-surface);
	--po-viewer-ink: var(--po-ds-color-text);
	--po-viewer-muted: var(--po-ds-color-muted);
	--po-viewer-accent: var(--po-ds-color-accent);
	--po-viewer-on-accent: var(--po-ds-color-surface);
	/* The backdrop is not a brand role. A photograph is the content and the room
	   around it is deliberately near-black whatever the website's colours are —
	   an operator whose brand turned the viewer's walls orange would be fighting
	   their own listings. */
	--po-viewer-stage: #0b0f19;
	--po-viewer-scrim: rgb(0 0 0 / 62%);
	--po-viewer-on-scrim: #ffffff;
	--po-viewer-hairline: var(--po-ds-color-border);

	/* The reference's proportions. The header and the toolbar are fixed bands;
	   the photograph takes everything between them, which is what makes the
	   image the largest thing on screen at every viewport. */
	--po-viewer-header: 106px;
	--po-viewer-toolbar: 72px;
	--po-viewer-close: 88px;

	/* The GRID's shape, as tokens rather than as rules, so a breakpoint changes
	   one number instead of restating the whole track definition — and so a test
	   can assert the contract rather than pattern-match a `repeat()` string.
	   Measured from the reference: three columns edge to edge, a narrow gutter
	   the chrome colour shows through, and a 16:9 crop. */
	--po-viewer-grid-columns: 3;
	--po-viewer-grid-gap: 8px;
	--po-viewer-grid-ratio: 16 / 9;

	position: fixed;
	inset: 0;
	z-index: 2147483000;
	display: grid;
	/* Three rows, and the middle one is `minmax(0, 1fr)` rather than `1fr`: a
	   bare `1fr` floors at the content's minimum size, so a tall photograph
	   would push the toolbar off the bottom of the window instead of being
	   made to fit. */
	grid-template-rows: auto minmax(0, 1fr) auto;
	/* 🚨 The COLUMN needs the same floor as the rows, and for the same reason on
	   the other axis. A grid column defaults to `auto`, which floors at the
	   widest item's MIN-CONTENT width — so a header whose contents did not fit
	   made the whole viewer 857px wide inside a 768px window, and carried the
	   close control and the next arrow off the right edge with it. Measured at
	   768: header/stage/toolbar 857, close at x=781, next at x=801. */
	grid-template-columns: minmax(0, 1fr);
	background: var(--po-viewer-stage);
	color: var(--po-viewer-on-scrim);
	font-family: var(--po-ds-font-family, system-ui, -apple-system, "Segoe UI", sans-serif);
	/* The viewer is the top layer of the document while it is open. Nothing on
	   the page behind it — a sticky theme header, an Elementor overlay — may
	   paint over a modal. */
	isolation: isolate;
}

/* `hidden` is an attribute a `display` rule can silently defeat, and a viewer
   that is merely invisible still holds forty-three focusable figures in the tab
   order. This is the one rule that must never be overridden. */
.po-media__viewer[hidden] {
	display: none;
}

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

/* ───────────────────────────────────────────────────────────────── header */

.po-media__viewer .po-media__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	min-height: var(--po-viewer-header);
	/* No right padding: the close control is flush to the window edge in the
	   reference, and a gap there would read as a misalignment. */
	padding: 0 0 0 28px;
	background: var(--po-viewer-chrome);
	color: var(--po-viewer-ink);
	border-bottom: 1px solid var(--po-viewer-hairline);
}

/* Price and title, side by side, sharing a baseline. */
.po-media__viewer .po-media__viewer-context {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 4px 18px;
	min-width: 0;
}

.po-media__viewer .po-media__price {
	margin: 0;
	color: var(--po-viewer-accent);
	font-size: 27px;
	font-weight: 700;
	line-height: 1.2;
	white-space: nowrap;
}

.po-media__viewer .po-media__viewer-title {
	margin: 0;
	color: var(--po-viewer-ink);
	font-size: 22px;
	font-weight: 400;
	line-height: 1.3;
	/* The one thing in the header allowed to lose characters. Everything else
	   is a number or an action; a long listing title is the only element that
	   can be truncated without losing meaning.

	   `min-width: 0` is what makes that actually happen. A flex item defaults to
	   `min-width: auto`, which refuses to shrink below its own content — so
	   `text-overflow: ellipsis` never fires and the title pushes the header
	   wider instead of getting shorter. */
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.po-media__viewer .po-media__header-actions {
	display: flex;
	align-items: center;
	gap: 28px;
	margin-left: auto;
}

/* ────────────────────────────────────────────────────────────────── facts */

.po-media__viewer .po-media__facts {
	display: flex;
	align-items: flex-start;
	gap: 30px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.po-media__viewer .po-media__fact {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 2px;
	text-align: center;
}

/* Mark and number share a line; the label sits under both. */
.po-media__viewer .po-media__fact-mark {
	display: inline-flex;
	align-items: center;
	gap: 7px;
}

.po-media__viewer .po-media__fact-icon {
	width: 21px;
	height: 21px;
	flex: 0 0 auto;
}

/* The supplied specification artwork is drawn with a literal `fill="#CBD5E1"`,
   which is a pale grey chosen for a dark card and is nearly invisible on this
   white header. It is repainted through the attribute it actually carries —
   the same technique the Property Card's style controls use — because a
   `color` rule cannot reach a fill that is not `currentColor`. */
.po-media__viewer .po-media__fact-icon [fill]:not([fill="none"]) {
	fill: var(--po-viewer-muted);
}

.po-media__viewer .po-media__fact-icon [stroke]:not([stroke="none"]) {
	stroke: var(--po-viewer-muted);
}

.po-media__viewer .po-media__fact-value {
	color: var(--po-viewer-ink);
	font-size: 20px;
	font-weight: 700;
	line-height: 1.2;
}

.po-media__viewer .po-media__fact-label {
	color: var(--po-viewer-muted);
	font-size: 13px;
	font-weight: 400;
	line-height: 1.2;
}

/* ──────────────────────────────────────────────────────── header actions */

.po-media__viewer .po-media__contact {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 60px;
	padding: 0 30px;
	border: 0;
	border-radius: 3px;
	background: var(--po-viewer-accent);
	color: var(--po-viewer-on-accent);
	font-family: inherit;
	font-size: 17px;
	font-weight: 500;
	line-height: 1;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 140ms ease;
}

/* Darkened by FILTER rather than by a second red. A hover state written as
   another hex would be a brand value this component invented, and it would stop
   tracking the accent the moment an operator changed it. */
.po-media__viewer .po-media__contact:hover,
.po-media__viewer .po-media__contact:focus-visible {
	filter: brightness(0.88);
	color: var(--po-viewer-on-accent);
	text-decoration: none;
}

.po-media__viewer .po-media__close {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--po-viewer-close);
	height: var(--po-viewer-close);
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: var(--po-viewer-accent);
	color: var(--po-viewer-on-accent);
	/* Square in the reference, and it stays square: a theme `line-height` on
	   buttons would otherwise stretch it into a rectangle. */
	line-height: 0;
	cursor: pointer;
	appearance: none;
	transition: background-color 140ms ease;
}

.po-media__viewer .po-media__close:hover,
.po-media__viewer .po-media__close:focus-visible {
	filter: brightness(0.88);
}

.po-media__viewer .po-media__close-icon {
	width: 30px;
	height: 30px;
}

/* ─────────────────────────────────────────────────────────────────── stage */

.po-media__viewer .po-media__stage {
	position: relative;
	/* `overflow: hidden` with `min-height: 0` is what actually holds the
	   photograph inside its row. Without the minimum, a grid item refuses to
	   shrink below its content and the image escapes the viewport. */
	min-height: 0;
	overflow: hidden;
	background: var(--po-viewer-stage);
}

.po-media__viewer .po-media__slides {
	position: relative;
	width: 100%;
	height: 100%;
}

/* Only the active slide occupies the stage. The rest stay in the document —
   server-rendered, lazy, addressable — but out of the flow and out of sight. */
.po-media__viewer .po-media__slide {
	display: none;
	position: relative;
	width: 100%;
	height: 100%;
	margin: 0;
}

.po-media__viewer .po-media__slide.is-active {
	display: block;
}

/* The reference fills the stage edge to edge — the photograph IS the screen,
   with no letterboxing either side. `cover` is what does that, and the cost is
   stated plainly: the extremes of a very tall or very wide picture are cropped.
   That is the reference's composition, not an accident. */
.po-media__viewer .po-media__image {
	display: block;
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	object-fit: cover;
	object-position: center;
}

.po-media__viewer .po-media__caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	margin: 0;
	padding: 14px 24px;
	background: linear-gradient(transparent, rgb(0 0 0 / 55%));
	color: var(--po-viewer-on-scrim);
	font-size: 13px;
	text-align: center;
}

/* ────────────────────────────────────────────────────────────── navigation */

.po-media__viewer .po-media__nav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 56px;
	height: 96px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: rgb(255 255 255 / 22%);
	color: var(--po-viewer-on-scrim);
	line-height: 0;
	cursor: pointer;
	appearance: none;
	transition: background-color 140ms ease;
}

.po-media__viewer .po-media__nav:hover,
.po-media__viewer .po-media__nav:focus-visible {
	background: rgb(255 255 255 / 38%);
}

/* Disabled rather than hidden: a control that disappears at the end of a
   gallery moves the one beside it, and layout shifting under a pointer is
   worse than a dimmed button. */
.po-media__viewer .po-media__nav[disabled] {
	opacity: 0.3;
	cursor: default;
}

.po-media__viewer .po-media__nav--previous {
	left: 0;
}

.po-media__viewer .po-media__nav--next {
	right: 0;
}

.po-media__viewer .po-media__nav-icon {
	width: 30px;
	height: 30px;
}

/* ───────────────────────────────────────────────────────────────── counter */

/* Over the photograph, bottom right — the reference's position. It is inside
   the stage, so it travels with the image rather than sitting in a band that
   would cost the picture height. */
.po-media__viewer .po-media__viewer-footer {
	position: absolute;
	right: 22px;
	bottom: 18px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 6px 12px;
	border-radius: 3px;
	background: var(--po-viewer-scrim);
	pointer-events: none;
}

.po-media__viewer .po-media__counter-icon {
	width: 15px;
	height: 15px;
	color: var(--po-viewer-on-scrim);
}

.po-media__viewer .po-media__counter-icon [fill]:not([fill="none"]) {
	fill: currentColor;
}

.po-media__viewer .po-media__counter-icon [stroke]:not([stroke="none"]) {
	stroke: currentColor;
}

.po-media__viewer .po-media__counter {
	margin: 0;
	color: var(--po-viewer-on-scrim);
	font-size: 13px;
	font-weight: 700;
	line-height: 1.2;
	white-space: nowrap;
}

/* ──────────────────────────────────────────────────────────────── the grid */

/**
 * The contact sheet, as the reference draws it.
 *
 * 🚨 NOT the dark room. The slideshow needs its near-black surround because one
 * photograph is the content and everything else is chrome in the way. The grid
 * inverts that: EVERY photograph is the content, so the reference runs them
 * edge to edge under the header with only a hairline gutter, and the surface
 * shows through that gutter rather than framing each picture in a dark card.
 *
 * Measured before this: 24px of padding and a 14px gap around 220x165 tiles on
 * `--po-viewer-stage`, which read as a thumbnail browser floating in a dark
 * room rather than a wall of photographs.
 *
 * The stage keeps its dark background — this is scoped to grid mode only.
 */
.po-media__viewer .po-media__viewer-grid {
	grid-row: 2;
	grid-column: 1;
	min-height: 0;
	overflow-y: auto;
	/* Edge to edge. The gutters between cells are the only spacing. */
	padding: 0;
	background: var(--po-viewer-chrome);
	-webkit-overflow-scrolling: touch;
}

.po-media__viewer .po-media__viewer-grid[hidden] {
	display: none;
}

/**
 * A FIXED column count, not `auto-fill`.
 *
 * `auto-fill` with a 220px floor is what produced six columns at 1440 and more
 * on a wide monitor: it fits as many tracks as the width allows, so the number
 * of columns — and therefore how large each photograph is — was decided by the
 * window rather than by the design. The reference states three, so the design
 * states three, and the breakpoints below change that number deliberately.
 *
 * `minmax(0, 1fr)` and not `1fr`: a bare `1fr` floors at the track's min-content
 * width, which for an image track is the image's intrinsic width. Same trap the
 * viewer's own grid column hit at 768.
 */
.po-media__viewer .po-media__viewer-grid-list {
	display: grid;
	grid-template-columns: repeat(var(--po-viewer-grid-columns), minmax(0, 1fr));
	gap: var(--po-viewer-grid-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.po-media__viewer .po-media__viewer-tile {
	margin: 0;
	padding: 0;
	list-style: none;
}

.po-media__viewer .po-media__viewer-tile-button {
	display: block;
	width: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	/* Square. The reference's photographs sit flush against each other; a
	   rounded corner reads as a card, and a wall of cards is the thing this
	   stopped being. */
	border-radius: 0;
	background: none;
	line-height: 0;
	cursor: pointer;
	appearance: none;
	overflow: hidden;
}

.po-media__viewer .po-media__viewer-tile-image {
	display: block;
	width: 100%;
	/* The reference's cells measure ~630x351 — 16:9, not the 4:3 these were.
	   `cover` still does the cropping, so no source dimension changes and no
	   image is distorted; only the window onto it does. */
	aspect-ratio: var(--po-viewer-grid-ratio);
	object-fit: cover;
	transition: transform 160ms ease, opacity 160ms ease;
}

.po-media__viewer .po-media__viewer-tile-button:hover .po-media__viewer-tile-image,
.po-media__viewer .po-media__viewer-tile-button:focus-visible .po-media__viewer-tile-image {
	transform: scale(1.03);
	opacity: 0.88;
}

/* The stage and the grid are the SAME row. Whichever the mode names is the one
   drawn; the other is `hidden`, which removes it from the tab order too. */
.po-media__viewer[data-po-media-mode="grid"] .po-media__stage {
	display: none;
}

/* ────────────────────────────────────────────────────────────────── toolbar */

.po-media__viewer .po-media__modes {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	min-height: var(--po-viewer-toolbar);
	padding: 6px 16px;
	background: var(--po-viewer-chrome);
	border-top: 1px solid var(--po-viewer-hairline);
}

.po-media__viewer .po-media__mode {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 62px;
	height: 54px;
	margin: 0;
	padding: 0;
	border: 1px solid var(--po-viewer-hairline);
	border-radius: 2px;
	background: var(--po-viewer-chrome);
	color: var(--po-viewer-muted);
	line-height: 0;
	cursor: pointer;
	appearance: none;
	transition: background-color 140ms ease, color 140ms ease, border-color 140ms ease;
}

.po-media__viewer .po-media__mode:hover {
	color: var(--po-viewer-ink);
	border-color: rgb(0 0 0 / 22%);
}

/* The active view is the solid red control in the reference. Written against
   BOTH the class and `aria-pressed` so the visual state and the announced one
   cannot disagree — if the script ever sets one without the other, the button
   stops looking active and the bug is visible rather than silent. */
.po-media__viewer .po-media__mode.is-active,
.po-media__viewer .po-media__mode[aria-pressed="true"] {
	background: var(--po-viewer-accent);
	border-color: var(--po-viewer-accent);
	color: var(--po-viewer-on-accent);
}

.po-media__viewer .po-media__mode-icon {
	width: 26px;
	height: 26px;
}

.po-media__viewer .po-media__mode-icon [fill]:not([fill="none"]) {
	fill: currentColor;
}

.po-media__viewer .po-media__mode-icon [stroke]:not([stroke="none"]) {
	stroke: currentColor;
}

/* ───────────────────────────────────────────────── host-theme reset */

/**
 * 🚨 SPECIFICITY ONLY PROTECTS PROPERTIES THIS FILE ACTUALLY DECLARES.
 *
 * That is the trap, and it was MEASURED on the acceptance rig rather than
 * reasoned about. Every control here already outranked `.elementor-kit-N button`
 * on background, colour, border, radius and font — because each of those is
 * declared above. But the same host rule also sets `box-shadow`, `opacity`,
 * `font-family` and `font-size`, and for a property no PropOffice rule mentions
 * there is nothing to outrank: the host wins uncontested at (0,1,1) over
 * nothing at all.
 *
 * Live result before this block: a 14px blue glow around every arrow, close
 * button, toolbar button and grid tile — over the photograph — plus Comic Sans
 * at 19px and 0.9 opacity on all of them.
 *
 * So the properties §16 names are declared EXPLICITLY on every control, at the
 * same two-class specificity. Declaring a property is what makes specificity
 * mean anything; an undeclared property has no contest to win.
 */
.po-media__viewer .po-media__close,
.po-media__viewer .po-media__contact,
.po-media__viewer .po-media__nav,
.po-media__viewer .po-media__mode,
.po-media__viewer .po-media__viewer-tile-button {
	box-shadow: none;
	opacity: 1;
	font-family: inherit;
	letter-spacing: normal;
	text-transform: none;
	min-width: 0;
	min-height: 0;
	max-width: none;
	outline-offset: 0;
}

/* The disabled arrows keep their own dimming — declared after the reset so the
   reset cannot flatten the one opacity this design does mean. */
.po-media__viewer .po-media__nav[disabled] {
	opacity: 0.3;
}

/* Icon-only controls carry no text, so a host font-size would only change how
   the SVG's `em`-derived box resolves. Pinned anyway: it costs one declaration
   and removes a whole class of surprise. */
.po-media__viewer .po-media__close,
.po-media__viewer .po-media__nav,
.po-media__viewer .po-media__mode,
.po-media__viewer .po-media__viewer-tile-button {
	font-size: 0;
}

/* ───────────────────────────────────────────────────────────────── focus */

/* A visible focus ring on every control, in a colour that reads against both
   the white chrome and the photograph. */
.po-media__viewer .po-media__close:focus-visible,
.po-media__viewer .po-media__contact:focus-visible,
.po-media__viewer .po-media__nav:focus-visible,
.po-media__viewer .po-media__mode:focus-visible,
.po-media__viewer .po-media__viewer-tile-button:focus-visible {
	outline: 3px solid var(--po-viewer-accent);
	outline-offset: 2px;
}

/* ─────────────────────────────────────────────────────── responsive */

/* The viewer is the one part that IS viewport business: it covers the window,
   so it is the window's dimensions that decide how much chrome fits.

   The DESIGN does not change below — the same header, the same bands, the same
   red actions in the same order. Only the sizes step down, and only where
   keeping the desktop value would push something off screen. */

/* Tablet and below: the title yields first. It is the longest thing in the
   header and the only one that can be shortened without losing a fact. */
@media (max-width: 1024px) {
	.po-media__viewer {
		--po-viewer-header: 92px;
		--po-viewer-close: 76px;
		/* Two. Three tracks here would be ~250px each, which is the thumbnail
		   scale the reference is explicitly not. */
		--po-viewer-grid-columns: 2;
	}

	.po-media__viewer .po-media__header {
		padding-left: 20px;
	}

	.po-media__viewer .po-media__header-actions {
		gap: 18px;
	}

	.po-media__viewer .po-media__facts {
		gap: 22px;
	}

	.po-media__viewer .po-media__price {
		font-size: 24px;
	}

	.po-media__viewer .po-media__viewer-title {
		font-size: 18px;
	}

	.po-media__viewer .po-media__contact {
		height: 52px;
		padding: 0 22px;
		font-size: 15px;
	}
}

/* Below this the three specification stacks cannot share a line with the price,
   a truncating title, an action and a close control — measured, not guessed: at
   768 the header's contents came to 857px and pushed the close control off the
   right edge of the window.

   The facts are what go, because the price and the title identify the listing
   and the specifications are a short scroll away on the page behind. Losing the
   close control instead would leave a visitor inside a modal with no way out. */
@media (max-width: 860px) {
	.po-media__viewer .po-media__facts {
		display: none;
	}
}

/* Phone. The same design, at phone sizes. */
@media (max-width: 767px) {
	.po-media__viewer {
		--po-viewer-header: 72px;
		--po-viewer-toolbar: 62px;
		--po-viewer-close: 60px;
	}

	.po-media__viewer .po-media__header {
		gap: 12px;
		padding-left: 14px;
	}

	.po-media__viewer .po-media__viewer-context {
		flex-direction: column;
		align-items: flex-start;
		gap: 1px;
	}

	.po-media__viewer .po-media__price {
		font-size: 19px;
	}

	.po-media__viewer .po-media__viewer-title {
		font-size: 13px;
	}

	.po-media__viewer .po-media__facts {
		display: none;
	}

	.po-media__viewer .po-media__header-actions {
		gap: 10px;
	}

	.po-media__viewer .po-media__contact {
		height: 44px;
		padding: 0 16px;
		font-size: 14px;
	}

	.po-media__viewer .po-media__close-icon {
		width: 22px;
		height: 22px;
	}

	.po-media__viewer .po-media__nav {
		width: 40px;
		height: 72px;
	}

	.po-media__viewer .po-media__nav-icon {
		width: 22px;
		height: 22px;
	}

	.po-media__viewer .po-media__viewer-footer {
		right: 12px;
		bottom: 12px;
		padding: 5px 9px;
	}

	.po-media__viewer .po-media__counter {
		font-size: 12px;
	}

	.po-media__viewer .po-media__mode {
		width: 54px;
		height: 46px;
	}

	/* One. At 375 two tracks are ~183px wide and 103 tall — a contact sheet of
	   stamps. The reference's whole proposition is that the photographs
	   dominate, and on a phone that means one per row. The grid stays edge to
	   edge; only the count changes. */
	.po-media__viewer {
		--po-viewer-grid-columns: 1;
	}
}

/* The narrowest supported widths. The Contact Agent label is the last thing to
   go — at 320px it would push the close control off the window, and a viewer
   that cannot be closed is worse than one that cannot be contacted from. The
   enquiry form is still there on the page behind. */
@media (max-width: 419px) {
	.po-media__viewer {
		--po-viewer-header: 64px;
		--po-viewer-close: 52px;
	}

	/* Contact Agent SHRINKS here rather than disappearing. It is one of the
	   reference's elements, and a viewer that cannot be enquired from has lost
	   something real. The title gives up the room instead — it is the one thing
	   in the header that can truncate without losing meaning. */
	.po-media__viewer .po-media__contact {
		height: 38px;
		padding: 0 12px;
		font-size: 13px;
	}

	.po-media__viewer .po-media__price {
		font-size: 17px;
	}

	.po-media__viewer .po-media__viewer-title {
		font-size: 12px;
	}
}

/* Below 360. Contact Agent is the last thing to go, and only now: any narrower
   and it pushes the close control off the window. A visitor trapped in a modal
   they cannot close is a worse failure than one who has to scroll the page
   behind to reach the enquiry form. */
@media (max-width: 359px) {
	.po-media__viewer {
		--po-viewer-close: 46px;
	}

	.po-media__viewer .po-media__contact {
		display: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.po-media__thumb,
	.po-media__open-hint,
	.po-media__action,
	.po-media__play,
	.po-media__viewer .po-media__nav,
	.po-media__viewer .po-media__close,
	.po-media__viewer .po-media__contact,
	.po-media__viewer .po-media__mode,
	.po-media__viewer .po-media__viewer-tile-image {
		transition: none;
	}

	.po-media__cell:hover .po-media__thumb,
	.po-media__play:hover,
	.po-media__viewer .po-media__viewer-tile-button:hover .po-media__viewer-tile-image {
		transform: none;
	}
}
