/**
 * Realist — STRUCTURE layer.
 *
 * Functional CSS only: rules whose absence doesn't make the plugin ugly, it makes
 * it BROKEN (dead click targets, a visible honeypot, distorted photos, missing
 * loading feedback). This file always loads and must not be dequeued.
 *
 * Anything purely presentational belongs in frontend-skin.css.
 */

/* ---------- Filter bar ---------- */
.realist-filter-bar { display: flex; flex-wrap: wrap; }
.realist-filter-group { flex: 1 1 200px; display: flex; flex-direction: column; }
.realist-filter-group select,
.realist-filter-group input[type="number"],
.realist-filter-group input[type="text"] { width: 100%; }
.realist-filter-range { display: flex; }
.realist-filter-range > * { flex: 1 1 0; min-width: 0; }
.realist-filter-checks { display: flex; flex-wrap: wrap; }
.realist-filter-checks label { display: inline-flex; align-items: center; }

/* Availability toggle: All ↔ Available. The native checkbox is visually
   replaced by the track/thumb but kept in the layout (off-screen) so it stays
   keyboard-operable and focusable — losing it would break accessibility. */
.realist-toggle { display: inline-flex; align-items: center; }
.realist-toggle-input { position: absolute; width: 1px; height: 1px; opacity: 0; margin: 0; }
.realist-toggle-track { position: relative; flex: 0 0 auto; }
.realist-toggle-thumb { position: absolute; top: 50%; transform: translateY( -50% ); }

/* ---------- Grid & loading state ---------- */
.realist-index-body { position: relative; } /* positioning context for the loader */
.realist-grid-container {
	display: grid;
	/* --realist-index-columns defaults to auto-fill (responsive by card width);
	   a style variation can set a fixed count (e.g. 3) instead. Card min-width
	   and the count are both variation-settable via theme.json custom props. */
	grid-template-columns: repeat(
		var( --realist-index-columns, var( --wp--custom--realist--index--columns, auto-fill ) ),
		minmax( var( --realist-card-min, var( --wp--custom--realist--index--card-min, 320px ) ), 1fr )
	);
	min-height: 200px;
}
.realist-grid-container.is-loading { opacity: 0.5; pointer-events: none; }
.realist-loader {
	display: none;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate( -50%, -50% );
	animation: realist-spin 1s linear infinite;
}
#realist-property-grid.is-loading + .realist-loader { display: block; }
@keyframes realist-spin {
	0%   { transform: translate( -50%, -50% ) rotate( 0deg ); }
	100% { transform: translate( -50%, -50% ) rotate( 360deg ); }
}

/* ---------- Card ---------- */
.realist-property-card { position: relative; display: flex; flex-direction: column; overflow: hidden; }
/* Stretched link: the title's anchor covers the whole card, so the card stays
   fully clickable AND the one crawlable link carries the property address as its
   anchor text. Without the ::after the card is dead (no click target). */
.realist-card-link { text-decoration: none; color: inherit; }
.realist-card-link::after { content: ""; position: absolute; top: 0; left: 0; right: 0; bottom: 0; z-index: 10; }
.realist-card-image {
	position: relative;
	width: 100%;
	padding-top: var( --realist-card-ratio, 66.66% ); /* reserves aspect ratio, prevents layout shift */
	overflow: hidden;
}
.realist-card-image img { position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover; }
.realist-card-badge { position: absolute; top: 15px; right: 15px; z-index: 2; }
.realist-card-content { display: flex; flex-direction: column; flex-grow: 1; }
/* Title + price share a row; if either is long the price wraps to its own line
   instead of overflowing or crushing the title. */
.realist-card-header-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; }
.realist-card-meta { display: flex; }
.realist-no-results { grid-column: 1 / -1; }

/* wpautop can leave a stray trailing <p> after the map embed; that margin
   breaks the wrapper box. */
.realist-map-wrapper p:last-child { margin: 0 !important; }

/* ---------- Feature tags ---------- */
.realist-features-tags { display: flex; flex-wrap: wrap; }

/* ---------- Single property: sidebar & actions ---------- */
.realist-sidebar p { display: flex; align-items: baseline; }
.realist-sidebar i.fa { width: 25px; text-align: center; }
.realist-badge { display: inline-block; }
.realist-action-buttons { display: flex; flex-wrap: wrap; }
.realist-action-btn { display: inline-flex; align-items: center; justify-content: center; flex: 1 1 auto; }
/* Extra gallery files are collected by GLightbox at init but never shown as
   their own buttons — they're reached via the carousel behind the one button. */
.realist-gallery-hidden { display: none; }

@media ( max-width: 600px ) {
	.realist-action-buttons { flex-direction: column; }
	.realist-action-btn { width: 100%; }
}

/* ---------- Carousel ---------- */
.realist-property-carousel { width: 100%; }
.realist-property-carousel .splide__slide img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	aspect-ratio: 3 / 2;
}

/* ---------- Lead form ----------
 * A flex-wrap layout whose column count is a single custom property, so a theme
 * (or a block style variation) switches single- vs multi-column by setting
 * --realist-form-columns alone. Flex is used rather than grid on purpose: a
 * short field left orphaned on an incomplete row grows to fill it (so Name +
 * Email pair up, a leftover Phone becomes full-width) — grid would leave it as a
 * half-width stub. :where() keeps specificity at zero so themes/Global Styles win.
 */
:where( .realist-lead-form ) {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var( --realist-form-gap, var( --wp--custom--realist--form--gap, 1rem ) );
}
/* Default: every direct child takes a whole row. */
:where( .realist-lead-form ) > * { flex: 1 1 100%; min-width: 0; }
/* Short fields share rows N-up; flex-grow lets an orphan fill its row.
   Precedence for the column count: a per-form block style variation (sets
   --realist-form-columns) wins; else the theme default from theme.json
   (--wp--custom--realist--form--columns); else single column. */
:where( .realist-lead-form ) .realist-lead-field {
	--realist-form-cols: var( --realist-form-columns, var( --wp--custom--realist--form--columns, 1 ) );
	flex: 1 1 calc( ( 100% - ( var( --realist-form-cols ) - 1 ) * var( --realist-form-gap, var( --wp--custom--realist--form--gap, 1rem ) ) ) / var( --realist-form-cols ) );
}
/* Large / structural fields always take the whole row. */
:where( .realist-lead-form ) .realist-lead-field--wide,
:where( .realist-lead-form ) .realist-lead-consent { flex: 1 1 100%; }

/* Fields are <p> elements, so the UA's 1em block margin would stack on top of the
   flex gap above — doubling the row pitch and pushing the submit button out of
   line with the fields it sits beside. Spacing here is the gap's job alone. */
.realist-lead-field { display: flex; flex-direction: column; margin: 0; }
.realist-lead-field input[type="text"],
.realist-lead-field input[type="email"],
.realist-lead-field input[type="tel"],
.realist-lead-field input[type="number"],
.realist-lead-field input[type="datetime-local"],
.realist-lead-field select,
.realist-lead-field textarea { width: 100%; font: inherit; }
.realist-lead-consent { flex-direction: row; }
.realist-lead-consent label { display: flex; align-items: flex-start; }
/* The status message is rendered up front so it can be an aria-live region, but
   it is empty until a submit resolves. As a full-width flex child it would then
   reserve a blank row (its skin padding plus a gap) above every untouched form —
   and in a single-row layout it would push the submit onto its own line. Drop it
   from the flow while empty; it returns the moment the script writes into it. */
:where( .realist-lead-message:empty ) { display: none; }

/* ---------- Form controls inherit the page's typeface ----------
 * Browsers do not inherit font-family into form controls: the UA stylesheet
 * gives button/input/select/textarea its own system font, so every other Realist
 * element picks up the theme's typography for free and these silently do not.
 * It shows up as one stray Arial button in an otherwise correctly-typeset form,
 * and a theme is unlikely to catch it — the Realist theme's own base rule lists
 * `input, select, textarea` but not `button`, which is exactly how the lead
 * form's submit ended up as Arial on a Poppins site.
 *
 * Only the family is set. `font: inherit` would also reset size and weight,
 * wiping the skin layer's per-control values (this file loads before the skin,
 * but these selectors outrank its zero-specificity :where() rules).
 */
.realist-lead-submit,
.realist-load-more-btn,
.realist-filter-group select,
.realist-filter-group input,
.realist-filter-checks input { font-family: inherit; }

/* ---------- Property video (oEmbed) ---------- */
.realist-property-video { position: relative; }
.realist-property-video iframe,
.realist-property-video video { width: 100%; aspect-ratio: 16 / 9; height: auto; display: block; border: 0; }

/* ---------- Building / divider gallery ---------- */
.realist-divider-carousel .splide__slide img {
	display: block;
	width: 100%;
	height: var( --realist-divider-height, 220px );
	object-fit: cover;
}

/* ---------- Agent card ---------- */
.realist-agent-card { display: flex; gap: 1rem; align-items: flex-start; }
.realist-agent-photo-wrap { flex: 0 0 auto; }
.realist-agent-body { flex: 1 1 auto; min-width: 0; }
.realist-agent-card p { margin: 0.15rem 0; }

/* Honeypot: must stay visually hidden or real users see it and the spam trap inverts. */
.realist-lead-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Feedback visibility is behaviour, not decoration. */
.realist-lead-message { display: none; }
.realist-lead-message.is-error,
.realist-lead-message.is-success { display: block; }
