/**
 * Property Search — filter bar and results.
 *
 * Every element here is ours, so unlike map-search.css there is no guessing at
 * someone else's class names and no !important arms race. Cards come from
 * listing-card.css, declared as a stylesheet dependency.
 *
 * Flex, never grid — grid placement breaks inside Elementor (CLAUDE.md §2).
 */

/* The page lock, the header spacer and the wrapper reset all live further down,
   next to the layout they belong to. An unguarded copy of them used to sit here
   as well, and because it came first it beat the desktop-only media query below:
   phones and narrow windows got body{overflow:hidden;height:100vh} over a page
   that stacks to ~11,000px, so the results could not be scrolled to at all. */

.bbis.bbis .bbis-ps__shell {
	--bbis-ps-gap: 16px;
	font-family: var(--bbis-font-body);

	/* Zillow's layout is an app shell, not a long page: the window never
	   scrolls, the map is pinned, and only the results column moves. Sticky
	   positioning cannot do this — it still lets the page scroll past. So the
	   shell claims the viewport below wherever it starts (measured into
	   --bbis-ps-top by the script) and manages its own overflow. */
	display: flex;
	flex-direction: column;
	/* Sit directly beneath a pinned header rather than under it. The height
	   subtracts the same amount, so the shell still ends exactly at the bottom
	   of the viewport and the window never scrolls. */
	margin-top: var(--bbis-ps-header, 0px);
	height: calc(100vh - var(--bbis-ps-top, 0px));
	overflow: hidden;
	/* Break out of the theme's content column. A property search in a boxed
	   740px column wastes the half of the screen the map needs. The scrollbar
	   gutter is measured by property-search.js into --bbis-sbw; without it a
	   raw 100vw overflows and pushes the results off the right edge. */
	width: calc(100vw - var(--bbis-sbw, 0px));
	max-width: calc(100vw - var(--bbis-sbw, 0px));
	margin-left: calc(50% - (100vw - var(--bbis-sbw, 0px)) / 2);
	margin-right: calc(50% - (100vw - var(--bbis-sbw, 0px)) / 2);
}

.bbis.bbis .bbis-ps__title {
	font-family: var(--bbis-font-head);
	font-size: clamp(1.35rem, 1.1rem + 1.1vw, 2rem);
	line-height: 1.15;
	margin: 0 0 18px;
}

/* ------------------------------------------------------------ filter bar

   Two rows: a real search box on top, compact controls under it. The previous
   version put a 2,322-option <select> in front of the visitor, which meant
   hunting for a city instead of typing it — the single worst thing about the
   first build. The box is now a text input backed by a <datalist>, so typing
   filters natively with no JS and no autocomplete library. */

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

.bbis.bbis .bbis-ps__filters {
	/* Every control in this bar shares one height and one radius. The site's
	   --bbis-radius token is 0 on some brands, which would leave the search box
	   and Search button square beside pill-shaped dropdowns — two shapes in one
	   row. The bar defines its own so it is internally consistent regardless of
	   the brand token, which still governs cards and everything below. */
	--ps-h: 40px;
	--ps-r: 999px;

	flex: 0 0 auto;
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: center;
	gap: 8px;
	/* Explicit height, not derived. Padding plus content let the widget's
	   inherited line-height and the theme's form rules inflate the bar to three
	   times this — a locked height cannot be inflated by anything. */
	height: 56px;
	min-height: 56px;
	max-height: 56px;
	padding: 0 clamp(12px, 1.6vw, 20px);
	margin: 0;
	background: var(--bbis-surface);
	border-bottom: 1px solid var(--bbis-border);
	/* No overflow here. `overflow` creates a clipping context, which cut the
	   dropdown panels off at the bar's own edge and made them look like they
	   rendered underneath it. It also made the bar scroll sideways. Controls
	   shrink instead — see the flex-basis on the search box. */
}

.bbis.bbis .bbis-ps__row {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
}

.bbis.bbis .bbis-ps__row--main { gap: 12px; }

/* -------------------------------------------------------- search input */

.bbis.bbis .bbis-ps__search {
	position: relative;
	flex: 1 1 200px;
	max-width: 340px;
	min-width: 130px;
	display: flex;
	align-items: center;
	/* Same height as every sibling, and centred against them explicitly.
	   Relying on flex to size this by content left it a couple of pixels
	   taller than the buttons, which reads as the box sitting lower. */
	height: var(--ps-h);
	align-self: center;
	margin: 0;
	padding: 0;
}

/* The datalist is a real element in the flow; some engines give it a box. */
.bbis.bbis .bbis-ps__search datalist { display: none !important; }

/* Every control forced onto one height. The specificity and !important are
   deliberate: Elementor and the theme both style form fields globally, and a
   single overriding rule anywhere leaves one control taller than its
   neighbours — which reads as the search box sitting lower. */
.bbis.bbis .bbis-ps__filters > * {
	align-self: center;
	margin-top: 0;
	margin-bottom: 0;
}

.bbis.bbis .bbis-ps__filters .bbis-ps__search,
.bbis.bbis .bbis-ps__filters .bbis-ps__search input,
.bbis.bbis .bbis-ps__filters .bbis-ps__dd-btn,
.bbis.bbis .bbis-ps__filters .bbis-ps__submit {
	height: var(--ps-h) !important;
	min-height: var(--ps-h) !important;
	max-height: var(--ps-h) !important;
	line-height: 1 !important;
	margin: 0 !important;
	box-sizing: border-box !important;
}

.bbis.bbis .bbis-ps__filters .bbis-ps__search input { line-height: normal !important; }

.bbis.bbis .bbis-ps__search-icon {
	position: absolute;
	left: 13px;
	width: 17px;
	height: 17px;
	color: var(--bbis-muted);
	pointer-events: none;
}

.bbis.bbis .bbis-ps__search input {
	width: 100%;
	display: block;
	height: var(--ps-h);
	margin: 0;
	padding: 0 34px 0 36px;
	background: var(--bbis-surface);
	border: 1px solid var(--bbis-border);
	border-radius: var(--ps-r);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	/* 16px stops iOS zooming the page when the field takes focus. */
	font-size: 15px;
	line-height: normal;
	-webkit-appearance: none;
	appearance: none;
}

.bbis.bbis .bbis-ps__search input::placeholder { color: var(--bbis-muted); opacity: 1; }

.bbis.bbis .bbis-ps__search input:focus {
	outline: 0;
	border-color: var(--bbis-accent);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--bbis-accent) 26%, transparent);
}

.bbis.bbis .bbis-ps__submit {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	height: var(--ps-h);
	padding: 0 22px;
	border: 0;
	background: var(--bbis-primary);
	color: var(--bbis-primary-fg);
	border-radius: var(--ps-r);
	font-family: var(--bbis-font-head);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: .02em;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: background .18s ease;
}

.bbis.bbis .bbis-ps__submit:hover { background: var(--bbis-primary-hi); }

/* -------------------------------------------------------- dropdown pills

   Filter buttons that open a panel, the Zillow pattern. The button text always
   reflects the current selection, so a closed bar still tells you what is
   filtered — a row of buttons all reading "Price" with results quietly narrowed
   is how people lose track of why they cannot find anything. */

.bbis.bbis .bbis-ps__dd { position: relative; flex: 0 0 auto; }

.bbis.bbis .bbis-ps__dd-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: var(--ps-h);
	padding: 0 15px;
	background: var(--bbis-surface);
	border: 1px solid var(--bbis-border);
	border-radius: var(--ps-r);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: 14px;
	font-weight: 500;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: border-color .15s ease, box-shadow .15s ease;
}

.bbis.bbis .bbis-ps__dd-btn:hover { border-color: var(--bbis-muted); }

.bbis.bbis .bbis-ps__dd.is-open .bbis-ps__dd-btn,
/* A pill carrying a choice looks chosen: tinted fill, brand border, brand text.
   The reference for this is Zillow's bar, where the active facet is obvious at a
   glance instead of being distinguishable only by reading it. */
.bbis.bbis .bbis-ps__dd-btn.is-set {
	border-color: var(--bbis-primary);
	box-shadow: inset 0 0 0 1px var(--bbis-primary);
	/* A tinted fill as well as a border, so an applied filter is obvious at a
	   glance rather than only on close inspection. */
	background: color-mix(in srgb, var(--bbis-primary) 8%, var(--bbis-surface));
	color: var(--bbis-primary);
	font-weight: 600;
}

/* Belt and braces on the search box: centre it against the bar explicitly
   rather than relying on the flex line, which has proved unreliable against
   the theme's own form styling. */
.bbis.bbis .bbis-ps__filters .bbis-ps__search {
	position: relative;
	top: 0;
	align-self: center !important;
	padding: 0 !important;
	border: 0 !important;
}

.bbis.bbis .bbis-ps__chev {
	width: 14px; height: 14px;
	flex: 0 0 auto;
	transition: transform .15s ease;
}

.bbis.bbis .bbis-ps__dd.is-open .bbis-ps__chev { transform: rotate(180deg); }

/* ------------------------------------------------------------- panels */

.bbis.bbis .bbis-ps__dd-panel {
	position: absolute;
	top: calc(100% + 6px);
	left: 0;
	z-index: 500;
	min-width: 300px;
	padding: 18px;
	background: var(--bbis-surface);
	border: 1px solid var(--bbis-border);
	border-radius: var(--bbis-radius);
	box-shadow: 0 12px 34px rgb(0 0 0 / 16%);
}

.bbis.bbis .bbis-ps__dd-panel[hidden] { display: none; }
.bbis.bbis .bbis-ps__dd-panel--narrow { min-width: 168px; padding: 4px; }
.bbis.bbis .bbis-ps__dd-panel--right { left: auto; right: 0; min-width: 215px; padding: 4px; }

.bbis.bbis .bbis-ps__dd-head {
	margin: 0 0 10px;
	font-family: var(--bbis-font-head);
	font-size: .82rem;
	font-weight: 700;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--bbis-muted);
}

.bbis.bbis .bbis-ps__dd-head + .bbis-ps__pills { margin-bottom: 18px; }

/* Single-choice rows: sort, for sale / for rent. */
.bbis.bbis .bbis-ps__dd-panel--narrow .bbis-ps__opt,
.bbis.bbis .bbis-ps__dd-panel--right .bbis-ps__opt { font-size: 14px; }

.bbis.bbis .bbis-ps__opt {
	display: block;
	width: 100%;
	margin: 0;
	padding: 7px 11px;
	line-height: 1.3;
	border: 0;
	background: transparent;
	border-radius: var(--bbis-radius);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: 15px;
	text-align: left;
	cursor: pointer;
	transition: background .12s ease;
}

.bbis.bbis .bbis-ps__opt:hover { background: var(--bbis-border); }

.bbis.bbis .bbis-ps__opt.is-on {
	color: var(--bbis-primary);
	font-weight: 700;
}

/* Beds / baths / property type pills. */
.bbis.bbis .bbis-ps__pills { display: flex; gap: 0; }
.bbis.bbis .bbis-ps__pills--wrap { flex-wrap: wrap; gap: 8px; }

.bbis.bbis .bbis-ps__pill {
	flex: 1 1 0;
	padding: 11px 6px;
	background: var(--bbis-surface);
	border: 1px solid var(--bbis-border);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: 14px;
	font-weight: 500;
	line-height: 1.2;
	white-space: nowrap;
	cursor: pointer;
	transition: background .12s ease, border-color .12s ease;
}

/* A joined segmented row, so it reads as one control not six buttons. */
.bbis.bbis .bbis-ps__pills:not(.bbis-ps__pills--wrap) .bbis-ps__pill + .bbis-ps__pill { margin-left: -1px; }
.bbis.bbis .bbis-ps__pills:not(.bbis-ps__pills--wrap) .bbis-ps__pill:first-child { border-radius: var(--bbis-radius) 0 0 var(--bbis-radius); }
.bbis.bbis .bbis-ps__pills:not(.bbis-ps__pills--wrap) .bbis-ps__pill:last-child { border-radius: 0 var(--bbis-radius) var(--bbis-radius) 0; }
.bbis.bbis .bbis-ps__pills--wrap .bbis-ps__pill { flex: 0 0 auto; border-radius: 999px; padding: 9px 16px; }

.bbis.bbis .bbis-ps__pill:hover { background: var(--bbis-border); }

.bbis.bbis .bbis-ps__pill.is-on {
	background: var(--bbis-primary);
	border-color: var(--bbis-primary);
	color: var(--bbis-primary-fg);
	position: relative;
	z-index: 1;
}

.bbis.bbis .bbis-ps__dd-pair {
	display: flex;
	align-items: flex-end;
	gap: 10px;
}

.bbis.bbis .bbis-ps__dd-pair label { flex: 1 1 0; display: block; margin: 0; }
.bbis.bbis .bbis-ps__dd-dash { padding-bottom: 12px; color: var(--bbis-muted); }

.bbis.bbis .bbis-ps__dd-sub {
	display: block;
	margin-bottom: 5px;
	font-size: .74rem;
	font-weight: 600;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--bbis-muted);
}

.bbis.bbis .bbis-ps__dd-panel select {
	width: 100%;
	padding: 11px 30px 11px 12px;
	background: var(--bbis-surface);
	border: 1px solid var(--bbis-border);
	border-radius: var(--bbis-radius);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: 15px;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
		linear-gradient(135deg, currentColor 50%, transparent 50%);
	background-position: calc(100% - 16px) calc(50% + 1px), calc(100% - 11px) calc(50% + 1px);
	background-size: 5px 5px, 5px 5px;
	background-repeat: no-repeat;
}

.bbis.bbis .bbis-ps__apply {
	display: block;
	width: 100%;
	margin-top: 18px;
	padding: 13px;
	border: 0;
	background: var(--bbis-primary);
	color: var(--bbis-primary-fg);
	border-radius: var(--bbis-radius);
	font-family: var(--bbis-font-head);
	font-size: .92rem;
	font-weight: 700;
	letter-spacing: .03em;
	cursor: pointer;
	transition: background .16s ease;
}

.bbis.bbis .bbis-ps__apply:hover { background: var(--bbis-primary-hi); }

/* ------------------------------------------------- count + sort row */

.bbis.bbis .bbis-ps__meta {
	/* Inside the results column, sticky to its top — Zillow keeps the count and
	   sort visible while the list scrolls under them. */
	position: sticky;
	top: 0;
	z-index: 3;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 12px 0 10px;
	background: var(--bbis-surface);
}

.bbis.bbis .bbis-ps__sort-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	height: 34px;
	margin: 0;
	padding: 0 14px;
	border: 1px solid var(--bbis-border);
	border-radius: 999px;
	background: var(--bbis-surface);
	color: var(--bbis-primary);
	font-family: var(--bbis-font-body);
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	text-decoration: none;
	cursor: pointer;
}

/* The label and the value must render identically — they are one sentence, and
   the theme was styling the inner span differently from the button text. */
.bbis.bbis .bbis-ps__sort-btn span {
	font: inherit;
	color: inherit;
	text-decoration: none;
	letter-spacing: inherit;
}

.bbis.bbis .bbis-ps__sort-btn:hover {
	border-color: var(--bbis-primary);
	color: var(--bbis-primary-hi);
}

.bbis.bbis .bbis-ps__dd--sort.is-open .bbis-ps__sort-btn {
	border-color: var(--bbis-primary);
	box-shadow: inset 0 0 0 1px var(--bbis-primary);
}

.bbis.bbis .bbis-ps__dd-btn:focus-visible,
.bbis.bbis .bbis-ps__sort-btn:focus-visible,
.bbis.bbis .bbis-ps__pill:focus-visible,
.bbis.bbis .bbis-ps__opt:focus-visible,
.bbis.bbis .bbis-ps__apply:focus-visible,
.bbis.bbis .bbis-ps__submit:focus-visible,
.bbis.bbis .bbis-ps__more:focus-visible {
	outline: 3px solid var(--bbis-accent);
	outline-offset: 2px;
}

/* Clear button inside the search box. */
.bbis.bbis .bbis-ps__clear {
	position: absolute;
	right: 9px;
	width: 22px; height: 22px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 0;
	background: var(--bbis-border);
	color: var(--bbis-ink);
	border-radius: 50%;
	font-size: 17px;
	line-height: 1;
	cursor: pointer;
}

.bbis.bbis .bbis-ps__clear[hidden] { display: none; }

@media (max-width: 900px) {
	.bbis.bbis .bbis-ps__dd-panel { min-width: 270px; }
	.bbis.bbis .bbis-ps__dd-panel--right { right: auto; left: 0; }
}

@media (max-width: 600px) {
	/* A panel wider than the phone is worse than a plain list. */
	.bbis.bbis .bbis-ps__dd-panel {
		position: fixed;
		top: auto; bottom: 0; left: 0; right: 0;
		min-width: 0;
		border-radius: var(--bbis-radius) var(--bbis-radius) 0 0;
		box-shadow: 0 -8px 40px rgb(0 0 0 / 28%);
	}
}

/* ------------------------------------------------------------- results */

.bbis.bbis .bbis-ps__count {
	margin: 0;
	padding: 0;
	line-height: 1;
	font-size: .95rem;
	font-family: var(--bbis-font-head);
	font-weight: 700;
	color: var(--bbis-ink);
}

.bbis.bbis .bbis-ps__results {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bbis-ps-gap);
	align-content: flex-start;
	margin: 0;
	padding: 0;
	list-style: none;
	/* Results replace in place; without this the page jumps to the top of a
	   shorter list and the visitor loses their scroll position. */
	min-height: 200px;
}

.bbis.bbis .bbis-ps__results > .bbis-card__item {
	flex: 0 0 100%;
	max-width: 100%;
}

@media (min-width: 700px) {
	.bbis.bbis .bbis-ps__results > .bbis-card__item {
		flex: 0 0 calc(
			(100% - (var(--bbis-ps-cols) - 1) * var(--bbis-ps-gap)) / var(--bbis-ps-cols)
		);
		max-width: calc(
			(100% - (var(--bbis-ps-cols) - 1) * var(--bbis-ps-gap)) / var(--bbis-ps-cols)
		);
	}
}

/* Fading rather than blanking keeps the previous results readable while the
   next set loads, so the layout never collapses mid-search. */
.bbis.bbis .bbis-ps__shell.is-busy .bbis-ps__results {
	opacity: .45;
	transition: opacity .15s ease;
	pointer-events: none;
}

.bbis.bbis .bbis-ps__counts { min-width: 0; }

/* The same action in the bar itself, at the end of the row. */
/* The sale/rent pill always represents a decision, so it always reads as one.

   Targeted by an explicit class, not :first-of-type — that matches the first
   <div> among siblings, which is the search box, so the rule matched nothing at
   all. The same mistake cost an hour on the gallery. */
.bbis.bbis .bbis-ps__dd--status .bbis-ps__dd-btn {
	background: color-mix(in srgb, var(--bbis-primary) 8%, #fff);
	border-color: var(--bbis-primary);
	color: var(--bbis-primary);
	font-weight: 700;
}

.bbis.bbis .bbis-ps__dd--status .bbis-ps__dd-btn svg { stroke: var(--bbis-primary); }

.bbis.bbis .bbis-ps__savebar {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	flex: 0 0 auto;
	/* Hard right, away from the filters. It acts on the whole search rather
	   than being another facet, so it should not sit in the row of facets. */
	margin-left: auto;
	height: var(--ps-h);
	padding: 0 16px;
	background: transparent;
	border: 1px solid var(--bbis-border);
	border-radius: var(--ps-r);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: .88rem;
	font-weight: 600;
	white-space: nowrap;
	cursor: pointer;
}

.bbis.bbis .bbis-ps__savebar:hover { border-color: var(--bbis-ink); }
.bbis.bbis .bbis-ps__savebar.is-busy { opacity: .55; pointer-events: none; }

.bbis.bbis .bbis-ps__savebar svg {
	width: 16px;
	height: 16px;
	fill: none;
	stroke: var(--bbis-accent);
	stroke-width: 2;
	stroke-linejoin: round;
}

.bbis.bbis .bbis-ps__savebar.is-on svg { fill: var(--bbis-accent); }

/* Below this the bar scrolls sideways; the label would eat the room the
   filters need, so only the heart remains. */
@media (max-width: 900px) {
	.bbis.bbis .bbis-ps__savebar span { display: none; }
	.bbis.bbis .bbis-ps__savebar { padding: 0 12px; }
}





@media (max-width: 600px) {
	/* The same action in the bar itself, at the end of the row. */
.bbis.bbis .bbis-ps__savebar {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	flex: 0 0 auto;
	/* Hard right, away from the filters. It acts on the whole search rather
	   than being another facet, so it should not sit in the row of facets. */
	margin-left: auto;
	height: var(--ps-h);
	padding: 0 16px;
	background: transparent;
	border: 1px solid var(--bbis-border);
	border-radius: var(--ps-r);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: .88rem;
	font-weight: 600;
	white-space: nowrap;
	cursor: pointer;
}

.bbis.bbis .bbis-ps__savebar:hover { border-color: var(--bbis-ink); }
.bbis.bbis .bbis-ps__savebar.is-busy { opacity: .55; pointer-events: none; }

.bbis.bbis .bbis-ps__savebar svg {
	width: 16px;
	height: 16px;
	fill: none;
	stroke: var(--bbis-accent);
	stroke-width: 2;
	stroke-linejoin: round;
}

.bbis.bbis .bbis-ps__savebar.is-on svg { fill: var(--bbis-accent); }

/* Below this the bar scrolls sideways; the label would eat the room the
   filters need, so only the heart remains. */
@media (max-width: 900px) {
	.bbis.bbis .bbis-ps__savebar span { display: none; }
	.bbis.bbis .bbis-ps__savebar { padding: 0 12px; }
}

}

.bbis.bbis .bbis-ps__note {
	margin: 3px 0 0;
	color: var(--bbis-muted);
	font-size: .84rem;
	line-height: 1.35;
}

.bbis.bbis .bbis-ps__note[hidden] { display: none; }

.bbis.bbis .bbis-ps__empty {
	padding: 48px 24px;
	margin: 0;
	color: var(--bbis-muted);
	text-align: center;
	font-size: 1.02rem;
	line-height: 1.5;
}

/* An empty result set keeps the split.

   A previous attempt stacked them — flex-direction:column with the map ordered
   last. It made things worse: the results column still had flex-grow, so it
   stretched to the full height of the shell and pushed the map off the bottom
   of the screen behind a screenful of white. Leaflet had also already measured
   itself against the old width, so the tiles only painted across part of the
   new frame.

   Keeping the map where it is means nothing moves and nothing needs
   remeasuring, and the message reads as the answer to the search rather than a
   collapse. It is what Zillow does with no matches too. */

.bbis.bbis .bbis-ps__shell.is-empty .bbis-ps__empty {
	padding-top: clamp(40px, 12vh, 120px);
}

.bbis.bbis .bbis-ps__more {
	display: block;
	margin: 22px auto 0;
	padding: 13px 34px;
	background: transparent;
	color: var(--bbis-primary);
	border: 2px solid var(--bbis-primary);
	border-radius: var(--bbis-radius);
	font-family: var(--bbis-font-head);
	font-weight: 700;
	letter-spacing: .05em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background .18s ease, color .18s ease;
}

.bbis.bbis .bbis-ps__more:hover {
	background: var(--bbis-primary);
	color: var(--bbis-primary-fg);
}

.bbis.bbis .bbis-ps__more[hidden] { display: none; }

/* Left over from the pre-Zillow bar: .bbis-ps__field and its modifiers no
   longer exist in the markup, and the rules that did still match were actively
   wrong for a bar that now scrolls sideways — a Search button at flex 1 1 100%
   would have stretched to the full width of the row. */

@media (max-width: 600px) {
	.bbis.bbis .bbis-ps__filters { padding: 0 12px; }
}

@media (prefers-reduced-motion: reduce) {
	.bbis.bbis .bbis-ps__submit,
	.bbis.bbis .bbis-ps__more,
	.bbis.bbis .bbis-ps__results { transition: none; }
}

/* ------------------------------------------------- map + results layout

   The Zillow shape: map fixed on the left, results scrolling on the right.
   Below the breakpoint they stack, map first — on a phone a map you cannot
   see is worse than no map, and a short one above the list still orients you.

   Flex, not grid, per CLAUDE.md §2. */

.bbis.bbis .bbis-ps__layout {
	flex: 1 1 auto;
	display: flex;
	gap: 0;
	align-items: stretch;
	/* Fill every pixel the shell has left. Without this the layout sizes to its
	   content and leaves a white strip under the map. */
	height: 100%;
	/* Without min-height:0 a flex child refuses to shrink below its content,
	   so the column never gets its own scrollbar and the page scrolls instead. */
	min-height: 0;
}

/* The wrapper is the flex child now, not the map.

   The map used to be sized directly by the layout — `flex: 0 0 45%` with
   `height: 100%`. Putting the draw controls beside it meant wrapping it, which
   orphaned it from the flex container: the basis stopped applying and the
   height resolved against a parent that had none, so the map collapsed to
   nothing and the page rendered with no map at all.

   The sizing therefore belongs on the wrapper, and the map fills it. */
.bbis.bbis .bbis-ps__mapwrap {
	position: relative;
	flex: 0 0 45%;
	height: 100%;
	min-height: 0;
}

.bbis.bbis .bbis-ps__map {
	width: 100%;
	height: 100%;
	min-height: 0;
	border: 0;
	border-radius: 0;
	overflow: hidden;
	background: var(--bbis-border);
	z-index: 0; /* keep Leaflet panes under the site header */
}

.bbis.bbis .bbis-ps__col {
	flex: 0 0 55%;
	min-width: 0;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: 0 clamp(12px, 1.6vw, 20px) 24px;
}

/* ---------------------------------------------------- lock the page

   The shell fills the viewport, so any content after it is reachable only by
   scrolling a full-screen application off the top. Zillow does not put a footer
   on its search page for exactly this reason.

   Desktop only, and that is the whole point. This block was previously nested
   inside the max-width:900px query below, so the lock applied on phones and
   nowhere else — which is precisely backwards. On a phone the panes are
   stacked and the page is meant to scroll normally; locking the body to 100vh
   with overflow:hidden meant the results simply could not be reached.

   Scoped with :has() so it applies on pages containing the search and nowhere
   else. The footer is hidden rather than deleted, so nothing is lost — turning
   the module off restores it. */

@media (min-width: 901px) {

	body:has(.bbis-ps--tight) {
		overflow: hidden;
		height: 100vh;
	}

	body:has(.bbis-ps--tight) .site-footer,
	body:has(.bbis-ps--tight) footer,
	body:has(.bbis-ps--tight) [class*="elementor-location-footer"] {
		display: none !important;
	}
}

/* ---------------------------------------------- reclaim the header spacer

   Themes with a fixed header insert a spacer element to reserve room for it —
   smart-header-reveal does this in JavaScript, so it never appears in the page
   source and cannot be found by inspecting the server response. On a normal
   page that spacer is correct. Above a viewport-height app shell it is ~100px
   of dead white before anything starts.

   Opt-in via the module setting, because collapsing it slides the search under
   a header that may be transparent at the top of the page. */

.bbis-ps--tight ~ .shr-spacer,
body:has(.bbis-ps--tight) .shr-spacer { display: none !important; }

/* ------------------------------------------------ neutralise the wrappers

   The search is a viewport-height app shell, so any padding on the elements
   between the page and it shows up as dead space above the bar and a gap below.
   The real chain on an Elementor page is:

     .page-content            theme padding
       .e-con                 container padding
         .elementor-widget    default widget bottom margin
           .elementor-widget-container
             .bbis-ps

   Zeroing the container in the page's own settings only handled one of those.
   These rules reach up with :has(), so they apply on pages containing the
   search and nowhere else — no global theme surgery. */

.bbis.bbis.bbis-ps { margin: 0; padding: 0; }

:where(.elementor-widget-container):has(> .bbis-ps),
:where(.elementor-widget):has(.bbis-ps),
:where(.e-con, .elementor-element):has(> * > .bbis-ps) {
	margin: 0 !important;
	padding: 0 !important;
}

:where(.page-content, .site-main, .bn-wrap):has(.bbis-ps) {
	padding-top: 0 !important;
	padding-bottom: 0 !important;
	margin-top: 0 !important;
	margin-bottom: 0 !important;
}

/* Below this the split stops being useful: half a phone screen of map and half
   of results is two unusable panes. Stack them and let the page scroll normally. */

@media (max-width: 900px) {

	.bbis.bbis .bbis-ps__shell {
		height: auto;
		overflow: visible;
	}

	.bbis.bbis .bbis-ps__layout { flex-direction: column; }

	.bbis.bbis .bbis-ps__mapwrap {
		flex: 1 1 auto;
		height: 320px;
	}

	.bbis.bbis .bbis-ps__map { height: 100%; }

	.bbis.bbis .bbis-ps__col {
		flex: 1 1 auto;
		overflow-y: visible;
		padding: 0 clamp(16px, 3vw, 32px) 40px;
	}

	/* The filter bar scrolls sideways rather than cutting off at whichever pill
	   happens to reach the edge — Beds & baths, on a phone.

	   On desktop this bar deliberately has no overflow, because `overflow`
	   creates a clipping context and the dropdown panels were being sliced off
	   at the bar's own edge. That does not apply here: below this width the
	   panels are fixed-position sheets anchored to the bottom of the screen, so
	   they are not inside the clipping context at all and there is nothing left
	   to clip. */
	.bbis.bbis .bbis-ps__filters {
		overflow-x: auto;
		overflow-y: visible;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}

	.bbis.bbis .bbis-ps__filters::-webkit-scrollbar { display: none; }

	/* Keep their natural size — squeezed pills would defeat the scrolling. */
	.bbis.bbis .bbis-ps__filters > * { flex-shrink: 0; }

	.bbis.bbis .bbis-ps__search { flex: 0 0 210px; max-width: none; }

	/* Sheets, so nothing depends on the bar not clipping. */
	.bbis.bbis .bbis-ps__dd-panel,
	.bbis.bbis .bbis-ps__dd-panel--right {
		position: fixed;
		top: auto;
		bottom: 0;
		left: 0;
		right: 0;
		min-width: 0;
		max-height: 72vh;
		overflow-y: auto;
		border-radius: var(--bbis-radius) var(--bbis-radius) 0 0;
		box-shadow: 0 -8px 40px rgb(0 0 0 / 28%);
	}
}

/* ---------------------------------------------------------------- pins */

.bbis.bbis .bbis-ps__pin { background: none; border: 0; }

/* The label sits above the coordinate with a tail pointing down at it, so it
   marks a house rather than floating near one. The extra 7px of lift is the
   tail's height — without it the tip lands 7px below the property. */

.bbis.bbis .bbis-ps__pin-label {
	position: relative;
	display: inline-block;
	padding: 4px 9px;
	background: var(--bbis-primary);
	color: var(--bbis-primary-fg);
	border-radius: var(--bbis-radius);
	font-family: var(--bbis-font-head);
	font-size: 12px;
	font-weight: 700;
	line-height: 1.2;
	white-space: nowrap;
	filter: drop-shadow(0 2px 4px rgb(0 0 0 / 35%));
	cursor: pointer;
	transform: translate(-50%, calc(-100% - 7px));
	transition: background .15s ease;
}

/* Drawn with borders rather than a rotated square: a rotated square needs its
   own shadow clipped off, and drop-shadow on the parent wraps this shape for
   free — which is why the box-shadow above became a filter. */
.bbis.bbis .bbis-ps__pin-label::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 100%;
	width: 0;
	height: 0;
	transform: translateX(-50%);
	border: 7px solid transparent;
	border-bottom: 0;
	border-top-color: var(--bbis-primary);
	transition: border-top-color .15s ease;
}

.bbis.bbis .bbis-ps__pin:hover { z-index: 400 !important; }

.bbis.bbis .bbis-ps__pin:hover .bbis-ps__pin-label {
	background: var(--bbis-accent);
	color: var(--bbis-accent-fg);
}

.bbis.bbis .bbis-ps__pin:hover .bbis-ps__pin-label::after {
	border-top-color: var(--bbis-accent);
}

/* Leaflet's own attribution must stay legible and must not be hidden —
   the tile licences require it. */
.bbis.bbis .bbis-ps__map .leaflet-control-attribution {
	font-size: 10px;
	background: rgb(255 255 255 / 82%);
}

@media (prefers-reduced-motion: reduce) {
	.bbis.bbis .bbis-ps__pin-label { transition: none; }
}

/* The hidden-state wrapper must never occupy space. `hidden` alone loses to the
   flex display rules above it. */
.bbis.bbis .bbis-ps__state { display: none !important; }

/* Any paragraph wpautop still manages to inject into the bar is inert. Belt and
   braces: the markup no longer gives it anything to wrap, but this bar must
   never again be laid out around an element nobody authored. */
.bbis.bbis .bbis-ps__filters > p:empty,
.bbis.bbis .bbis-ps__filters > p { display: contents; margin: 0; }

/* --------------------------------------------------------- MLS attribution

   Required on a results page by the IDX licence. This page hides the site
   footer, so without this the disclaimer would appear nowhere at all. Muted,
   never hidden, and it scrolls with the results rather than being pinned —
   pinning it would take space from the listings on every screen. */

.bbis.bbis .bbis-ps__legal {
	margin-top: 28px;
	padding-top: 18px;
	border-top: 1px solid var(--bbis-border);
	color: var(--bbis-muted);
	font-size: .72rem;
	line-height: 1.55;
}

.bbis.bbis .bbis-ps__legal img {
	max-width: 160px;
	height: auto;
	margin-bottom: 8px;
	display: block;
}

.bbis.bbis .bbis-ps__legal p { margin: 0 0 6px; }

/* ================================================== map: clusters + draw ==

   The cluster bubble is styled here rather than loading the plugin's own
   MarkerCluster.Default.css, which ships a green-amber-red traffic-light
   palette. That would put three colours nobody chose on every site in the
   fleet, on the one element the eye goes to first. */

.bbis.bbis .bbis-ps__cluster {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 38px;
	height: 38px;
	background: var(--bbis-primary);
	color: var(--bbis-primary-fg);
	border: 2px solid #fff;
	border-radius: 50%;
	box-shadow: 0 2px 8px rgb(0 0 0 / 32%);
	font-family: var(--bbis-font-body);
	font-size: .82rem;
	font-weight: 700;
	transform: translate(-50%, -50%);
}

/* Bigger groups read as bigger circles — the size carries the count before
   the number is read. */
.bbis.bbis .bbis-ps__cluster.is-mid { width: 46px; height: 46px; font-size: .88rem; }
.bbis.bbis .bbis-ps__cluster.is-big {
	width: 56px;
	height: 56px;
	font-size: .95rem;
	background: var(--bbis-accent);
	color: var(--bbis-accent-fg);
}

.bbis.bbis .bbis-ps__draw {
	position: absolute;
	top: 12px;
	right: 12px;
	/* Above the map, below the filter panels.

	   This was 500 to clear Leaflet's controls — which was unnecessary, because
	   those live inside .bbis-ps__map and its z-index: 0 traps them there. What
	   500 actually did was tie with the filter dropdowns, and on a tie the later
	   element in the document wins: the map comes after the filter bar, so Price
	   and Beds & baths opened underneath these buttons. */
	z-index: 2;
	display: flex;
	gap: 8px;
}

.bbis.bbis .bbis-ps__drawbtn {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 9px 14px;
	background: var(--bbis-surface);
	color: var(--bbis-ink);
	border: 1px solid var(--bbis-border);
	border-radius: 999px;
	box-shadow: 0 2px 10px rgb(0 0 0 / 20%);
	font-family: var(--bbis-font-body);
	font-size: .84rem;
	font-weight: 700;
	cursor: pointer;
	transition: background .15s ease, color .15s ease;
}

.bbis.bbis .bbis-ps__drawbtn svg { width: 15px; height: 15px; }

.bbis.bbis .bbis-ps__drawbtn:hover,
.bbis.bbis .bbis-ps__drawbtn.is-on {
	background: var(--bbis-accent);
	color: var(--bbis-accent-fg);
	border-color: var(--bbis-accent);
}

/* Crosshair while drawing, and Leaflet's grab cursor suppressed — the map is
   not draggable in this mode and a grab hand would say it is. */
.bbis.bbis .bbis-ps__map.is-drawing,
.bbis.bbis .bbis-ps__map.is-drawing .leaflet-grab { cursor: crosshair; }

/* -------------------------------------------------- search this area ---- */

.bbis.bbis .bbis-ps__redo {
	position: absolute;
	top: 12px;
	left: 50%;
	z-index: 2;
	transform: translateX(-50%);
}

.bbis.bbis .bbis-ps__redobtn {
	padding: 10px 20px;
	background: var(--bbis-primary);
	color: var(--bbis-primary-fg);
	border: 0;
	border-radius: 999px;
	box-shadow: 0 3px 14px rgb(0 0 0 / 30%);
	font-family: var(--bbis-font-body);
	font-size: .86rem;
	font-weight: 700;
	cursor: pointer;
	transition: background .15s ease;
}

.bbis.bbis .bbis-ps__redobtn:hover { background: var(--bbis-primary-hi); }
.bbis.bbis .bbis-ps__redo[hidden] { display: none; }

/* The card a pin points at, flashed after it scrolls into view. An outline
   rather than a colour wash: it has to be obvious over any photograph. */
.bbis.bbis .bbis-card__item.is-flash .bbis-card {
	outline: 3px solid var(--bbis-accent);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
	.bbis.bbis .bbis-card__item.is-flash .bbis-card {
		transition: outline-color .25s ease;
	}
}

/* Search-as-I-move toggle. Sits under the draw controls rather than beside
   them: it governs the map's behaviour rather than doing something, and a
   checkbox in a row of buttons reads as a fourth button. */
.bbis.bbis .bbis-ps__auto {
	position: absolute;
	top: 58px;
	right: 12px;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 7px 12px;
	background: var(--bbis-surface);
	border: 1px solid var(--bbis-border);
	border-radius: 999px;
	box-shadow: 0 2px 10px rgb(0 0 0 / 18%);
	color: var(--bbis-ink);
	font-family: var(--bbis-font-body);
	font-size: .78rem;
	font-weight: 600;
	cursor: pointer;
	user-select: none;
}

.bbis.bbis .bbis-ps__auto input {
	width: 14px;
	height: 14px;
	margin: 0;
	accent-color: var(--bbis-accent);
	cursor: pointer;
}

@media (max-width: 900px) {
	/* The controls stack on a phone and three floating chips is most of the
	   map, so the wording shortens rather than the toggle disappearing. */
	.bbis.bbis .bbis-ps__auto { top: 52px; font-size: .72rem; padding: 6px 10px; }
}
