/**
 * PropOffice Property UIs - slider presentation.
 *
 * Slider chrome only. Nothing here knows what a property is or how a showcase
 * looks; a slide is a box that holds whichever version renderer ran, and
 * version styling stays in assets/css/versions/.
 *
 * Swiper's own stylesheet comes from Elementor and does the layout. This file
 * adds only what Swiper has no opinion about: where the navigation and
 * pagination sit, and what they look like.
 *
 * Positioning is the substantial part. Navigation and pagination are each
 * absolutely positioned against the slider root and placed by two custom
 * properties - an anchor percentage and the matching translation - so a preset
 * is one declaration and needs no per-preset selector. Left is 0%/0%, centre is
 * 50%/-50%, right is 100%/-100%. Offsets nudge from the anchor and may be
 * negative, which is what makes an arbitrary position reachable without a
 * separate "custom" mode. Nothing uses a negative margin to fake a layout.
 */

/*
 * No gap or slides-per-view token here. Swiper writes both as inline styles on
 * the wrapper and slides once it initialises, and an inline style outranks
 * every stylesheet, so a token would be dead the moment the slider started.
 * Those two settings travel as Swiper configuration instead.
 */
.propoffice-pui-slider {
	--ppui-nav-x: 50%;
	--ppui-nav-tx: -50%;
	--ppui-nav-y: 100%;
	--ppui-nav-ty: 0%;
	--ppui-nav-dx: 0px;
	--ppui-nav-dy: 12px;
	--ppui-nav-gap: 0.75rem;
	--ppui-nav-size: 44px;
	--ppui-nav-icon-size: 1.25rem;
	--ppui-nav-color: var(--ppui-cta-text);
	--ppui-nav-color-hover: var(--ppui-cta-text);
	--ppui-nav-bg: var(--ppui-cta-bg);
	--ppui-nav-bg-hover: var(--ppui-cta-bg);

	--ppui-dot-x: 50%;
	--ppui-dot-tx: -50%;
	--ppui-dot-y: 100%;
	--ppui-dot-ty: 0%;
	--ppui-dot-dx: 0px;
	--ppui-dot-dy: 12px;
	--ppui-dot-gap: 0.5rem;
	--ppui-dot-size: 10px;
	--ppui-dot-active-size: 10px;
	--ppui-dot-color: var(--ppui-border);
	--ppui-dot-active-color: var(--ppui-cta-bg);

	--ppui-counter-x: 0%;
	--ppui-counter-tx: 0%;
	--ppui-counter-y: 0%;
	--ppui-counter-ty: 0%;
	--ppui-counter-dx: 0px;
	--ppui-counter-dy: 0px;
	--ppui-counter-color: var(--ppui-text-inverse);
	--ppui-counter-active: var(--ppui-text-inverse);
	--ppui-counter-bg: transparent;

	position: relative;

	/*
	 * min-width, and it is not optional.
	 *
	 * The slider is a grid item of the component root, and a grid item defaults
	 * to min-width: auto - meaning it refuses to become narrower than its own
	 * min-content width. Inside is a flex row of every slide, so that
	 * min-content width is the sum of all of them.
	 *
	 * The result was not a slightly wide slider but a runaway one: the item grew
	 * to fit the row, Swiper measured that width and wrote it back as each
	 * slide's width, which widened the row again. On a page of 21 properties it
	 * settled at roughly 26.8 million pixels, dragging the document's scroll
	 * width with it and stretching one placeholder across the whole viewport -
	 * which is what the large flat colour blocks actually were.
	 *
	 * max-width pins the other end, so no future content can push it out again.
	 */
	max-width: 100%;
	min-width: 0;
}

/*
 * The viewport clips; the root does not. Navigation and pagination are siblings
 * of the viewport rather than children, so they can be placed outside the
 * slide area without being cut off by the overflow that makes a slider work.
 */
.propoffice-pui-slider__viewport {
	overflow: hidden;
	position: relative;
	width: 100%;
}

.propoffice-pui-slider__slide {
	height: auto;
	min-width: 0;
}

/*
 * Before Swiper initialises - and permanently, if the library never arrives -
 * the slides stay in normal block flow, which reads exactly like the static
 * presentation.
 *
 * This is where degradation belongs. An earlier version handled it in PHP by
 * refusing to emit slider markup unless Swiper was already registered, which
 * made the rendered HTML depend on asset-registration order and produced a
 * slider on the site and a vertical list in the editor from identical settings.
 *
 * Note what this does not do: no slide is hidden, none is clipped, and every
 * property remains a real .swiper-slide in the document. Swiper adds
 * .swiper-initialized the moment it takes over, and this stops applying.
 */
.propoffice-pui-slider .swiper:not(.swiper-initialized) .swiper-wrapper {
	display: block;
}

/*
 * The track's own layout, for an initialised slider.
 *
 * The comment at the top of this file says Swiper's stylesheet does the layout,
 * and on a page that carries it, it does. The widget's declared dependencies
 * and its render-time enqueue both request that stylesheet, but a request is not
 * a guarantee: an Elementor element-cache hit skips the render, and an asset
 * optimiser can drop a stylesheet it believes unused. Swiper still initialises
 * in that case - the script does not need the stylesheet - and then lays its
 * inline slide widths out in a `display: block` wrapper, which is a column of
 * full-height cards that reads as "the slider is broken on the live site" while
 * the editor, which always loads every stylesheet, looks right.
 *
 * These four declarations are the ones the track cannot work without, written
 * for the initialised state only and identical to Swiper's, so on a page that
 * has both stylesheets they change nothing. Navigation, pagination, effects and
 * the rest of Swiper's stylesheet are deliberately not copied.
 */
.propoffice-pui-slider .swiper.swiper-initialized {
	overflow: hidden;
}

.propoffice-pui-slider .swiper-initialized > .swiper-wrapper {
	display: flex;
	box-sizing: content-box;
	width: 100%;
	height: 100%;
	position: relative;
}

.propoffice-pui-slider .swiper-initialized > .swiper-wrapper > .swiper-slide {
	flex-shrink: 0;
	position: relative;
}

/*
 * The one frame between the markup landing and Swiper taking over.
 *
 * In the editor the build is deferred so the browser can paint the fields an
 * editor just changed rather than laying out twenty slides first. That leaves a
 * single frame in which the rule above is in force and every slide is in normal
 * block flow - twenty heroes stacked vertically, which is a worse flicker than
 * the wait it replaces.
 *
 * The attribute is set only while a build is actually pending, and only in the
 * editor, so the degradation above is untouched everywhere it matters: a page
 * that never receives Swiper still shows every property as a real slide.
 */
.propoffice-pui-slider[data-propoffice-initialising] .swiper:not(.swiper-initialized) .swiper-slide:not(:first-child) {
	display: none;
}

/* ------------------------------------------------------------- Navigation */

/*
 * Every rule from here down is written as `.propoffice-pui-slider .x` rather
 * than `.x`, and the extra class is doing real work.
 *
 * The arrows are <button> elements, and both the theme and the Elementor kit
 * style buttons globally - `.elementor-kit-10 button` is one class plus one
 * element, which outranks a lone class. On the live site that silently replaced
 * the arrow's background and colour with the kit's accent, and forced
 * `padding: 20px 40px`, inflating a 64px button to 83px. Two classes beats one
 * class plus an element, so these rules win without resorting to !important.
 *
 * The pagination has the same problem from the other direction: Swiper's own
 * `.swiper-pagination-bullets.swiper-pagination-horizontal` is two classes and
 * sets `width: 100%; left: 0`, which pinned the dots full-width and left the
 * centring transform pulling them 50% off the edge.
 */
.propoffice-pui-slider .propoffice-pui-slider__nav {
	align-items: center;
	display: flex;
	gap: var(--ppui-nav-gap);
	left: var(--ppui-nav-x);
	margin: var(--ppui-nav-dy) 0 0 var(--ppui-nav-dx);
	position: absolute;
	top: var(--ppui-nav-y);
	transform: translate(var(--ppui-nav-tx), var(--ppui-nav-ty));
	z-index: 5;
}

.propoffice-pui-slider .propoffice-pui-slider__arrow {
	align-items: center;
	background: var(--ppui-nav-bg);
	border: 0;
	color: var(--ppui-nav-color);
	cursor: pointer;
	display: inline-flex;
	height: var(--ppui-nav-size);
	justify-content: center;
	padding: 0;
	transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out;
	width: var(--ppui-nav-size);
}

.propoffice-pui-slider .propoffice-pui-slider__arrow:hover,
.propoffice-pui-slider .propoffice-pui-slider__arrow:focus-visible {
	background: var(--ppui-nav-bg-hover);
	color: var(--ppui-nav-color-hover);
}

.propoffice-pui-slider .propoffice-pui-slider__arrow:focus-visible {
	outline: 3px solid var(--ppui-nav-bg);
	outline-offset: 2px;
}

/*
 * Swiper marks the ends itself. The button stays in the document and stays
 * focusable rather than disappearing, so the control row does not reflow as the
 * visitor reaches either end.
 */
.propoffice-pui-slider .propoffice-pui-slider__arrow.swiper-button-disabled {
	cursor: default;
	opacity: 0.4;
}

.propoffice-pui-slider .propoffice-pui-slider__icon,
.propoffice-pui-slider .propoffice-pui-slider__arrow svg {
	height: var(--ppui-nav-icon-size);
	width: var(--ppui-nav-icon-size);
}

.propoffice-pui-slider .propoffice-pui-slider__arrow i {
	font-size: var(--ppui-nav-icon-size);
	line-height: 1;
}

/*
 * One arrow's own appearance, where it has been given one.
 *
 * Each declaration falls back to the value the pair shares, so a widget that
 * never opens these controls resolves to exactly what it resolved to before
 * they existed. Elementor writes a per-side token only when its control holds a
 * value, which is why those controls ship with no default: a default would make
 * the fallback unreachable and the shared control dead.
 *
 * These sit after the shared rules and match on the same number of classes, so
 * source order is what decides - which is the whole reason they are here rather
 * than beside the rules they override.
 */
.propoffice-pui-slider .propoffice-pui-slider__arrow--prev {
	background: var(--ppui-nav-prev-bg, var(--ppui-nav-bg));
	color: var(--ppui-nav-prev-color, var(--ppui-nav-color));
	height: var(--ppui-nav-prev-size, var(--ppui-nav-size));
	margin: var(--ppui-nav-prev-dy, 0) 0 0 var(--ppui-nav-prev-dx, 0);
	width: var(--ppui-nav-prev-size, var(--ppui-nav-size));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--next {
	background: var(--ppui-nav-next-bg, var(--ppui-nav-bg));
	color: var(--ppui-nav-next-color, var(--ppui-nav-color));
	height: var(--ppui-nav-next-size, var(--ppui-nav-size));
	margin: var(--ppui-nav-next-dy, 0) 0 0 var(--ppui-nav-next-dx, 0);
	width: var(--ppui-nav-next-size, var(--ppui-nav-size));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--prev:hover,
.propoffice-pui-slider .propoffice-pui-slider__arrow--prev:focus-visible {
	background: var(--ppui-nav-prev-bg-hover, var(--ppui-nav-bg-hover));
	color: var(--ppui-nav-prev-color-hover, var(--ppui-nav-color-hover));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--next:hover,
.propoffice-pui-slider .propoffice-pui-slider__arrow--next:focus-visible {
	background: var(--ppui-nav-next-bg-hover, var(--ppui-nav-bg-hover));
	color: var(--ppui-nav-next-color-hover, var(--ppui-nav-color-hover));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--prev:focus-visible {
	outline-color: var(--ppui-nav-prev-bg, var(--ppui-nav-bg));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--next:focus-visible {
	outline-color: var(--ppui-nav-next-bg, var(--ppui-nav-bg));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--prev svg,
.propoffice-pui-slider .propoffice-pui-slider__arrow--prev .propoffice-pui-slider__icon {
	height: var(--ppui-nav-prev-icon-size, var(--ppui-nav-icon-size));
	width: var(--ppui-nav-prev-icon-size, var(--ppui-nav-icon-size));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--next svg,
.propoffice-pui-slider .propoffice-pui-slider__arrow--next .propoffice-pui-slider__icon {
	height: var(--ppui-nav-next-icon-size, var(--ppui-nav-icon-size));
	width: var(--ppui-nav-next-icon-size, var(--ppui-nav-icon-size));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--prev i {
	font-size: var(--ppui-nav-prev-icon-size, var(--ppui-nav-icon-size));
}

.propoffice-pui-slider .propoffice-pui-slider__arrow--next i {
	font-size: var(--ppui-nav-next-icon-size, var(--ppui-nav-icon-size));
}

/* ------------------------------------------------------------- Pagination */

/*
 * The `.swiper-pagination` on the end is not decoration.
 *
 * Swiper's own `.swiper-pagination-bullets.swiper-pagination-horizontal` is two
 * classes and sets `width: 100%; left: 0`. A single class here lost to it, so
 * the dots stretched the full width while the centring transform still pulled
 * them 50% of that width to the left - putting them 600px off the slider on a
 * 1200px layout. Matching its two classes, and coming later, wins cleanly.
 */
.propoffice-pui-slider .propoffice-pui-slider__pagination.swiper-pagination {
	bottom: auto;
	display: flex;
	gap: var(--ppui-dot-gap);
	justify-content: center;
	left: var(--ppui-dot-x);
	margin: var(--ppui-dot-dy) 0 0 var(--ppui-dot-dx);
	position: absolute;
	right: auto;
	top: var(--ppui-dot-y);
	transform: translate(var(--ppui-dot-tx), var(--ppui-dot-ty));
	width: auto;
	z-index: 5;
}

.propoffice-pui-slider .swiper-pagination-bullet {
	background: var(--ppui-dot-color);
	border-radius: 999px;
	height: var(--ppui-dot-size);
	margin: 0;
	opacity: 1;
	transition: background-color 0.15s ease-in-out;
	width: var(--ppui-dot-size);
}

.propoffice-pui-slider .swiper-pagination-bullet-active {
	background: var(--ppui-dot-active-color);
	height: var(--ppui-dot-active-size);
	width: var(--ppui-dot-active-size);
}

.propoffice-pui-slider .swiper-pagination-bullet:focus-visible {
	outline: 3px solid var(--ppui-dot-active-color);
	outline-offset: 2px;
}

/*
 * Swiper draws the fraction and the progress bar itself, from the pagination
 * type it was constructed with. Only the two things it has no opinion about are
 * set here: the colours, and the fact that the container is no longer a row of
 * bullets and must stop behaving like one.
 */
.propoffice-pui-slider .propoffice-pui-slider__pagination--fraction {
	color: var(--ppui-dot-active-color);
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.08em;
}

.propoffice-pui-slider .propoffice-pui-slider__pagination--progressbar {
	background: var(--ppui-dot-color);
	height: 4px;
	width: 60%;
}

.propoffice-pui-slider .propoffice-pui-slider__pagination--progressbar .swiper-pagination-progressbar-fill {
	background: var(--ppui-dot-active-color);
}

/* --------------------------------------------------------------- Counter */

/*
 * Placed by the same anchor-and-translation pair as the navigation and the
 * pagination, and with its own tokens, so moving one never moves another.
 *
 * The counter is printed complete by PHP and only its leading number is
 * rewritten as the slider moves, which is why it reads correctly even on a page
 * that never receives Swiper. It is hidden from assistive technology because
 * Swiper's own accessibility module already announces every slide change.
 */
.propoffice-pui-slider .propoffice-pui-slider__counter {
	align-items: baseline;
	background: var(--ppui-counter-bg);
	color: var(--ppui-counter-color);
	display: flex;
	font-size: 0.875rem;
	font-variant-numeric: tabular-nums;
	gap: 0.4em;
	letter-spacing: 0.12em;
	line-height: 1;
}

.propoffice-pui-slider .propoffice-pui-slider__counter-current {
	color: var(--ppui-counter-active);
	font-size: 1.5em;
	font-weight: 700;
}

.propoffice-pui-slider .propoffice-pui-slider__counter-separator,
.propoffice-pui-slider .propoffice-pui-slider__counter-total {
	opacity: 0.7;
}

@media (prefers-reduced-motion: reduce) {
	.propoffice-pui-slider .propoffice-pui-slider__arrow,
	.propoffice-pui-slider .swiper-pagination-bullet {
		transition: none;
	}
}
