/* Event passthrough for popup overlays.
 *
 * The popup container (`rmaps-popup-passthrough`) is set to
 * `pointer-events: none` in JS so the popup is EVENT-TRANSPARENT:
 * clicks / wheel / touch / hover land on the layer underneath (the
 * GL canvas or the Google tile pane), which means dragging or
 * pinching directly on a popup pans / zooms the map natively as if
 * the popup weren't there. This is the cleanest way to make the
 * popup behave like a visual overlay without rebuilding the engines'
 * gesture handlers on top of forwarded touch events.
 *
 * Interactive descendants (close X, links, buttons, form fields,
 * route step list, slider arrows) need to capture their own clicks
 * and key events, so we explicitly re-enable `pointer-events: auto`
 * for them below. The `.rmaps-react-infowindow-content--has-scroll`
 * branch keeps wheel-scroll + touch-scroll working when the popup
 * content overflows; the modifier class is added by PopupCard's
 * ResizeObserver only while the body genuinely overflows, so short
 * popups stay fully event-transparent. */
.rmaps-popup-passthrough a,
.rmaps-popup-passthrough button,
.rmaps-popup-passthrough input,
.rmaps-popup-passthrough textarea,
.rmaps-popup-passthrough select,
.rmaps-popup-passthrough label,
.rmaps-popup-passthrough [role="button"],
.rmaps-popup-passthrough .MuiIconButton-root,
.rmaps-popup-passthrough form,
.rmaps-popup-passthrough .rmaps-popup__slider-btn,
.rmaps-popup-passthrough .rmaps-popup__directions-btn,
.rmaps-popup-passthrough .rmaps-popup__images--slider,
.rmaps-popup-passthrough .rmaps-popup__slider-track,
.rmaps-popup-passthrough .rmaps-react-infowindow-content--has-scroll {
	pointer-events: auto;
}

/* Listing content — server-emitted HTML inside `.rmaps-listing-content`.
 * Same wrapper class on BOTH the popup body AND the sidebar listing
 * cards, so every formatting rule below applies to both contexts.
 * The popup carries an additional wrapper class
 * `.rmaps-react-infowindow-content` which scopes the popup-only
 * scrollbar + right-edge gutter (block further down); sidebar cards
 * don't have that class, so they don't pick up the popup chrome.
 *
 * Force the default arrow cursor so the map's grab cursor doesn't
 * bleed through the popup overlay. Buttons/links opt back into
 * pointer below. */
.rmaps-listing-content,
.rmaps-listing-content * {
	cursor: default;
}
/* Vertical rhythm between the popup-field rows. Each row's own
 * `.rmaps-popup__field` already has `margin: 0`, so without an
 * explicit gap on the parent stack the icon column rows sit flush
 * against each other and the "Email", "Phone", "Address" lines run
 * together. Flex column with `gap: 8px` gives a consistent
 * inter-row breathing space that matches the in-row icon/value
 * gap declared on `.rmaps-popup__field`. Applies in both contexts
 * the class wraps — popup card body AND sidebar listing card —
 * because the markup is identical between the two surfaces. */
.rmaps-listing-content {
	display: flex;
	flex-direction: column;
	gap: 8px;
}
.rmaps-listing-content a,
.rmaps-listing-content button,
.rmaps-listing-content [role="button"] {
	cursor: pointer;
}
.rmaps-listing-content input,
.rmaps-listing-content textarea,
.rmaps-listing-content select {
	cursor: text;
}
.rmaps-listing-content input[type="checkbox"],
.rmaps-listing-content input[type="radio"] {
	cursor: pointer;
}

/* Popup-only scrollbar + right-edge gutter. The sidebar card has
 * its own scroll context (`.rmaps-react-sidebar__scroll`) and does
 * NOT need either the padding gutter or a custom scrollbar inside
 * the card itself — these rules stay scoped to the popup wrapper.
 * Popup body has BOTH classes (`rmaps-react-infowindow-content
 * rmaps-listing-content`); sidebar card has only `rmaps-listing-content`.
 *
 * Win 11–style thin scrollbar that thickens on hover. The container
 * width is always 14 px; the thumb sits inside a transparent border
 * that we shrink on hover so the thumb appears to expand smoothly
 * without the layout reflowing. Firefox honours scrollbar-width /
 * -color but cannot animate the width. */
.rmaps-react-infowindow-content {
	scrollbar-width: thin;
	scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
	/* Scrollbar gutter is conditional — see the
	   `--has-scroll` rule near the bottom of this file for the
	   4 px right padding that kicks in only when the body actually
	   overflows. Without overflow we'd otherwise carry a visible
	   asymmetric gap on the right edge of every popup. */
}
.rmaps-react-infowindow-content::-webkit-scrollbar { width: 14px; height: 14px; }
.rmaps-react-infowindow-content::-webkit-scrollbar-track,
.rmaps-react-infowindow-content::-webkit-scrollbar-corner { background: transparent; }
.rmaps-react-infowindow-content::-webkit-scrollbar-thumb {
	background-color: rgba(0, 0, 0, 0.2);
	background-clip: padding-box;
	border: 5px solid transparent;
	border-radius: 7px;
	-webkit-transition: border-width 0.18s ease, background-color 0.18s ease;
	transition: border-width 0.18s ease, background-color 0.18s ease;
}
.rmaps-react-infowindow-content:hover::-webkit-scrollbar-thumb {
	border-width: 3px;
	background-color: rgba(0, 0, 0, 0.32);
}
.rmaps-react-infowindow-content::-webkit-scrollbar-thumb:hover {
	background-color: rgba(0, 0, 0, 0.5);
	border-width: 2px;
}
.rmaps-listing-content .rmaps-popup {
	display: flex;
	flex-direction: column;
	gap: 10px;
	font-size: 13px;
	color: #1f2937;
}
.rmaps-listing-content .rmaps-popup__title {
	font-size: 16px;
	font-weight: 600;
	margin: 0;
	line-height: 1.3;
	color: #111827;
}
/* Inline edit-pencil — sits flush after the title text. Server-side
 * w2gm_render_popup_source injects this anchor inside the h3 when
 * the current user has edit permission on the listing (admin URL)
 * or owns it (dashboard URL). The cardinal sin to avoid: don't
 * underline-decorate or visually loaden the link inside a heading
 * — it should read as an icon-only action, not a hyperlink inside
 * the title. `vertical-align: baseline` keeps the icon visually
 * centred with the title's cap-height (pure middle alignment makes
 * the pencil sit ~2px too low against 16px text). The sidebar
 * card's click handler watches `data-rmaps-no-card-click` so a
 * click here doesn't ALSO open the popup. */
.rmaps-listing-content .rmaps-popup__edit-link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	margin-left: 6px;
	padding: 2px;
	color: #6b7280;
	border-radius: 3px;
	vertical-align: baseline;
	text-decoration: none;
	transition: color 0.12s, background 0.12s;
	cursor: pointer;
}
.rmaps-listing-content .rmaps-popup__edit-link:hover,
.rmaps-listing-content .rmaps-popup__edit-link:focus {
	color: var(--rmaps-primary, #2563eb);
	background: #eff6ff;
	outline: none;
}
/* The universal `.rmaps-listing-content *` rule above sets
 * `cursor: default` on every descendant — including the SVG inside
 * this anchor. When the SVG covers nearly the whole 17×17 hit area
 * the cursor stays default even though the parent <a> has
 * `cursor: pointer`. Selector specificity (0,2,1) beats the
 * universal-descendant rule (0,1,0) so the override sticks without
 * `!important`. Also stops `pointer-events: none` from being
 * implicitly set so the SVG forwards clicks to the anchor.
 *
 * Sidebar parallel: when `.is-clickable` cards force `cursor:
 * pointer` on every descendant the visual is fine either way — but
 * non-clickable sidebars (popups disabled) also benefit from this
 * explicit override. */
.rmaps-listing-content .rmaps-popup__edit-link,
.rmaps-listing-content .rmaps-popup__edit-link * {
	cursor: pointer;
}
.rmaps-listing-content .rmaps-popup__edit-link svg {
	display: block;
	pointer-events: none;
}
.rmaps-listing-content .rmaps-popup__field {
	display: grid;
	grid-template-columns: 18px 1fr;
	gap: 8px;
	align-items: start;
	margin: 0;
}
/* Per-type icon glyph injected via :before — uses FontAwesome class names that
 * already ship with the plugin (rmaps-fa-*). */
.rmaps-listing-content .rmaps-popup__field::before {
	font-family: 'FontAwesome';
	font-weight: 400;
	font-style: normal;
	font-size: 14px;
	color: var(--rmaps-primary, #2563eb);
	line-height: 1.4;
	text-align: center;
}
.rmaps-listing-content .rmaps-popup__field--content::before    { content: '\f15c'; } /* file-text */
.rmaps-listing-content .rmaps-popup__field--excerpt::before    { content: '\f036'; } /* align-left */
.rmaps-listing-content .rmaps-popup__field--address::before    { content: '\f041'; } /* map-marker */
.rmaps-listing-content .rmaps-popup__field--categories::before { content: '\f02c'; } /* tags */
.rmaps-listing-content .rmaps-popup__field--tags::before       { content: '\f02b'; } /* tag */
.rmaps-listing-content .rmaps-popup__field--hours::before      { content: '\f017'; } /* clock-o */
.rmaps-listing-content .rmaps-popup__field--datetime::before   { content: '\f073'; } /* calendar */
.rmaps-listing-content .rmaps-popup__field--price::before      { content: '\f155'; } /* dollar */
.rmaps-listing-content .rmaps-popup__field--number::before     { content: '\f292'; } /* hashtag */
.rmaps-listing-content .rmaps-popup__field--phone::before      { content: '\f095'; } /* phone */
.rmaps-listing-content .rmaps-popup__field--email::before      { content: '\f0e0'; } /* envelope */
.rmaps-listing-content .rmaps-popup__field--website::before    { content: '\f0c1'; } /* link */
.rmaps-listing-content .rmaps-popup__field--fileupload::before { content: '\f0c6'; } /* paperclip */
.rmaps-listing-content .rmaps-popup__field--list::before,
.rmaps-listing-content .rmaps-popup__field--select::before,
.rmaps-listing-content .rmaps-popup__field--radio::before,
.rmaps-listing-content .rmaps-popup__field--checkbox::before   { content: '\f00b'; } /* list-ul */
.rmaps-listing-content .rmaps-popup__field--text::before,
.rmaps-listing-content .rmaps-popup__field--string::before,
.rmaps-listing-content .rmaps-popup__field--textarea::before   { content: '\f031'; } /* font */

/* Price is bumped two pixels above the body baseline (15 instead of
 * the popup-default 13) — applies in both the popup AND the sidebar
 * since `.rmaps-listing-content` is the shared wrapper class for
 * both surfaces. The `::before` icon keeps its own explicit
 * `font-size: 14px` rule above, so this only affects the value text. */
.rmaps-listing-content .rmaps-popup__field--price {
	font-size: 15px;
}

/* Per-field custom icon override — when the admin picked an icon in the
 * form-builder Field Properties panel, PHP renders an inline <i> and
 * tags the wrapper with `--has-custom-icon`. Suppress the type-default
 * pseudo so the two don't stack, and style the inline element to fit
 * the same grid column the pseudo would have occupied. */
.rmaps-listing-content .rmaps-popup__field--has-custom-icon::before {
	content: none;
}
.rmaps-listing-content .rmaps-popup__icon {
	font-size: 14px;
	color: var(--rmaps-primary, #2563eb);
	line-height: 1.4;
	text-align: center;
}

/* Per-source "hide icon" — the admin unticked the Popups-metabox
 * "show icon" checkbox for this field. Collapse the reserved 18 px
 * icon column to a single value column and suppress BOTH icon
 * sources (the type-default `::before` glyph and any custom inline
 * `<i class="rmaps-popup__icon">`). PHP tags the wrapper with
 * `--no-icon` (see `rmaps_build_popup_html`). */
.rmaps-listing-content .rmaps-popup__field--no-icon {
	grid-template-columns: 1fr;
}
/* `!important` — necessary because per-type `::before` rules
 * (`--contact_form::before { content: '\f0e0' }`, `--email::before`,
 * `--phone::before`, …) live LATER in this file and would otherwise
 * win on equal specificity. The `--no-icon` modifier is an explicit
 * admin opt-out, so it must override regardless of source order. */
.rmaps-listing-content .rmaps-popup__field--no-icon::before {
	content: none !important;
}
.rmaps-listing-content .rmaps-popup__field--no-icon .rmaps-popup__icon {
	display: none;
}

/* Title doesn't get an icon column — span both grid cells. */
.rmaps-listing-content .rmaps-popup__title {
	margin-bottom: 4px;
}

.rmaps-listing-content .rmaps-popup__label {
	font-size: 11px;
	font-weight: 600;
	text-transform: uppercase;
	color: #6b7280;
	letter-spacing: 0.4px;
	margin-bottom: 2px;
}
.rmaps-listing-content .rmaps-popup__value {
	line-height: 1.4;
	min-width: 0;        /* allow ellipsis inside grid cell */
	word-wrap: break-word;
	overflow-wrap: anywhere;
}
.rmaps-listing-content .rmaps-popup__value p { margin: 0; }
.rmaps-listing-content .rmaps-popup__value p + p { margin-top: 4px; }

/* Long text fields — clamp to 4 lines with ellipsis instead of scrolling. */
.rmaps-listing-content .rmaps-popup__field--content .rmaps-popup__value,
.rmaps-listing-content .rmaps-popup__field--excerpt .rmaps-popup__value,
.rmaps-listing-content .rmaps-popup__field--textarea .rmaps-popup__value,
.rmaps-listing-content .rmaps-popup__field--text .rmaps-popup__value,
.rmaps-listing-content .rmaps-popup__field--string .rmaps-popup__value {
	display: -webkit-box;
	-webkit-line-clamp: 4;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.rmaps-listing-content .rmaps-popup__field--content .rmaps-popup__value p,
.rmaps-listing-content .rmaps-popup__field--excerpt .rmaps-popup__value p,
.rmaps-listing-content .rmaps-popup__field--textarea .rmaps-popup__value p,
.rmaps-listing-content .rmaps-popup__field--text .rmaps-popup__value p,
.rmaps-listing-content .rmaps-popup__field--string .rmaps-popup__value p {
	display: inline;
}

/* Single-line truncation for fields that should never wrap to a new line. */
.rmaps-listing-content .rmaps-popup__field--phone .rmaps-popup__value,
.rmaps-listing-content .rmaps-popup__field--website .rmaps-popup__value,
.rmaps-listing-content .rmaps-popup__field--email .rmaps-popup__value {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.rmaps-listing-content .rmaps-popup__field--phone .rmaps-popup__value p,
.rmaps-listing-content .rmaps-popup__field--website .rmaps-popup__value p,
.rmaps-listing-content .rmaps-popup__field--email .rmaps-popup__value p {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.rmaps-listing-content .rmaps-popup__field--website .rmaps-popup__value a {
	display: inline-block;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	vertical-align: bottom;
}

/* Images — single logo OR mini slider depending on count.
 * Both span the full popup width (icon column + value cell). */
.rmaps-listing-content .rmaps-popup__images {
	grid-column: 1 / -1;
}

/* Single logo — fills the container width, height scales by aspect
 * ratio. Same shape works in BOTH render contexts:
 *   - popup     → fills popup width
 *   - sidebar   → fills card width = full sidebar (left/right vertical
 *                  layout) OR column width (top/bottom grid layout,
 *                  where `.rmaps-react-sidebar__grid--grid` auto-fills
 *                  with `repeat(auto-fill, minmax(220px, 1fr))`)
 * The earlier `height: 140px; width: auto` cropped the image to a
 * 140-px-tall band even when way more vertical space was available
 * — confusing UX, especially for portrait-oriented listing logos
 * that ended up tiny. */
.rmaps-listing-content .rmaps-popup__images--single {
	display: flex;
	justify-content: center;
}
.rmaps-listing-content .rmaps-popup__images--single img {
	width: 100%;
	height: auto;
	max-width: 100%;
	-o-object-fit: contain;
	   object-fit: contain;
	border-radius: 4px;
	display: block;
}

/* Multi-image slider — arrow-driven, scrollbar hidden. `overflow-x: auto`
 * (instead of hidden) lets users swipe between slides with their finger on
 * mobile; the scroll-snap stops naturally on each slide. The scrollbar is
 * suppressed via `scrollbar-width: none` + ::-webkit-scrollbar so the
 * gallery still looks clean. */
.rmaps-listing-content .rmaps-popup__images--slider {
	position: relative;
}
.rmaps-listing-content .rmaps-popup__slider-track {
	display: flex;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	/* Lets the browser keep horizontal swipes on the slider while still
	 * bubbling vertical scroll up to the sidebar. Without this, a swipe that
	 * starts diagonally can be claimed by the parent and the slide never
	 * advances. */
	touch-action: pan-x pan-y;
}
.rmaps-listing-content .rmaps-popup__slider-track::-webkit-scrollbar { display: none; }
.rmaps-listing-content .rmaps-popup__slide {
	flex: 0 0 100%;
	scroll-snap-align: start;
	display: flex;
	justify-content: center;
}
.rmaps-listing-content .rmaps-popup__slide img {
	width: 100%;
	height: auto;
	max-width: 100%;
	-o-object-fit: contain;
	   object-fit: contain;
	border-radius: 4px;
	display: block;
}
/* Arrow buttons — circular overlay on track edges, symmetric inset. The
 * `touch-action: manipulation` removes the 300 ms tap delay and stops the
 * browser from interpreting a quick tap as the start of a scroll gesture
 * (which would swallow the click). */
.rmaps-listing-content .rmaps-popup__slider-btn {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	width: 32px;
	height: 32px;
	border-radius: 50%;
	border: none;
	background: rgba(0, 0, 0, 0.55);
	color: #fff;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 2;
	transition: background 0.15s;
	padding: 0;
	touch-action: manipulation;
	-webkit-tap-highlight-color: transparent;
}
.rmaps-listing-content .rmaps-popup__slider-btn:hover { background: rgba(0, 0, 0, 0.78); }
.rmaps-listing-content .rmaps-popup__slider-btn > .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-weight: 900;        /* bolder chevron stroke */
	font-size: 16px;
	line-height: 1;
}
.rmaps-listing-content .rmaps-popup__slider-prev { left: 8px; }
.rmaps-listing-content .rmaps-popup__slider-next { right: 8px; }
/* Larger hit area on touch screens — visual button stays the same, the
 * `::before` pseudo extends the tap target without shifting layout. */
@media (hover: none) and (pointer: coarse) {
	.rmaps-listing-content .rmaps-popup__slider-btn {
		width: 40px;
		height: 40px;
	}
	.rmaps-listing-content .rmaps-popup__slider-btn::before {
		content: '';
		position: absolute;
		inset: -8px;
	}
}

/* Chips for list/select/radio/checkbox + categories/tags */
.rmaps-listing-content .rmaps-popup__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
}
.rmaps-listing-content .rmaps-popup__chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 3px 10px;
	background: #f3f4f6;
	border-radius: 12px;
	font-size: 12px;
	color: #374151;
	line-height: 1.3;
}
.rmaps-listing-content .rmaps-popup__chip > .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-weight: 400;
	font-size: 13px;
	line-height: 1;
	color: var(--rmaps-primary, #2563eb);
	display: inline-block;
}

/* Distance-to-search-centre chip — injected by Popup.tsx /
   MapSidebar's SidebarCard into the address field whenever an
   address+radius search is active. Sits inline at the end of the
   address text, picks up the same colour palette as the primary
   button, hover-title shows the entered/picked address. */
.rmaps-listing-content .rmaps-popup__distance {
	display: inline-block;
	margin-left: 6px;
	padding: 1px 8px;
	background: var(--rmaps-button-primary, var(--rmaps-primary, #2563eb));
	color: #ffffff;
	border-radius: 10px;
	font-size: 11px;
	font-weight: 500;
	line-height: 1.5;
	white-space: nowrap;
	cursor: help;
	vertical-align: baseline;
}

/* Hours table */
.rmaps-listing-content .rmaps-popup__hours,
.rmaps-listing-content .rmaps-popup__hours tr,
.rmaps-listing-content .rmaps-popup__hours td {
	border: 0;
	background: transparent;
	box-shadow: none;
}
.rmaps-listing-content .rmaps-popup__hours {
	width: 100%;
	border-collapse: collapse;
	font-size: 12px;
}
.rmaps-listing-content .rmaps-popup__hours tr + tr td {
	border-top: 1px solid #f3f4f6;   /* divider only between rows */
}
.rmaps-listing-content .rmaps-popup__hours td {
	padding: 2px 6px;
}
.rmaps-listing-content .rmaps-popup__hours td:first-child {
	color: #6b7280;
	width: 48px;
}
.rmaps-listing-content .rmaps-popup__hours tr.is-today td {
	font-weight: 600;
	color: #111827;
}
.rmaps-listing-content .rmaps-popup__hours tr.is-today td:first-child {
	color: #374151;
}

/* Status badge — sits above the 7-day schedule and mirrors the
 * marker label: green pill when "Open · HH:MM" or "N min left",
 * red pill when "Opens HH:MM" / "Opens Day HH:MM" / "Closed". */
.rmaps-listing-content .rmaps-popup__hours-status {
	display: inline-block;
	padding: 1px 8px;
	margin: 0 0 4px 0;
	font-size: 11px;
	font-weight: 600;
	border-radius: 999px;
	line-height: 18px;
}
.rmaps-listing-content .rmaps-popup__hours-status--open {
	background: #dcfce7;
	color: #166534;
}
.rmaps-listing-content .rmaps-popup__hours-status--closed {
	background: #fee2e2;
	color: #991b1b;
}

/* "Send message" button — replaces the inline contact form in the
 * popup body. Visual contract identical to `.rmaps-popup__directions-btn`
 * (same height, primary background, full-width); the two are listed
 * together below to keep the parallel obvious. Click dispatches
 * `START_CONTACT`, which mounts the ContactSidebar with the
 * extracted form HTML. */
.rmaps-listing-content .rmaps-popup__contact-btn {
	display: flex;
	width: 100%;
	box-sizing: border-box;
	align-items: center;
	justify-content: center;
	gap: 6px;
	height: 30px;
	min-height: 0;
	padding: 0 12px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	color: #fff;
	background: var(--rmaps-primary, #2563eb);
	border: 0;
	border-radius: 4px;
	cursor: pointer;
}
.rmaps-listing-content .rmaps-popup__contact-btn:hover { filter: brightness(1.05); }
/* Active state — symmetrical with `.rmaps-popup__directions-btn.is-active`
 * over in `directions.css`. PopupCard's effect adds `is-active` while
 * the contact sidebar is the live open panel for THIS marker; the
 * secondary-colour fill reads as "this is the open form's button"
 * vs the regular primary "click to open" variant. */
.rmaps-listing-content .rmaps-popup__contact-btn.is-active {
	background: var(--rmaps-button-secondary, var(--rmaps-secondary, #1d4ed8));
}
.rmaps-listing-content .rmaps-popup__contact-btn.is-active:hover { filter: brightness(1.05); }
.rmaps-listing-content .rmaps-popup__contact-btn .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-size: 12px;
}

/* Listing-name banner inside the contact form — server-injected
   `<div class="rmaps-popup__contact-listing">` above the inputs.
   Reads as a small "Contacting:" subtitle so the visitor sees which
   listing the message will reach without having to scroll back to
   the popup/card title. Subtle background tint (primary-colour
   wash) so it visually GROUPS into the form below it; not loud
   enough to compete with the popup's own title above. */
.rmaps-listing-content .rmaps-popup__contact-listing {
	font-size: 12px;
	font-weight: 600;
	color: var(--rmaps-primary, #2563eb);
	background: color-mix(in srgb, var(--rmaps-primary, #2563eb) 8%, transparent);
	padding: 6px 10px;
	border-radius: 6px;
	border-left: 3px solid var(--rmaps-primary, #2563eb);
	line-height: 1.3;
	margin: 0 0 14px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* CF7 textarea — pin the rendered default to 6 rows regardless of
   what the CF7 admin stamped into the `rows="…"` attribute (often
   left at the CF7 default of 10 → way too tall for a sidebar
   popup). Combining `height` with `resize: vertical` lets the
   visitor drag the corner handle wider when they're writing a long
   message, but the initial reveal lands at a friendly 6-row size.
   `!important` overrides any baseline rule shipped by the CF7
   stylesheet (cf7's own `.wpcf7-form-control` selector has higher
   default specificity than our `.rmaps-listing-content` scope; the
   bang keeps the contract intact without forcing every CF7 host
   site to reorder stylesheets). 6 rows × 1.5 line-height × 14 px
   inherited font ≈ 126 px. */
.rmaps-listing-content .wpcf7-form-control.wpcf7-textarea {
	height: 126px !important;
	min-height: 126px;
	resize: vertical;
}

/* Contact form */
.rmaps-listing-content .rmaps-popup__contact-form {
	display: flex;
	flex-direction: column;
	gap: 6px;
	/* Defensive reset against Redux Framework's admin CSS. In the
	 * admin map-edit preview the popup is rendered INSIDE the WP
	 * dashboard where redux-admin.min.css ships a `.no-js` rule
	 * (alert-danger styling: pink background, red border, red text,
	 * text-shadow) that gets applied to any `<form>` Redux's JS
	 * hasn't initialised yet. Our popup form never gets initialised
	 * by Redux, so the bleed-through is permanent until we override.
	 * Match the no-style baseline the frontend popup uses so the
	 * admin preview looks identical. */
	background: transparent !important;
	border: 0 !important;
	color: inherit !important;
	text-shadow: none !important;
	padding: 0 !important;
	margin: 0 !important;
}
/* Universal kill-switch for Redux's `.no-js` admin styling — applies to
 * ANY element with class `no-js` inside the popup, including the CF7
 * form wrapper (`.wpcf7-form`) and the W2GM built-in form. Without
 * this, when the popup renders a CF7 shortcode (option
 * `w2gm_listing_contact_form_7`), the form's class is `wpcf7-form`,
 * not `.rmaps-popup__contact-form` — the more specific rules above
 * miss it. This selector catches both. The JS strip in Popup.tsx is
 * still the cleaner permanent fix (rebuild the React bundle to ship
 * it); this CSS is the no-build-required safety net. */
.rmaps-listing-content .no-js,
.rmaps-listing-content .wpcf7-form.no-js,
.rmaps-listing-content form.no-js {
	background: transparent !important;
	background-color: transparent !important;
	border: 0 !important;
	color: inherit !important;
	text-shadow: none !important;
	padding: 0 !important;
}
.rmaps-listing-content .no-js input,
.rmaps-listing-content .no-js textarea,
.rmaps-listing-content .wpcf7-form input,
.rmaps-listing-content .wpcf7-form textarea {
	text-shadow: none !important;
}
.rmaps-listing-content .rmaps-popup__contact-form input[type="text"],
.rmaps-listing-content .rmaps-popup__contact-form input[type="email"],
.rmaps-listing-content .rmaps-popup__contact-form textarea {
	width: 100%;
	box-sizing: border-box;
	padding: 0 8px;
	font-size: 12px;
	line-height: 1;
	border: 1px solid #d1d5db;
	border-radius: 4px;
	background: #fff;
	color: #1f2937;
	font-family: inherit;
	resize: vertical;
	/* Same defensive override as the form wrapper — Redux's
	 * `.no-js` admin CSS targets inputs / textareas too. */
	text-shadow: none !important;
}
/* Single-line inputs — explicit 30 px to match
 * `.rmaps-popup__contact-submit` + `.rmaps-popup__directions-btn`.
 * Textarea keeps its multi-line min/max height (next rule). */
.rmaps-listing-content .rmaps-popup__contact-form input[type="text"],
.rmaps-listing-content .rmaps-popup__contact-form input[type="email"] {
	height: 30px;
	min-height: 0;
}
.rmaps-listing-content .rmaps-popup__contact-form textarea {
	padding: 6px 8px;
	line-height: 1.4;
	min-height: 60px;
	max-height: 160px;
}
.rmaps-listing-content .rmaps-popup__contact-actions {
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 8px;
}
.rmaps-listing-content .rmaps-popup__contact-submit {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	box-sizing: border-box;
	/* See directions-btn — explicit height beats relying on padding +
	 * line-height that preflight's `font: inherit` can override. */
	height: 30px;
	min-height: 0;
	padding: 0 14px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	color: #fff;
	background: var(--rmaps-primary, #2563eb);
	border: none;
	border-radius: 4px;
	cursor: pointer;
	text-align: center;
}
.rmaps-listing-content .rmaps-popup__contact-submit:hover { filter: brightness(1.05); }
.rmaps-listing-content .rmaps-popup__contact-submit:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}
.rmaps-listing-content .rmaps-popup__contact-status {
	font-size: 11px;
	color: #6b7280;
}
.rmaps-listing-content .rmaps-popup__contact-status[data-state="ok"]  { color: #15803d; }
.rmaps-listing-content .rmaps-popup__contact-status[data-state="err"] { color: #b91c1c; }

/* Field icon for the contact-form row uses an envelope. */
.rmaps-listing-content .rmaps-popup__field--contact_form::before { content: '\f0e0'; }

/* ============================================================
   Contact Form 7 — match the standard contact form's compact look
   ----------------------------------------------------------------
   When the admin pastes a CF7 shortcode into Listings → Contact form
   → "Contact Form 7 shortcode", `maps_manager.php :: contact_form`
   wraps `do_shortcode()`'s output in `.rmaps-popup__field--cf7` and
   we restyle CF7's default markup to mirror the plugin's own form
   geometry — column flex, compact 30 px buttons, full-width inputs,
   subtle status colours. Without this CF7 inherits its theme styles
   inside a 280-px popup, which usually looks oversized and drifts
   off the geometry the rest of the popup cards use.
   ============================================================ */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form {
	display: flex;
	flex-direction: column;
	gap: 6px;
	margin: 0;
}
/* CF7 wraps each field row in a `<p>` with bare label text + `<br>`
 * + the input span. Labels live in the paragraph's text nodes, not
 * inside `<label>` elements — so the row-level font-size/color rules
 * here are what styles "Your Name (required)" / etc. WP's admin
 * `load-styles.php` sets `p { font-size: 13px; line-height: 1.5;
 * margin: 1em 0 }` which bleeds into the in-admin map-edit popup
 * preview; `!important` keeps our overrides ahead of it without
 * having to chase specificity across two stylesheets. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form p {
	margin: 0 !important;
	font-size: 12px !important;
	line-height: 1.4 !important;
	color: #374151;
}
/* Inputs / textarea / select — same baseline as the plugin's standard form */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="text"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="email"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="tel"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="url"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="number"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="date"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form select,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form textarea {
	width: 100%;
	box-sizing: border-box;
	padding: 0 8px;
	font-size: 12px;
	line-height: 1;
	border: 1px solid #d1d5db;
	border-radius: 4px;
	background: #fff;
	color: #1f2937;
	font-family: inherit;
	resize: vertical;
}
/* Single-line CF7 inputs — explicit 30 px to match popup buttons. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="text"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="email"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="tel"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="url"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="number"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="date"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form select {
	height: 30px;
	min-height: 0;
}
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form textarea {
	padding: 6px 8px;
	line-height: 1.4;
	min-height: 60px;
	max-height: 160px;
}
/* Some CF7 templates wrap the control in `<label>` instead of `<p>`
 * (admin can edit the form structure freely in the CF7 form editor).
 * Keep the same baseline as the `<p>` path so both shapes render
 * identically. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form label {
	display: block;
	font-size: 12px;
	line-height: 1.4;
	color: #374151;
	margin: 0;
}
/* Submit button — explicit 30 px height matches `.rmaps-popup__contact-submit`.
 * `!important` defends against theme stylesheets that inject button
 * padding via low-specificity selectors. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form .wpcf7-submit,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="submit"],
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form button[type="submit"] {
	display: flex !important;
	align-items: center;
	justify-content: center;
	width: 100% !important;
	box-sizing: border-box;
	height: 30px !important;
	min-height: 0 !important;
	padding: 0 14px !important;
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	color: #fff !important;
	background: var(--rmaps-primary, #2563eb) !important;
	border: 0 !important;
	border-radius: 4px !important;
	cursor: pointer;
	text-align: center;
	text-transform: none;
}
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form .wpcf7-submit:hover,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="submit"]:hover,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form button[type="submit"]:hover {
	filter: brightness(1.05);
}
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form .wpcf7-submit:disabled,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-form input[type="submit"]:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}
/* CF7 status response (`.wpcf7-response-output`) — same colour
 * conventions as the plugin's `.rmaps-popup__contact-status`. CF7
 * adds class modifiers for the state, so we map all of them. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-response-output {
	margin: 6px 0 0 !important;
	padding: 6px 8px !important;
	font-size: 11px;
	border-radius: 4px;
	border: 1px solid transparent !important;
}
/* CF7 leaves the response container in the DOM even before the user
 * submits — pre-submit it carries our margin+padding but no text, so
 * it shows up as a lonely empty bar wedged between the form and the
 * popup edge. Collapse it to nothing whenever it has no content; CF7
 * fills it on submit, and the `:empty` selector flips back off the
 * moment any text or child node lands. `!important` defends against
 * the rule above also using `!important` for margin/padding. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-response-output:empty {
	display: none !important;
}
.rmaps-listing-content .rmaps-popup__field--cf7 form.sent .wpcf7-response-output,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-mail-sent-ok {
	color: #15803d !important;
	background: #f0fdf4;
	border-color: #bbf7d0 !important;
}
.rmaps-listing-content .rmaps-popup__field--cf7 form.invalid .wpcf7-response-output,
.rmaps-listing-content .rmaps-popup__field--cf7 form.failed .wpcf7-response-output,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-validation-errors,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-mail-sent-ng,
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-spam-blocked {
	color: #b91c1c !important;
	background: #fef2f2;
	border-color: #fecaca !important;
}
/* Per-field validation tips */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-not-valid-tip {
	font-size: 11px;
	color: #b91c1c;
	margin-top: 2px;
}
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-not-valid {
	border-color: #fca5a5 !important;
}
/* CF7's spinner sits next to the submit button — fine inline, just
 * shrink so it matches the compact button height. */
.rmaps-listing-content .rmaps-popup__field--cf7 .wpcf7-spinner {
	width: 18px;
	height: 18px;
	margin: 0 0 0 6px;
}

/* File list */
.rmaps-listing-content .rmaps-popup__files {
	margin: 0;
	padding-left: 18px;
}
.rmaps-listing-content .rmaps-popup__files a {
	color: var(--rmaps-primary, #2563eb);
	text-decoration: none;
}
.rmaps-listing-content .rmaps-popup__files a:hover { text-decoration: underline; }

/* ============================================================
   Popup-only overrides — tighter spacing and smaller fonts
   ----------------------------------------------------------------
   Every rule above is scoped to `.rmaps-listing-content`, which is
   carried by BOTH the popup body AND the sidebar listing cards.
   The popup body ALSO carries `.rmaps-react-infowindow-content`
   (sidebar cards don't), so prefixing override selectors with
   that class scopes them to popups only — sidebar listings keep
   the looser geometry the shared rules above set.

   Equal-specificity ties between
   `.rmaps-listing-content .rmaps-popup__X` and
   `.rmaps-react-infowindow-content .rmaps-popup__X` (both 0,2,0)
   resolve in CSS source order, so as long as this block stays
   AT THE BOTTOM of the file, the popup-only values win on the
   popup body and the shared values keep applying to sidebar
   cards.

   Sizing brief: popup title 14 px, chips 11 px, every margin /
   padding / gap declared above is halved here so the same
   server-rendered HTML reads denser inside the popup card while
   the sidebar listing card stays unchanged.
   ============================================================ */
/* Scrollbar gutter — only when the content actually overflows.
   `.rmaps-react-infowindow-content--has-scroll` is toggled by
   `PopupCard.tsx`'s overflow-observer effect alongside the
   `overflowY: auto/hidden` switch. */
.rmaps-react-infowindow-content.rmaps-react-infowindow-content--has-scroll {
	padding-right: 4px;
}
.rmaps-react-infowindow-content .rmaps-popup {
	gap: 5px;
}
.rmaps-react-infowindow-content .rmaps-popup__title {
	font-size: 14px;
}
/* The shared block sets a second `margin-bottom: 4px` on the
   title; halve it here. */
.rmaps-react-infowindow-content .rmaps-popup__title {
	margin-bottom: 2px;
}
.rmaps-react-infowindow-content .rmaps-popup__edit-link {
	margin-left: 3px;
	padding: 1px;
}
.rmaps-react-infowindow-content .rmaps-popup__field {
	gap: 4px;
}
.rmaps-react-infowindow-content .rmaps-popup__label {
	margin-bottom: 1px;
}
.rmaps-react-infowindow-content .rmaps-popup__value {
	font-size: 11px;
}
.rmaps-react-infowindow-content .rmaps-popup__value p + p {
	margin-top: 2px;
}
.rmaps-react-infowindow-content .rmaps-popup__chips {
	gap: 2px;
}
.rmaps-react-infowindow-content .rmaps-popup__chip {
	font-size: 11px;
	gap: 3px;
	padding: 2px 5px;
}
.rmaps-react-infowindow-content .rmaps-popup__hours td {
	padding: 1px 3px;
}
.rmaps-react-infowindow-content .rmaps-popup__hours-status {
	padding: 1px 4px;
	margin: 0 0 2px 0;
}
.rmaps-react-infowindow-content .rmaps-popup__contact-form {
	gap: 3px;
}
.rmaps-react-infowindow-content .rmaps-popup__contact-form input[type="text"],
.rmaps-react-infowindow-content .rmaps-popup__contact-form input[type="email"],
.rmaps-react-infowindow-content .rmaps-popup__contact-form textarea {
	padding: 3px 4px;
}
.rmaps-react-infowindow-content .rmaps-popup__contact-actions {
	gap: 4px;
}
.rmaps-react-infowindow-content .rmaps-popup__contact-submit {
	padding: 0 7px;
}
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form {
	gap: 3px;
}
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="text"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="email"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="tel"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="url"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="number"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="date"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form select,
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form textarea {
	padding: 3px 4px;
}
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form .wpcf7-submit,
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form input[type="submit"],
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-form button[type="submit"] {
	padding: 0 7px !important;
}
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-response-output {
	margin: 3px 0 0 !important;
	padding: 3px 4px !important;
}
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-not-valid-tip {
	margin-top: 1px;
}
.rmaps-react-infowindow-content .rmaps-popup__field--cf7 .wpcf7-spinner {
	margin: 0 0 0 3px;
}
.rmaps-react-infowindow-content .rmaps-popup__files {
	padding-left: 9px;
}

/* Directions popup affordances.
 *
 * This stylesheet used to host the now-deleted top-mounted input
 * bar (`.rmaps-directions-bar*`) and the in-popup route summary
 * (`.rmaps-popup__route-stats`, `.rmaps-popup__route-steps`). The
 * rework moved both into the dedicated DirectionsSidebar (see
 * `directionsSidebar.css`). What stays here is the popup-side
 * surface area: the "Get directions" button rendered inside every
 * popup, and the global `.pac-container` z-index lift that keeps
 * the Google Places autocomplete dropdown above any other
 * map-anchored chrome.
 */

/* Google Places autocomplete dropdown — Google appends `.pac-container` to
 * <body>; bump z-index above any Material/Google overlays on the page so it
 * stays visible above the sidebar / popup / InfoWindow. */
.pac-container {
	z-index: 100000 !important;
}

.rmaps-listing-content .rmaps-popup__directions-btn {
	display: flex;
	width: 100%;
	box-sizing: border-box;
	align-items: center;
	justify-content: center;
	gap: 6px;
	/* Hard-pin the height (and zero out vertical padding) — relying on
	 * just `padding-y` + font/line-height made the button's final
	 * height depend on Tailwind preflight's `font: inherit` (which
	 * overrode line-height to whatever the InfoWindow container has).
	 * Explicit `height` + `padding: 0` + `line-height: 1` removes that
	 * variable, locking the button to 24 px. */
	height: 30px;
	min-height: 0;
	padding: 0 12px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	color: #fff;
	background: var(--rmaps-primary, #2563eb);
	border: 0;
	border-radius: 4px;
	cursor: pointer;
}
.rmaps-listing-content .rmaps-popup__directions-btn:hover { filter: brightness(1.05); }
/* Active state — set by PopupCard's `is-active` toggle while THIS
 * marker's directions sidebar is the live open panel. Reads as
 * "this is the button whose panel you're currently looking at",
 * not the regular "click me" CTA. Secondary palette colour so it
 * visibly STEPS DOWN from the primary call-to-action variant the
 * other popup's button still shows — admins themed for high
 * primary/secondary contrast get a clean toggle, sites with the
 * two close together still get a subtle "is open" hint. */
.rmaps-listing-content .rmaps-popup__directions-btn.is-active {
	background: var(--rmaps-button-secondary, var(--rmaps-secondary, #1d4ed8));
}
.rmaps-listing-content .rmaps-popup__directions-btn.is-active:hover { filter: brightness(1.05); }
.rmaps-listing-content .rmaps-popup__directions-btn .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-size: 12px;
}

.rmaps-listing-content .rmaps-popup__field--directions::before { content: '\f124'; } /* location-arrow */

/* Directions sidebar — left-anchored overlay that hosts the
 * starting-address form, a loader while the provider computes,
 * and the resulting distance/duration + step list. Visual contract
 * matches the listings sidebar (`sidebar.css`):
 *
 *   - white card + soft shadow background,
 *   - chevron toggle on the trailing edge that slides the panel
 *     off-screen via transform (no width change → no map reflow),
 *   - same 0.25s ease transition timing,
 *   - same primary-coloured chip for the toggle and same hover
 *     darken,
 *   - thin Win 11–style scrollbar that thickens on hover for the
 *     internal scroll container.
 *
 * Differences from the listings sidebar:
 *   - always left-anchored (the design has only one slot for this
 *     panel — no admin metabox to move it elsewhere),
 *   - higher z-index (720) so it stacks above the listings sidebar
 *     (z 700) when both are open on the left edge,
 *   - mounted only while `state.directions` is set — no
 *     persistent open/closed preference in localStorage,
 *   - the toggle COLLAPSES the panel without dispatching
 *     `CLEAR_DIRECTIONS`. The × in the header is what clears the
 *     route. Distinguishing the two affordances lets the user park
 *     the directions panel off-screen to look at the map while the
 *     route is still drawn.
 */

.rmaps-react-directions-sidebar {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	max-width: calc(100% - 36px);
	background: #fff;
	box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	/* Stacks above listings sidebar (z 700). Tied with ContactSidebar
	 * (also 720) so neither panel paints OVER the other during the
	 * cross-fade swap on mobile — they cross-fade at the same z, the
	 * opacity transition (mobile @media below) handles the smooth
	 * blend instead of one eating the other from the top. Still
	 * below click-popup (z 1000 / 1500). */
	z-index: 720;
	transform: translateX(0);
	transition: transform 0.25s ease, opacity 0.25s ease;
	will-change: transform, opacity;
	opacity: 1;
	color: #1f2937;
}
.rmaps-react-directions-sidebar.is-collapsed,
.rmaps-react-directions-sidebar.is-collapsed-up {
	transform: translateX(-100%);
}

/* Toggle button intentionally removed — the directions panel is a
 * transient task surface, not a persistent affordance the visitor
 * needs a one-click "park it" button for. The × in the header
 * dismisses the panel (and clears the route). */

/* Header — title + close X. The close is the explicit "I'm done
 * with this route" action; clicking it clears the route AND
 * unmounts the sidebar (CLEAR_DIRECTIONS resets state.directions
 * to null). */
.rmaps-react-directions-sidebar__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 12px 14px;
	border-bottom: 1px solid #e5e7eb;
	background: #f9fafb;
	flex: 0 0 auto;
}
.rmaps-react-directions-sidebar__title {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
	font-weight: 600;
	color: #111827;
}
.rmaps-react-directions-sidebar__title .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-weight: 400;
	font-size: 14px;
	color: var(--rmaps-primary, #2563eb);
	line-height: 1;
}
.rmaps-react-directions-sidebar__close,
.rmaps-react-directions-sidebar__close:hover,
.rmaps-react-directions-sidebar__close:focus,
.rmaps-react-directions-sidebar__close:active {
	border: 0;
	background: none;
	background-color: transparent;
	font-size: 22px;
	line-height: 1;
	color: #6b7280;
	cursor: pointer;
	padding: 0 4px;
	box-shadow: none;
	outline: none;
}
.rmaps-react-directions-sidebar__close:hover { color: #111827; }

/* Body — scroll container for the form + loader / route summary. */
.rmaps-react-directions-sidebar__body {
	flex: 1 1 auto;
	overflow-y: auto;
	overflow-x: hidden;
	padding: 14px;
	box-sizing: border-box;
	/* Win 11–style thin scrollbar — matches MapSidebar's scroll. */
	scrollbar-width: thin;
	scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
}
.rmaps-react-directions-sidebar__body::-webkit-scrollbar {
	width: 14px;
	height: 14px;
}
.rmaps-react-directions-sidebar__body::-webkit-scrollbar-track,
.rmaps-react-directions-sidebar__body::-webkit-scrollbar-corner {
	background: transparent;
}
.rmaps-react-directions-sidebar__body::-webkit-scrollbar-thumb {
	background-color: rgba(0, 0, 0, 0.2);
	background-clip: padding-box;
	border: 5px solid transparent;
	border-radius: 7px;
	-webkit-transition: border-width 0.18s ease, background-color 0.18s ease;
	transition: border-width 0.18s ease, background-color 0.18s ease;
}
.rmaps-react-directions-sidebar__body:hover::-webkit-scrollbar-thumb {
	border-width: 3px;
	background-color: rgba(0, 0, 0, 0.32);
}
.rmaps-react-directions-sidebar__body::-webkit-scrollbar-thumb:hover {
	background-color: rgba(0, 0, 0, 0.5);
	border-width: 2px;
}

/* Destination row — static "To: ..." anchor above the form so the
 * visitor knows what the route is being computed TO without having
 * to look back at the marker on the map. Label uses the same
 * uppercase-tracked styling as the form field labels so the two
 * read as a single mini-table of "Destination / Starting address". */
.rmaps-react-directions-sidebar__dest {
	display: flex;
	flex-direction: column;
	gap: 4px;
	padding: 8px 10px;
	margin-bottom: 12px;
	background: #f9fafb;
	border: 1px solid #e5e7eb;
	border-radius: 6px;
}
.rmaps-react-directions-sidebar__dest-value {
	display: flex;
	align-items: flex-start;
	gap: 6px;
	font-size: 13px;
	color: #1f2937;
	line-height: 1.4;
	overflow-wrap: anywhere;
}
.rmaps-react-directions-sidebar__dest-value .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-weight: 400;
	color: var(--rmaps-primary, #2563eb);
	font-size: 13px;
	line-height: 1.4;
	flex: 0 0 auto;
}
.rmaps-react-directions-sidebar__dest-value .rmaps-fa-map-marker::before {
	content: '\f041';
}

/* Form */
.rmaps-react-directions-sidebar__form {
	display: flex;
	flex-direction: column;
	gap: 8px;
}
.rmaps-react-directions-sidebar__field {
	display: flex;
	flex-direction: column;
	gap: 4px;
}
.rmaps-react-directions-sidebar__label {
	font-size: 11px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.4px;
	color: #6b7280;
}
.rmaps-react-directions-sidebar__input-row {
	display: flex;
	align-items: center;
	gap: 6px;
	border: 1px solid #d1d5db;
	border-radius: 6px;
	background: #fff;
	padding: 0 6px;
	transition: border-color 0.12s, box-shadow 0.12s;
}
.rmaps-react-directions-sidebar__input-row:focus-within {
	border-color: var(--rmaps-primary, #2563eb);
	box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}
.rmaps-react-directions-sidebar__input {
	flex: 1 1 auto;
	min-width: 0;
	height: 32px;
	border: 0;
	outline: none;
	font-size: 13px;
	background: transparent;
	color: #1f2937;
	padding: 0 2px;
	font-family: inherit;
}
.rmaps-react-directions-sidebar__input::-moz-placeholder { color: #9ca3af; }
.rmaps-react-directions-sidebar__input::placeholder { color: #9ca3af; }
.rmaps-react-directions-sidebar__input:disabled { color: #6b7280; }

.rmaps-react-directions-sidebar__find {
	border: 0;
	background: transparent;
	color: #9ca3af;
	cursor: pointer;
	width: 26px;
	height: 26px;
	padding: 0;
	border-radius: 50%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	transition: background 0.12s, color 0.12s;
}
.rmaps-react-directions-sidebar__find:hover {
	background: #f3f4f6;
	color: #4b5563;
}
.rmaps-react-directions-sidebar__find:focus {
	outline: none;
	background: #f3f4f6;
	color: #4b5563;
	box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.25);
}
.rmaps-react-directions-sidebar__find:disabled {
	opacity: 0.6;
	cursor: progress;
}

.rmaps-react-directions-sidebar__go {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	box-sizing: border-box;
	height: 32px;
	min-height: 0;
	padding: 0 14px;
	font-size: 13px;
	font-weight: 600;
	line-height: 1;
	color: #fff;
	background: var(--rmaps-primary, #2563eb);
	border: 0;
	border-radius: 6px;
	cursor: pointer;
	font-family: inherit;
}
.rmaps-react-directions-sidebar__go:hover:not(:disabled) {
	filter: brightness(1.05);
}
.rmaps-react-directions-sidebar__go:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

.rmaps-react-directions-sidebar__error {
	background: #fee2e2;
	color: #b91c1c;
	font-size: 12px;
	padding: 6px 10px;
	border-radius: 4px;
	border: 1px solid #fecaca;
}

/* Loading state — centred spinner + label while the provider
 * computes the route. Appears under the form so the user sees the
 * input they just submitted alongside the spinner (context).
 * Cleared the moment the route response lands. */
.rmaps-react-directions-sidebar__loading {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 10px;
	padding: 24px 12px;
	color: #6b7280;
	font-size: 13px;
}

/* Route summary — distance / duration stats and step list. */
.rmaps-react-directions-sidebar__route {
	margin-top: 14px;
	border-top: 1px solid #e5e7eb;
	padding-top: 12px;
}
.rmaps-react-directions-sidebar__stats {
	display: flex;
	gap: 14px;
	font-size: 13px;
	color: #1f2937;
	margin-bottom: 10px;
}
.rmaps-react-directions-sidebar__stats > span {
	display: inline-flex;
	align-items: center;
	gap: 5px;
}
.rmaps-react-directions-sidebar__stats .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-weight: 400;
	color: var(--rmaps-primary, #2563eb);
	font-size: 13px;
	line-height: 1;
}

.rmaps-react-directions-sidebar__steps {
	margin: 0;
	padding-left: 22px;
	font-size: 12px;
	color: #374151;
}
.rmaps-react-directions-sidebar__steps li {
	padding: 6px 6px 6px 4px;
	margin: 2px 0;
	border-radius: 4px;
	cursor: pointer;
	transition: background 0.12s;
	line-height: 1.45;
}
.rmaps-react-directions-sidebar__steps li:hover {
	background: #fef3c7;            /* matches the amber map highlight */
}
/* Click-locked step — deeper amber + bold so the row stays visible
 * after the cursor leaves the list (the click handler keeps the map
 * highlight up until the user clicks again). */
.rmaps-react-directions-sidebar__steps li.is-selected,
.rmaps-react-directions-sidebar__steps li.is-selected:hover {
	background: #fde68a;
	color: #1f2937;
	font-weight: 600;
}
.rmaps-react-directions-sidebar__step-dist {
	color: #6b7280;
}

/* Mobile reflow — narrow viewports get a bottom drawer instead
 * of an edge panel. The configured width is replaced by full-width
 * and a fixed dynamic-viewport height, mirroring the spirit of the
 * listings sidebar's mobile drawer.
 *
 * Two iOS-Safari–driven choices here:
 *   1. `position: fixed` instead of `absolute`. Anchoring to the
 *      visual viewport means the drawer is independent of
 *      canvas-host's layout — any reflow of the map element (e.g.
 *      address-bar collapse changing the page chrome height) can't
 *      drag the drawer along, which is what produced the user's
 *      reported "map jerks UP" the instant the directions panel
 *      mounted. The drawer just stays glued to viewport bottom.
 *   2. `dvh` (dynamic viewport height) instead of `vh`. On iOS
 *      Safari `vh` is locked to the LARGEST possible viewport (no
 *      address bar), so 60vh always under-reports when the bar is
 *      visible — every state change that nudges the address bar
 *      causes the drawer to "snap" to a new height. `dvh`
 *      interpolates with the visual viewport, so the drawer's
 *      visible height stays stable across browser-chrome changes. */
@media (max-width: 768px) {
	.rmaps-react-directions-sidebar {
		position: fixed !important;
		top: auto;
		bottom: 0;
		left: 0;
		right: 0;
		width: 100% !important;
		max-width: 100%;
		height: 60dvh;
		max-height: 60dvh;
		box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.16);
	}
	/* Mobile slide animation — three states:
	 *   • `.is-open`              → translateY(0), visible
	 *   • `.is-collapsed`         → translateY(101%), off-screen
	 *                                BELOW. Normal close direction
	 *                                (× dismiss, no successor).
	 *   • `.is-collapsed-up`      → translateY(-101%), off-screen
	 *                                ABOVE. Used when the other
	 *                                sidebar (contact) is taking
	 *                                over — directions slides UP off
	 *                                the top while contact slides UP
	 *                                from below at the same time.
	 *                                The two panels occupy DIFFERENT
	 *                                vertical bands during the
	 *                                transition (no overlap), so the
	 *                                visitor sees a clean conveyor-
	 *                                belt swap instead of a mashed
	 *                                cross-fade.
	 *
	 * Pinning the open state to translateY(0) is also necessary —
	 * without it the open state would inherit the desktop base's
	 * `translateX(0)`, and the browser would interpolate between two
	 * different transform functions during the slide, producing the
	 * "jumping from the top" the visitor reported. */
	.rmaps-react-directions-sidebar.is-open {
		transform: translateY(0);
		opacity: 1;
	}
	.rmaps-react-directions-sidebar.is-collapsed {
		transform: translateY(101%);
		opacity: 0;
	}
	.rmaps-react-directions-sidebar.is-collapsed-up {
		transform: translateY(-101%);
		opacity: 0;
	}
}

/* Contact-form sidebar — left-anchored overlay that hosts the
 * marker's contact form (built-in OR Contact Form 7 shortcode).
 * Structural / behavioural parallel of `directionsSidebar.css`:
 * same toggle chevron, same slide transition, same body scroll +
 * scrollbar styling. The only deltas are colour-neutral semantics
 * (the title icon is an envelope rather than a location arrow)
 * and a slightly different stacking slot — kept distinct from the
 * directions sidebar's z-index so a stale paint never lets the
 * two overlap silently.
 *
 * The sidebar's body deliberately wears the `rmaps-listing-content`
 * class so the popup-wide form styling (input height 30 px, submit
 * button chrome, CF7 overrides, response chips) applies verbatim
 * to the form rendered inside — no duplication.
 *
 * Directions + contact panels are mutually exclusive (the reducer
 * clears one when the other opens) so they're allowed to share the
 * left edge. Both render the toggle button in front of the panel
 * (z 721 / 731 below) and the sidebar slabs slightly behind (z 720
 * / 730), so the chevron always reads as the topmost reachable
 * widget regardless of which surface is in play.
 */

.rmaps-react-contact-sidebar {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	max-width: calc(100% - 36px);
	background: #fff;
	box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	/* Same z-index as DirectionsSidebar — they swap via reducer
	 * mutual exclusion and need to cross-fade at the same level so
	 * neither paints solidly OVER the other during the mobile
	 * bottom-drawer swap. The opacity transition (mobile @media
	 * below) handles the visual blend. Both still below
	 * click-popup (z 1000 / 1500). */
	z-index: 720;
	transform: translateX(0);
	transition: transform 0.25s ease, opacity 0.25s ease;
	will-change: transform, opacity;
	opacity: 1;
	color: #1f2937;
}
.rmaps-react-contact-sidebar.is-collapsed,
.rmaps-react-contact-sidebar.is-collapsed-up {
	transform: translateX(-100%);
}

/* Toggle button intentionally removed — symmetrical with
 * DirectionsSidebar. The × in the header is the only dismiss
 * affordance the contact panel exposes (along with the toggle on
 * the popup's "Send message" button, which also dispatches
 * CLEAR_CONTACT when re-clicked). */

/* Header — title + ×. The × is the explicit "I'm done with this
 * form" action; it dispatches CLEAR_CONTACT which slides the panel
 * out and unmounts it. */
.rmaps-react-contact-sidebar__header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 12px 14px;
	border-bottom: 1px solid #e5e7eb;
	background: #f9fafb;
	flex: 0 0 auto;
}
.rmaps-react-contact-sidebar__title {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-size: 14px;
	font-weight: 600;
	color: #111827;
}
.rmaps-react-contact-sidebar__title .rmaps-fa {
	font-family: 'FontAwesome';
	font-style: normal;
	font-weight: 400;
	font-size: 14px;
	color: var(--rmaps-primary, #2563eb);
	line-height: 1;
}
.rmaps-react-contact-sidebar__title .rmaps-fa-envelope::before { content: '\f0e0'; }

.rmaps-react-contact-sidebar__close,
.rmaps-react-contact-sidebar__close:hover,
.rmaps-react-contact-sidebar__close:focus,
.rmaps-react-contact-sidebar__close:active {
	border: 0;
	background: none;
	background-color: transparent;
	font-size: 22px;
	line-height: 1;
	color: #6b7280;
	cursor: pointer;
	padding: 0 4px;
	box-shadow: none;
	outline: none;
}
.rmaps-react-contact-sidebar__close:hover { color: #111827; }

/* Body — scroll container for the form HTML. */
.rmaps-react-contact-sidebar__body {
	flex: 1 1 auto;
	overflow-y: auto;
	overflow-x: hidden;
	padding: 14px;
	box-sizing: border-box;
	scrollbar-width: thin;
	scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
}
.rmaps-react-contact-sidebar__body::-webkit-scrollbar {
	width: 14px;
	height: 14px;
}
.rmaps-react-contact-sidebar__body::-webkit-scrollbar-track,
.rmaps-react-contact-sidebar__body::-webkit-scrollbar-corner {
	background: transparent;
}
.rmaps-react-contact-sidebar__body::-webkit-scrollbar-thumb {
	background-color: rgba(0, 0, 0, 0.2);
	background-clip: padding-box;
	border: 5px solid transparent;
	border-radius: 7px;
	-webkit-transition: border-width 0.18s ease, background-color 0.18s ease;
	transition: border-width 0.18s ease, background-color 0.18s ease;
}
.rmaps-react-contact-sidebar__body:hover::-webkit-scrollbar-thumb {
	border-width: 3px;
	background-color: rgba(0, 0, 0, 0.32);
}
.rmaps-react-contact-sidebar__body::-webkit-scrollbar-thumb:hover {
	background-color: rgba(0, 0, 0, 0.5);
	border-width: 2px;
}

/* Form-body reset — the body wears `.rmaps-listing-content` so any
 * popup-shared chrome (chips, hours table, distance badge styling,
 * etc.) renders consistently, but the form section doesn't have the
 * popup's column-of-fields layout. Drop the wrapper's flex layout
 * so the form's own block flow is unaffected. */
.rmaps-react-contact-sidebar__body.rmaps-listing-content {
	display: block;
	gap: 0;
}

/* ============================================================
 * Form styling — sidebar-scoped overrides so the contact form
 * picks up the same input chrome the rest of the plugin uses
 * (DirectionsSidebar inputs, SearchForm inputs, sidebar buttons).
 *
 * Important note on selector scoping:
 *   The form HTML is extracted from `.rmaps-popup__value` (inside
 *   the popup's contact field) before being passed to this
 *   sidebar — the `.rmaps-popup__field--contact_form` and
 *   `.rmaps-popup__field--cf7` parent wrappers stay in the popup
 *   and do NOT travel to the sidebar. So the popup's rules
 *   (scoped under those parents) DON'T apply here — which is the
 *   "form has no styles" symptom that motivated this block.
 *
 *   These rules therefore scope by the FORM's own classes —
 *   `.rmaps-popup__contact-form` (built-in) and `.wpcf7-form`
 *   (CF7) — which DO travel to the sidebar inside the extracted
 *   HTML. No `--cf7` parent prefix anywhere.
 *
 * Geometry: matches DirectionsSidebar — height 32 px, font 13 px,
 * border-radius 6 px, brand-primary focus ring; submit button is
 * a full-width "Go"-style chip.
 * ============================================================ */

/* Wrapper layout — looser column with a sensible inter-field gap. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form,
.rmaps-react-contact-sidebar__body .wpcf7-form {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin: 0;
	background: transparent !important;
	border: 0 !important;
	color: inherit !important;
	text-shadow: none !important;
	padding: 0 !important;
}

/* Field labels — CF7 puts label text in `<p>` rows (sometimes
 * `<label>`), the built-in form uses `<label>` directly. Style
 * both as the same small-grey label form factor. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form label,
.rmaps-react-contact-sidebar__body .wpcf7-form p,
.rmaps-react-contact-sidebar__body .wpcf7-form label {
	font-size: 12px !important;
	line-height: 1.4 !important;
	color: #374151;
	margin: 0 !important;
	display: block;
}

/* Inputs / textareas / select — full-width, 32 px tall, 13 px text.
 * Border + focus ring use the brand primary so the form reads as
 * part of the plugin's UI rather than a generic <form>. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input[type="text"],
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input[type="email"],
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form textarea,
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="text"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="email"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="tel"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="url"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="number"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="date"],
.rmaps-react-contact-sidebar__body .wpcf7-form select,
.rmaps-react-contact-sidebar__body .wpcf7-form textarea {
	width: 100%;
	box-sizing: border-box;
	font-size: 13px;
	font-family: inherit;
	color: #1f2937;
	background: #fff;
	border: 1px solid #d1d5db;
	border-radius: 6px;
	padding: 0 10px;
	line-height: 1;
	transition: border-color 0.12s, box-shadow 0.12s;
	text-shadow: none !important;
}

/* Single-line inputs — explicit 32 px to match the directions
 * sidebar input + Go button. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input[type="text"],
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input[type="email"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="text"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="email"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="tel"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="url"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="number"],
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="date"],
.rmaps-react-contact-sidebar__body .wpcf7-form select {
	height: 32px;
	min-height: 0;
}

/* Textarea — multi-line, generous height range. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form textarea,
.rmaps-react-contact-sidebar__body .wpcf7-form textarea {
	padding: 8px 10px;
	line-height: 1.4;
	min-height: 100px;
	max-height: 240px;
	resize: vertical;
}

/* Focus ring — brand-primary border + soft shadow halo. Same
 * pattern as `.rmaps-react-directions-sidebar__input-row:focus-within`,
 * applied directly to the control here since CF7 markup gives no
 * parent row container to scope :focus-within against. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input:focus,
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form textarea:focus,
.rmaps-react-contact-sidebar__body .wpcf7-form input:focus,
.rmaps-react-contact-sidebar__body .wpcf7-form textarea:focus,
.rmaps-react-contact-sidebar__body .wpcf7-form select:focus {
	outline: none;
	border-color: var(--rmaps-primary, #2563eb);
	box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}

/* Placeholder copy — slightly muted but legible against white. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input::-moz-placeholder, .rmaps-react-contact-sidebar__body .rmaps-popup__contact-form textarea::-moz-placeholder, .rmaps-react-contact-sidebar__body .wpcf7-form input::-moz-placeholder, .rmaps-react-contact-sidebar__body .wpcf7-form textarea::-moz-placeholder {
	color: #9ca3af;
}
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form input::placeholder,
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form textarea::placeholder,
.rmaps-react-contact-sidebar__body .wpcf7-form input::placeholder,
.rmaps-react-contact-sidebar__body .wpcf7-form textarea::placeholder {
	color: #9ca3af;
}

/* Submit button — visually the "Go" twin from DirectionsSidebar:
 * primary background, 32 px tall, full width, brand hover.
 * `!important` is necessary because CF7's theme stylesheets and
 * the host theme often ship high-specificity rules against
 * `input[type="submit"]` that would otherwise stomp ours. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form .rmaps-popup__contact-submit,
.rmaps-react-contact-sidebar__body .wpcf7-form .wpcf7-submit,
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="submit"],
.rmaps-react-contact-sidebar__body .wpcf7-form button[type="submit"] {
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	width: 100% !important;
	box-sizing: border-box;
	height: 32px !important;
	min-height: 0 !important;
	padding: 0 14px !important;
	margin: 4px 0 0 !important;
	font-size: 13px !important;
	font-weight: 600;
	font-family: inherit;
	line-height: 1;
	color: #fff !important;
	background: var(--rmaps-primary, #2563eb) !important;
	border: 0 !important;
	border-radius: 6px !important;
	cursor: pointer;
	text-align: center;
	text-transform: none;
	text-shadow: none !important;
}
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form .rmaps-popup__contact-submit:hover:not(:disabled),
.rmaps-react-contact-sidebar__body .wpcf7-form .wpcf7-submit:hover:not(:disabled),
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="submit"]:hover:not(:disabled),
.rmaps-react-contact-sidebar__body .wpcf7-form button[type="submit"]:hover:not(:disabled) {
	filter: brightness(1.05);
}
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-form .rmaps-popup__contact-submit:disabled,
.rmaps-react-contact-sidebar__body .wpcf7-form .wpcf7-submit:disabled,
.rmaps-react-contact-sidebar__body .wpcf7-form input[type="submit"]:disabled {
	opacity: 0.6;
	cursor: not-allowed;
}

/* Status row (built-in form) — small chip-style message under the
 * submit button. Sender's strings ship as innerHTML; styles only
 * colour them. */
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-status {
	font-size: 12px;
	margin-top: 6px;
	color: #6b7280;
}
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-status[data-state="ok"]  { color: #15803d; }
.rmaps-react-contact-sidebar__body .rmaps-popup__contact-status[data-state="err"] { color: #b91c1c; }

/* CF7 status response — coloured background chip for sent / failed
 * states. */
.rmaps-react-contact-sidebar__body .wpcf7-response-output {
	margin: 8px 0 0 !important;
	padding: 8px 10px !important;
	font-size: 12px;
	border-radius: 6px;
	border: 1px solid transparent !important;
}
.rmaps-react-contact-sidebar__body .wpcf7-response-output:empty {
	display: none !important;
}
.rmaps-react-contact-sidebar__body .wpcf7-form.sent .wpcf7-response-output,
.rmaps-react-contact-sidebar__body .wpcf7-mail-sent-ok {
	color: #15803d !important;
	background: #f0fdf4;
	border-color: #bbf7d0 !important;
}
.rmaps-react-contact-sidebar__body .wpcf7-form.invalid .wpcf7-response-output,
.rmaps-react-contact-sidebar__body .wpcf7-form.failed .wpcf7-response-output,
.rmaps-react-contact-sidebar__body .wpcf7-validation-errors,
.rmaps-react-contact-sidebar__body .wpcf7-mail-sent-ng,
.rmaps-react-contact-sidebar__body .wpcf7-spam-blocked {
	color: #b91c1c !important;
	background: #fef2f2;
	border-color: #fecaca !important;
}

/* Per-field validation tip and invalid border highlight (CF7). */
.rmaps-react-contact-sidebar__body .wpcf7-not-valid-tip {
	font-size: 12px;
	color: #b91c1c;
	margin-top: 3px;
}
.rmaps-react-contact-sidebar__body .wpcf7-not-valid {
	border-color: #fca5a5 !important;
}
.rmaps-react-contact-sidebar__body .wpcf7-spinner {
	width: 20px;
	height: 20px;
	margin: 0 0 0 8px;
}

/* Mobile reflow — same drawer pattern as DirectionsSidebar (see
 * the long comment over there for why `position: fixed` + `dvh`
 * are necessary on iOS to keep the drawer stable across visual-
 * viewport changes). */
@media (max-width: 768px) {
	.rmaps-react-contact-sidebar {
		position: fixed !important;
		top: auto;
		bottom: 0;
		left: 0;
		right: 0;
		width: 100% !important;
		max-width: 100%;
		height: 60dvh;
		max-height: 60dvh;
		box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.16);
	}
	/* Mobile slide animation — symmetrical with DirectionsSidebar
	 * (see the comment over there for the full rationale):
	 *   • `.is-open`             → translateY(0), visible
	 *   • `.is-collapsed`        → translateY(101%), off-screen
	 *                               BELOW. Normal close (× dismiss).
	 *   • `.is-collapsed-up`     → translateY(-101%), off-screen
	 *                               ABOVE. Used when DirectionsSidebar
	 *                               is taking over. Both panels slide
	 *                               UP together → no visual overlap. */
	.rmaps-react-contact-sidebar.is-open {
		transform: translateY(0);
		opacity: 1;
	}
	.rmaps-react-contact-sidebar.is-collapsed {
		transform: translateY(101%);
		opacity: 0;
	}
	.rmaps-react-contact-sidebar.is-collapsed-up {
		transform: translateY(-101%);
		opacity: 0;
	}
}

/* Listings sidebar — absolute overlay above the map. Width (left/right) or
 * height (top/bottom) comes from the metabox. Slide animation uses transform
 * only — never width/height — so the map canvas is NEVER resized during
 * open/close (no Google Maps redraw, no jank). */

/* Single-source CSS var driving the mobile drawer's height. Declared via
 * `@property` so it's animatable through CSS transitions. Both the
 * sidebar's `height` AND the toggle's `bottom` read from this same var,
 * so every frame they resolve to identical interpolated values from one
 * source — guaranteeing the toggle stays glued to the drawer's top edge
 * with zero phase lag. Without @property, custom properties default to
 * type `*` (any value) which is non-interpolable, and a CSS transition
 * on the var would snap rather than animate. */
@property --rmaps-mobile-drawer-h {
	syntax: '<length>';
	inherits: true;
	initial-value: 0px;
}

/* Theme-independent rendering. A host theme's dark mode (e.g.
 * `html[data-theme="dark"] { color-scheme: dark }`, or a
 * `@media (prefers-color-scheme: dark)` rule) leaks into the plugin two
 * ways:
 *   1. `color-scheme: dark` CASCADES into every native form control —
 *      the plugin's checkboxes, radios, range sliders, <select>
 *      dropdowns and scroll bars render inverted (dark fills) on the
 *      plugin's own light backgrounds.
 *   2. The theme's `body { color: <light-in-dark> }` is INHERITED by
 *      the plugin's text that doesn't set its own colour (field labels,
 *      checklist item text, the price caption…), so the copy turns near-
 *      white on the plugin's light card.
 * The plugin paints its own light UI and is NOT meant to follow the
 * site theme's light/dark switch, so pin every front-end React root to
 * `color-scheme: light` AND re-assert the plugin's base text colour.
 * `color` only reaches elements that don't set their own, so explicit
 * plugin colours are untouched; the map tiles' dark style (an engine
 * style swap, unrelated to `color-scheme`/`color`) is also untouched. */
.rmaps-react-mount,
.rmaps-react-map-wrapper,
.rmaps-react-listings-standalone,
.rmaps-react-search-standalone {
	color-scheme: light;
	color: #1f2937;
}

.rmaps-react-map-wrapper {
	position: relative;
	/* Clip the listings sidebar's translated-off-screen state so the cards
	 * don't bleed onto the surrounding page background. The toggle button
	 * sits at x=0..36px (relative to wrapper) when collapsed — INSIDE the
	 * clip rect — so it stays visible/clickable. */
	overflow: hidden;
	/* Flex column lets the responsive search form (search-form.css) pop out
	 * of the corner and claim its own row above or below the canvas on
	 * narrow viewports. order:0 (form-above) / order:1 (canvas) / order:2
	 * (form-below) gives correct stacking regardless of the form's DOM
	 * position. On desktop the form is `position: absolute` and ignores
	 * flex order entirely, so the layout is unaffected. */
	display: flex;
	flex-direction: column;
}
.rmaps-react-map-canvas-host {
	position: relative;
	/* Isolate the map's stacking context. Google Maps / Mapbox / MapLibre
	 * inject marker DOM elements with high z-index values (often 4-digit)
	 * into the map div. Without `isolation: isolate`, canvas-host doesn't
	 * create a stacking context (position:relative + z-index:auto isn't
	 * enough), so those marker z-indices resolve against the WRAPPER's
	 * stacking context — and rise above the in-map search form (z 700),
	 * making clicks on the form pass through to whichever marker happens
	 * to sit under the cursor. `isolation: isolate` traps every descendant
	 * z-index inside canvas-host, so the form's 700 (in wrapper context)
	 * cleanly beats canvas-host's auto (also wrapper context). */
	isolation: isolate;
	/* Desktop: flex-grow:1 fills the wrapper (which inherits the PHP mount
	 * div's fixed height) — no empty band below the map even if the
	 * inline `height` style we pass for the mobile path is smaller than
	 * the wrapper. */
	flex: 1 1 auto;
	min-height: 0;
	width: 100%;
	order: 1;
}
/* Mobile flow: search form claims its own row above/below the map. The
 * wrapper (and the PHP mount div around it) grow to fit form +
 * canvas-host, while the canvas locks to its inline `height` (= the
 * configured map height) instead of being squeezed by the flex row.
 * `flex: 0 0 auto` disables grow/shrink so inline height is honoured
 * verbatim. */
@media (max-width: 768px) {
	.rmaps-react-mount {
		height: auto !important;
	}
	.rmaps-react-map-wrapper {
		height: auto !important;
	}

	/* Mobile architecture: drawer is a FLEX CHILD of canvas-host, not
	 * an absolute overlay. Canvas-host switches to a vertical flex
	 * column that stacks:
	 *
	 *     ┌──────────────────────────────┐
	 *     │  .rmaps-react-map-canvas     │  ← stays at the configured
	 *     │  (the actual map, locked     │     map height (e.g. 400px)
	 *     │  to --rmaps-map-area-height) │     via flex-basis = the
	 *     │                              │     CSS var emitted by
	 *     ├──────────────────────────────┤     MapApp.tsx
	 *     │  .rmaps-react-sidebar        │
	 *     │  (drawer, 50vh when open,    │  ← grows / shrinks; canvas-
	 *     │  height: 0 when collapsed)   │     host's total height
	 *     └──────────────────────────────┘     follows.
	 *
	 * Both map and drawer share the SAME visible container — canvas-
	 * host's bounding box wraps them together. No `position:
	 * absolute` outside the host, no margin/padding hack to "reserve"
	 * space below — canvas-host just grows naturally with its flex
	 * children.
	 *
	 * Flex order: the React fragment renders the toggle button
	 * first, then the sidebar div, then the map canvas. We use
	 * `order: 1` on the sidebar so the map (order: 0 default) comes
	 * first visually, then the drawer.
	 *
	 * Toggle button stays `position: absolute` (NOT a flex item) and
	 * anchors at `bottom: var(--rmaps-sidebar-open-size, 0)` so it
	 * tracks the boundary between map and drawer — at canvas-host's
	 * bottom when collapsed (sidebar height 0), and at the drawer's
	 * top edge when open (sidebar height = the var).
	 *
	 * Map controls (zoom, fullscreen, pegman, counter, search form)
	 * are absolute children of canvas-host (or its descendants) and
	 * keep their default corners — the drawer no longer covers the
	 * map, so the desktop's translate-shift would only push them
	 * out of view. All shifts cancelled via `transform: none`.
	 */
	.rmaps-react-map-wrapper {
		--rmaps-mobile-drawer-h: 0px;
		transition: --rmaps-mobile-drawer-h 0.25s ease;
	}
	.rmaps-react-map-wrapper.rmaps-sidebar-open {
		--rmaps-mobile-drawer-h: 50vh;
	}
	.rmaps-react-map-canvas-host {
		flex: 0 0 auto;
		display: flex !important;
		flex-direction: column !important;
		height: auto !important;
	}

	/* Inner map element keeps the configured pixel height (set by
	 * MapApp.tsx as `--rmaps-map-area-height` on canvas-host).
	 * Without an explicit height the inline `height: 100%` would
	 * collapse to 0 once canvas-host becomes auto-sized. */
	.rmaps-react-map-canvas-host .rmaps-react-map-canvas {
		flex: 0 0 var(--rmaps-map-area-height, 400px) !important;
		height: var(--rmaps-map-area-height, 400px) !important;
		width: 100% !important;
		order: 0;
	}

	/* Fullscreen on mobile — the wrapper picks up `.rmaps-fs-host`
	 * (see search-form.css), which makes it a viewport-sized flex
	 * column with the search form on top and the canvas-host below.
	 * The static-flow rules above lock canvas-host to `flex: 0 0
	 * auto` + the inner canvas to the configured pixel height so the
	 * page can scroll past the form-then-map stack; in fullscreen the
	 * viewport IS the container, no scroll, and the lock leaves a
	 * black band below the canvas where the wrapper extends beyond
	 * the map area. Override both rules so canvas-host claims the
	 * remaining viewport and the canvas fills it. The mobile drawer
	 * stays inside canvas-host so its own slice still tracks
	 * `--rmaps-mobile-drawer-h` cleanly. */
	.rmaps-fs-host .rmaps-react-map-canvas-host {
		flex: 1 1 auto !important;
		min-height: 0 !important;
	}
	.rmaps-fs-host .rmaps-react-map-canvas-host .rmaps-react-map-canvas {
		flex: 1 1 auto !important;
		height: auto !important;
	}

	/* Sidebar reflows from absolute overlay → flex child. Sits
	 * below the map (order: 1) with full container width and 50vh
	 * height when open. Transitions on `height` animate the
	 * grow / shrink (and canvas-host's total height follows via
	 * flex layout). */
	.rmaps-react-sidebar--left,
	.rmaps-react-sidebar--right {
		position: relative !important;
		top:        auto !important;
		bottom:     auto !important;
		left:       auto !important;
		right:      auto !important;
		width:      100% !important;
		max-width:  100% !important;
		/* Height bound to the wrapper-level animated var — the var
		 * itself transitions (see @property + transition on wrapper),
		 * so we DON'T declare a separate transition on this element.
		 * One source of truth ⇒ zero phase desync with the toggle. */
		height:     var(--rmaps-mobile-drawer-h, 0px) !important;
		overflow:   hidden !important;
		flex:       0 0 auto !important;
		order:      1;
		transform:  none !important;
		transition: none !important;
	}

	/* Toggle button — `bottom` reads the SAME `--rmaps-mobile-drawer-h`
	 * the sidebar uses for its height. Since the var transitions on
	 * the wrapper element (@property animation), both elements
	 * resolve to identical interpolated values from the same source
	 * each frame — no separate per-element transition that could
	 * fall out of phase. */
	.rmaps-react-sidebar__toggle--left,
	.rmaps-react-sidebar__toggle--right {
		top:    auto !important;
		right:  auto !important;
		left:   50%  !important;
		bottom: var(--rmaps-mobile-drawer-h, 0px) !important;
		transform: translateX(-50%) !important;
		width:  80px !important;
		height: 36px !important;
		border-radius: 8px 8px 0 0 !important;
		transition: background-color 0.15s ease !important;
	}

	/* Chevron — drawer slides vertically, so arrow needs ▼ when
	 * OPEN (tap to push back down) and ▲ when COLLAPSED (tap to
	 * lift up from below). */
	.rmaps-react-sidebar__toggle--left.is-collapsed .rmaps-react-sidebar__toggle-icon,
	.rmaps-react-sidebar__toggle--right.is-collapsed .rmaps-react-sidebar__toggle-icon {
		transform: rotate(-90deg) !important;
	}
	.rmaps-react-sidebar__toggle--left.is-open .rmaps-react-sidebar__toggle-icon,
	.rmaps-react-sidebar__toggle--right.is-open .rmaps-react-sidebar__toggle-icon {
		transform: rotate(90deg) !important;
	}

	/* List → grid promotion (full-width drawer fits multiple columns
	 * better than one giant card). */
	.rmaps-react-sidebar--left  .rmaps-react-sidebar__grid--list,
	.rmaps-react-sidebar--right .rmaps-react-sidebar__grid--list {
		grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)) !important;
	}

	/* Cancel desktop control shifts on mobile ONLY when sidebar is
	 * configured as left/right — those positions reflow into a
	 * bottom-attached drawer, and the controls (zoom, fullscreen,
	 * pegman, GL ctrl-corners, search form, marker counter) live
	 * INSIDE `.rmaps-react-map-canvas` (fixed-height map div), so
	 * their absolute positions are already correct. Any compensating
	 * translate would just animate them out of place.
	 *
	 * has-sidebar--bottom is INTENTIONALLY OMITTED here — that
	 * position doesn't reflow on mobile (sidebar already sits at the
	 * bottom of canvas-host as an absolute overlay on both desktop
	 * and mobile). The desktop "push bottom-anchored controls up by
	 * sidebar height" rule (lines ~395-405) continues to apply, so
	 * pegman, zoom pad, counter and the bottom-anchored search form
	 * float up by the sidebar's height when the drawer opens.
	 *
	 * has-sidebar--top is also untouched — same rationale (no mobile
	 * reflow, desktop "push top controls down" applies as expected). */
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .gm-fullscreen-control,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .gm-bundled-control,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .gm-svpc,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .maplibregl-ctrl-top-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .maplibregl-ctrl-top-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .maplibregl-ctrl-bottom-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .maplibregl-ctrl-bottom-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .mapboxgl-ctrl-top-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .mapboxgl-ctrl-top-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .mapboxgl-ctrl-bottom-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .mapboxgl-ctrl-bottom-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .rmaps-map-counter,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .rmaps-search-form,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .gm-fullscreen-control,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .gm-bundled-control,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .gm-svpc,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .maplibregl-ctrl-top-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .maplibregl-ctrl-top-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .maplibregl-ctrl-bottom-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .maplibregl-ctrl-bottom-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .mapboxgl-ctrl-top-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .mapboxgl-ctrl-top-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .mapboxgl-ctrl-bottom-left,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .mapboxgl-ctrl-bottom-right,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .rmaps-map-counter,
	.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .rmaps-search-form {
		transform: none !important;
	}
}

/* "Edit map" affordance — emitted by `map_controller::display()`
 * when the current visitor has `edit_post` capability on the map
 * post. Rendered OUTSIDE the map mount as a sibling, right-aligned
 * below the map's bottom-right corner. Doesn't compete with the GL
 * engine's on-canvas controls (attribution, zoom buttons, geolocator
 * widget) — sits in the page flow underneath the map. */
.rmaps-map-frontend-actions {
	display: flex;
	justify-content: flex-end;
	margin-top: 8px;
}
.rmaps-map-frontend-edit-link {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	padding: 5px 12px;
	font-size: 12px;
	font-weight: 500;
	background: #fff;
	color: #2563eb;
	border: 1px solid #2563eb;
	border-radius: 4px;
	text-decoration: none;
	line-height: 1.2;
}
.rmaps-map-frontend-edit-link:hover,
.rmaps-map-frontend-edit-link:focus {
	background: #2563eb;
	color: #fff;
	text-decoration: none;
}
.rmaps-map-frontend-edit-link::before {
	content: "\270E";
	font-size: 14px;
	line-height: 1;
}
.rmaps-react-map-wrapper > .rmaps-search-form--top-left,
.rmaps-react-map-wrapper > .rmaps-search-form--top-right    { order: 0; }
.rmaps-react-map-wrapper > .rmaps-search-form--bottom-left,
.rmaps-react-map-wrapper > .rmaps-search-form--bottom-right { order: 2; }

/* On mobile, in-map search forms always attach to the TOP of the map
 * (above canvas-host) regardless of the admin-configured corner —
 * bottom-anchored forms would otherwise land below the drawer or off
 * to the side, far from the map they apply to.
 *
 * `transform: none` is necessary here because the desktop bottom-
 * sidebar shift rule (lines ~395-405) applies `translateY(-var)` to
 * `.rmaps-search-form--bottom-*` so it floats above the bottom
 * sidebar. With the form now reordered to the TOP of the wrapper
 * on mobile, that upward shift would push it off-screen above the
 * viewport. Clearing the transform keeps the form at its natural
 * flex position.
 *
 * The exception is sidebar=top: that already places the sidebar
 * above the map, and the existing translateY rule (line ~386)
 * keeps the form between the sidebar and the map — preserve that
 * arrangement by leaving the desktop order in place (form-bottom
 * keeps order:2). */
@media (max-width: 768px) {
	.rmaps-react-map-wrapper:not(.has-sidebar--top) > .rmaps-search-form--bottom-left,
	.rmaps-react-map-wrapper:not(.has-sidebar--top) > .rmaps-search-form--bottom-right {
		order: 0 !important;
		transform: none !important;
	}
}

.rmaps-react-sidebar {
	position: absolute;
	background: #fff;
	box-shadow: 0 0 8px rgba(0, 0, 0, 0.08);
	overflow: visible;          /* let the toggle button bleed out */
	box-sizing: border-box;
	/* Stacking order (inside canvas-host's stacking context, scoped by
	 * `isolation: isolate`):
	 *   - canvasOverlayShim pane         z 5
	 *   - clustered marker icons          z 6
	 *   - auto-popup layer                z 600
	 *   - sidebar                         z 700  ← THIS — sits ABOVE the
	 *                                              auto-popup layer so
	 *                                              markers fanning out
	 *                                              from a left-edge
	 *                                              marker don't leak
	 *                                              over the sidebar's
	 *                                              listing cards (was
	 *                                              z 10 before, where
	 *                                              auto-popups won).
	 *   - click popup                     z 1000 (still on top of sidebar
	 *                                              so a marker click can
	 *                                              open a popup that
	 *                                              briefly overlays the
	 *                                              sidebar). */
	z-index: 700;
	transition: transform 0.25s ease;
	will-change: transform;
}

/* Map-control shift while the sidebar is open. `MapSidebar` writes
 * `--rmaps-sidebar-open-size: <N>px` on the wrapper when expanded
 * (`0px` when collapsed), plus toggles the `rmaps-sidebar-open` class
 * so the rules below are scoped — controls return to their default
 * positions the moment the sidebar slides off-screen.
 *
 * Covered controls (Google Maps): fullscreen button, zoom/compass
 * pad, Pegman / Street View peg. Attribution + "Условия / Terms" are
 * NOT shifted (legal text, must remain visible verbatim where Google
 * places it).
 *
 * Covered controls (Mapbox / MapLibre GL): all four corner ctrl-
 * containers — we just shift the whole stack on the affected side.
 *
 * Custom controls: the marker counter chip (`.rmaps-map-counter`,
 * bottom-right by default) follows the same rules.
 *
 * Transition timing matches the sidebar's own 0.25s slide above, so
 * the controls glide in sync with the sidebar edge. */
.rmaps-react-map-wrapper .gm-fullscreen-control,
.rmaps-react-map-wrapper .gm-bundled-control,
.rmaps-react-map-wrapper .gm-svpc,
.rmaps-react-map-wrapper .maplibregl-ctrl-top-right,
.rmaps-react-map-wrapper .maplibregl-ctrl-bottom-right,
.rmaps-react-map-wrapper .maplibregl-ctrl-top-left,
.rmaps-react-map-wrapper .maplibregl-ctrl-bottom-left,
.rmaps-react-map-wrapper .mapboxgl-ctrl-top-right,
.rmaps-react-map-wrapper .mapboxgl-ctrl-bottom-right,
.rmaps-react-map-wrapper .mapboxgl-ctrl-top-left,
.rmaps-react-map-wrapper .mapboxgl-ctrl-bottom-left,
.rmaps-react-map-wrapper .rmaps-map-counter,
.rmaps-react-map-wrapper .rmaps-search-form,
.rmaps-react-map-wrapper .rmaps-directions-bar {
	transition: transform 0.25s ease;
}

/* Sidebar on the RIGHT → pull right-anchored controls LEFT by sidebar width.
 * Search form gets shifted only when its OWN corner is on the right
 * (top-right / bottom-right) so a left-anchored form stays put.
 *
 * `.gm-svpc` (Street View Pegman) deliberately NOT included: its
 * position is admin-configurable via `streetViewControlOptions.position`
 * and CSS can't tell which corner Google placed it in. On setups where
 * it lives in a left or top corner, a blanket left-shift moves it
 * away from where the visitor expects to grab it. Leave it where
 * Google put it; if it lands behind a right-positioned sidebar the
 * visitor can collapse the sidebar to reach it. */
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .gm-fullscreen-control,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .gm-bundled-control,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .maplibregl-ctrl-top-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .maplibregl-ctrl-bottom-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .mapboxgl-ctrl-top-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .mapboxgl-ctrl-bottom-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .rmaps-map-counter,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .rmaps-search-form--top-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--right .rmaps-search-form--bottom-right {
	transform: translateX(calc(var(--rmaps-sidebar-open-size, 0px) * -1));
}

/* Sidebar on the LEFT → push left-anchored controls (GL ctrl-containers +
 * left-corner search form) RIGHT. Google's built-in controls all live on
 * the right side by default, so there's nothing on the LEFT to shift for
 * Google maps. */
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .maplibregl-ctrl-top-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .maplibregl-ctrl-bottom-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .mapboxgl-ctrl-top-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .mapboxgl-ctrl-bottom-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .rmaps-search-form--top-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--left .rmaps-search-form--bottom-left {
	transform: translateX(var(--rmaps-sidebar-open-size, 0px));
}

/* Sidebar on TOP → push top-anchored controls DOWN. */
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .gm-fullscreen-control,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .maplibregl-ctrl-top-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .maplibregl-ctrl-top-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .mapboxgl-ctrl-top-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .mapboxgl-ctrl-top-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .rmaps-search-form--top-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--top .rmaps-search-form--top-right {
	transform: translateY(var(--rmaps-sidebar-open-size, 0px));
}

/* Sidebar on BOTTOM → pull bottom-anchored controls UP.
 * `.gm-svpc` (Street View Pegman) is INTENTIONALLY EXCLUDED — Google
 * places pegman with inline `top: X` (top-anchored) by default in
 * many setups. A `translateY(-var)` would move a top-anchored pegman
 * UP off the map; for a bottom-anchored pegman the shift would be
 * correct, but we can't distinguish anchor from CSS. Admins who
 * want a clearance from the bottom sidebar should position pegman
 * elsewhere via the Street View metabox. */
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .gm-bundled-control,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .maplibregl-ctrl-bottom-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .maplibregl-ctrl-bottom-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .mapboxgl-ctrl-bottom-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .mapboxgl-ctrl-bottom-right,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .rmaps-map-counter,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .rmaps-search-form--bottom-left,
.rmaps-react-map-wrapper.rmaps-sidebar-open.has-sidebar--bottom .rmaps-search-form--bottom-right {
	transform: translateY(calc(var(--rmaps-sidebar-open-size, 0px) * -1));
}
.rmaps-react-sidebar__scroll {
	width: 100%;
	height: 100%;
	overflow: auto;
	box-sizing: border-box;
	padding: 10px;
}

/* Win 11–style thin scrollbar that thickens on hover. The container width is
 * always 14 px; the thumb sits inside a transparent border that we shrink on
 * hover so the thumb appears to expand smoothly without the layout reflowing.
 * Firefox honours scrollbar-width / -color but cannot animate the width. */
.rmaps-react-sidebar__scroll {
	scrollbar-width: thin;
	scrollbar-color: rgba(0, 0, 0, 0.25) transparent;
}
.rmaps-react-sidebar__scroll::-webkit-scrollbar { width: 14px; height: 14px; }
.rmaps-react-sidebar__scroll::-webkit-scrollbar-track,
.rmaps-react-sidebar__scroll::-webkit-scrollbar-corner { background: transparent; }
.rmaps-react-sidebar__scroll::-webkit-scrollbar-thumb {
	background-color: rgba(0, 0, 0, 0.2);
	background-clip: padding-box;
	border: 5px solid transparent;
	border-radius: 7px;
	-webkit-transition: border-width 0.18s ease, background-color 0.18s ease;
	transition: border-width 0.18s ease, background-color 0.18s ease;
}
.rmaps-react-sidebar__scroll:hover::-webkit-scrollbar-thumb {
	border-width: 3px;
	background-color: rgba(0, 0, 0, 0.32);
}
.rmaps-react-sidebar__scroll::-webkit-scrollbar-thumb:hover {
	background-color: rgba(0, 0, 0, 0.5);
	border-width: 2px;
}

/* Per-position placement (size set inline by React from sidebar_size). The
 * inline `width` / `height` is capped by max-* so the sidebar can never
 * overflow the wrapper — important on the admin Edit Map preview where the
 * map column may be narrower than the configured sidebar size. The 36 px
 * gutter leaves room for the toggle button when the sidebar is fully open. */
.rmaps-react-sidebar--left,
.rmaps-react-sidebar--right { max-width:  calc(100% - 36px); }
.rmaps-react-sidebar--top,
.rmaps-react-sidebar--bottom { max-height: calc(100% - 36px); }
.rmaps-react-sidebar--left   { top: 0;    left: 0;   bottom: 0; }
.rmaps-react-sidebar--right  { top: 0;    right: 0;  bottom: 0; }
.rmaps-react-sidebar--top    { top: 0;    left: 0;   right: 0;  }
.rmaps-react-sidebar--bottom { bottom: 0; left: 0;   right: 0;  }

/* Collapsed: slide off-screen via transform (no width/height change). */
.rmaps-react-sidebar--left.is-collapsed   { transform: translateX(-100%); }
.rmaps-react-sidebar--right.is-collapsed  { transform: translateX(100%); }
.rmaps-react-sidebar--top.is-collapsed    { transform: translateY(-100%); }
.rmaps-react-sidebar--bottom.is-collapsed { transform: translateY(100%); }

/* Toggle button — a SIBLING of the sidebar (not a child) so its hit area
 * is never affected by the sidebar's `translateX(-100%)`. Position is
 * driven by inline left/right/top/bottom (set by React from `sidebar_size`)
 * and animates via the same 0.25 s ease the sidebar uses, so visually the
 * toggle and the sidebar slide together.
 *
 * Always carries the primary brand colour as a fill — switches to secondary
 * on hover. The SVG chevron is rendered with `currentColor`, so setting
 * `color: #fff` on the button makes the arrow white. Inline <svg> (not a
 * Unicode triangle) dodges the WP emoji shim, which would otherwise replace
 * ▶◀▲▼ with a coloured PNG. */
.rmaps-react-sidebar__toggle {
	position: absolute;
	width: 36px;
	height: 80px;
	background: var(--rmaps-button-primary, var(--rmaps-primary, #2563eb));
	border: none;
	color: var(--rmaps-button-text, #fff);
	cursor: pointer;
	/* Sits one above the sidebar (700) so it stays clickable when the
	 * sidebar is collapsed and the toggle bleeds outside the sidebar's
	 * translated box. Both must clear the auto-popup layer (z 600) so
	 * the toggle isn't covered by a popup card fanning out from a
	 * left/right-edge marker. */
	z-index: 701;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.22);
	touch-action: manipulation;
	-webkit-tap-highlight-color: transparent;
	transition:
		left 0.25s ease, right 0.25s ease, top 0.25s ease, bottom 0.25s ease,
		background-color 0.15s ease;
	/* Hint to compositor: keep this element on its own layer so the
	 * box-shadow renders ONCE and the layer just slides during the
	 * left/right/top/bottom transition. Without this, every frame of
	 * the 0.25 s position change re-rasters the 8 px shadow over the
	 * map canvas (heavy paint) and the toggle visibly jerks behind
	 * the sidebar's smoother transform-based slide. `transform`-only
	 * promotion is enough to opt the toggle into GPU compositing
	 * even though we're animating layout properties — the slowdown
	 * was paint, not layout. */
	will-change: transform;
	transform: translateZ(0);
}
.rmaps-react-sidebar__toggle:hover {
	/* Hover swaps to the admin-configured `--rmaps-button-secondary`
	 * slot (Style Manager → "Buttons" panel) so it stays in lockstep
	 * with the rest of the plugin's interactive surfaces. Fallback
	 * chain: button-secondary → color-mix darken of button-primary →
	 * color-mix darken of --rmaps-primary → hard-coded blue darken.
	 * The `color-mix` fallbacks guarantee a visible shift even on
	 * installs that haven't customised the secondary slot (or set it
	 * equal to primary), which was the original failure mode that
	 * made the hover look inert. */
	background: var(
		--rmaps-button-secondary,
		color-mix(in srgb, var(--rmaps-button-primary, var(--rmaps-primary, #2563eb)) 85%, #000)
	);
}
.rmaps-react-sidebar__toggle-icon { display: block; }

/* Edge orientation — round the side that faces away from the sidebar so
 * the button visually attaches to the sidebar. Centring on the
 * perpendicular axis goes through `transform`. */
.rmaps-react-sidebar__toggle--left,
.rmaps-react-sidebar__toggle--right {
	top: 50%;
	transform: translateY(-50%);
}
.rmaps-react-sidebar__toggle--left   { border-radius: 0 8px 8px 0; }
.rmaps-react-sidebar__toggle--right  { border-radius: 8px 0 0 8px; }
.rmaps-react-sidebar__toggle--top,
.rmaps-react-sidebar__toggle--bottom {
	left: 50%;
	transform: translateX(-50%);
	width: 80px;
	height: 36px;
}
.rmaps-react-sidebar__toggle--top    { border-radius: 0 0 8px 8px; }
.rmaps-react-sidebar__toggle--bottom { border-radius: 8px 8px 0 0; }

/* Larger hit area on touch screens — visual size grows too, since a
 * primary-coloured button is meant to be visible/grabbable on phones. */
@media (hover: none) and (pointer: coarse) {
	.rmaps-react-sidebar__toggle--left,
	.rmaps-react-sidebar__toggle--right { width: 44px; height: 88px; }
	.rmaps-react-sidebar__toggle--top,
	.rmaps-react-sidebar__toggle--bottom { width: 88px; height: 44px; }
}

/* Listings grid — list when sidebar is vertical (left/right), grid when horizontal. */
.rmaps-react-sidebar__grid {
	display: grid;
	gap: 10px;
}
.rmaps-react-sidebar__grid--list { grid-template-columns: 1fr; }
.rmaps-react-sidebar__grid--grid { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }

.rmaps-react-sidebar__card {
	border: 1px solid #e5e7eb;
	border-radius: 6px;
	padding: 8px 10px;
	background: #fff;
	transition: border-color 0.12s, box-shadow 0.12s;
}
/* Pointer cursor only when clicking a card actually opens a popup
 * (enable_infowindow). Otherwise the card is informational and a pointer
 * would mis-suggest interactivity.
 *
 * Inner `.rmaps-listing-content *` has `cursor: default` from the
 * popup stylesheet (popup.css) — the universal selector wins over a parent's
 * cursor due to specificity. Force pointer on every card descendant for the
 * clickable case so hovering text/img inside the card still shows pointer. */
.rmaps-react-sidebar__card.is-clickable,
.rmaps-react-sidebar__card.is-clickable .rmaps-listing-content,
.rmaps-react-sidebar__card.is-clickable .rmaps-listing-content * {
	cursor: pointer;
}
.rmaps-react-sidebar__card:hover {
	border-color: var(--rmaps-primary, #2563eb);
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.06);
}

.rmaps-react-sidebar__empty {
	text-align: center;
	color: #6b7280;
	font-size: 13px;
	padding: 24px 12px;
}

.rmaps-react-sidebar__overlay {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(255, 255, 255, 0.7);
	z-index: 4;
}
.rmaps-react-sidebar__tail-loader {
	display: flex;
	justify-content: center;
	padding: 12px;
}

/* =========================================================================
 * Standalone mode — when MapSidebar renders inside [webmap-listings]
 * (StandaloneListings.tsx). Cancels the absolute corner positioning that
 * docks it to the map edges, hides the toggle button (no map to collapse
 * over), and forces grid layout regardless of the map's configured
 * sidebar_position. Keeps internal scroll on a generous max-height so
 * infinite-scroll still triggers as the visitor scans the list.
 * ========================================================================= */
.rmaps-react-listings-standalone {
	width: 100%;
}
.rmaps-react-listings-standalone .rmaps-react-sidebar {
	position: static !important;       /* beats `position: absolute` set on the base class */
	/* MapSidebar applies an inline `style={width: 500}` for left/right positions
	 * (or `height: 500` for top/bottom). Inline styles win normal cascades, so
	 * we need !important here to flip the widget to fill the shortcode's slot. */
	max-width: 100% !important;
	max-height: none !important;
	width: 100% !important;
	height: auto !important;
	top: auto;
	left: auto;
	right: auto;
	bottom: auto;
	transform: none !important;        /* cancel any --left/--right/--top/--bottom collapse translate */
	background: transparent;           /* let the page chrome show through; cards have their own bg */
}
.rmaps-react-listings-standalone .rmaps-react-sidebar__toggle {
	display: none;
}
.rmaps-react-listings-standalone .rmaps-react-sidebar__scroll {
	max-height: 80vh;
	overflow-y: auto;
}
/* Force grid layout — the in-map vertical sidebar uses --list (single
 * column), but the shortcode lays out horizontally across the page so
 * cards should fill the natural width via auto-fill columns. */
.rmaps-react-listings-standalone .rmaps-react-sidebar__grid,
.rmaps-react-listings-standalone .rmaps-react-sidebar__grid--list {
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}

/* Mapbox / MapLibre native control containers — fullscreen, navigation
 * (compass + pitch), our custom map-type switcher. The GL libs ship
 * these with `z-index: auto` (i.e. effectively 0 inside the parent
 * stacking context), but the canvasOverlayShim's synthetic pane that
 * hosts our marker canvas sits at z-index: 5 — so any cluster that
 * happened to overlap the top-right control stack would PAINT OVER
 * the buttons (marker visible, fullscreen / compass hidden). Lift the
 * control containers above the canvas pane (>5) but keep them below
 * sidebar (10) and the directions panel (1001). All four corner
 * containers covered so future controls placed elsewhere also stay
 * clickable / visible. */
.maplibregl-ctrl-top-left,
.maplibregl-ctrl-top-right,
.maplibregl-ctrl-bottom-left,
.maplibregl-ctrl-bottom-right,
.mapboxgl-ctrl-top-left,
.mapboxgl-ctrl-top-right,
.mapboxgl-ctrl-bottom-left,
.mapboxgl-ctrl-bottom-right {
	z-index: 6;
}

/* Search-form — overlaid on the map at one of the four corners on desktop;
 * on narrow viewports it pops OUT of the map and claims its own row above
 * (top-*) or below (bottom-*) the canvas, so the form never covers map
 * content. Positioning is relative to .rmaps-react-map-wrapper, which is
 * a flex column and reorders form/canvas via order: 0 / 1. */

.rmaps-search-form {
	position: absolute;
	/* z-index hierarchy on the map:
	 *   - sidebar          z 4
	 *   - sidebar toggle   z 6
	 *   - auto-popup layer z 600 (`.rmaps-autopopups-layer`)
	 *   - search form      z 700  ← THIS (above auto-popups so the
	 *                                form is never covered when an
	 *                                auto-popup happens to land
	 *                                under it)
	 *   - click popup      z 1000
	 * The form holds input focus + autocomplete UI, so it must stay
	 * interactable even when auto-popups fan out across the map. */
	z-index: 700;
	width: 400px;
	max-width: calc(100% - 100px);
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 14px 16px;
	background: rgba(255, 255, 255, 0.96);
	backdrop-filter: blur(2px);
	border-radius: 8px;
	box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
	box-sizing: border-box;
	font-size: 13px;
}
.rmaps-search-form.is-submitting { opacity: 0.7; pointer-events: none; }

/* Drag handle — sits inside the form's corner. Clicking and dragging it
 * moves the form to a new pixel position (saved to localStorage). The
 * grip cursor signals that the entire form follows the pointer.
 *
 * Position is mirrored per anchor so the handle always sits in the
 * "near corner" of the form, not blocking content. On `position: static`
 * (mobile flow), the handle still renders but dragging has no effect —
 * the inline left/top is ignored by the static positioning. */
.rmaps-search-form__drag {
	position: absolute;
	width: 22px;
	height: 22px;
	border: 0;
	background: transparent;
	color: #9ca3af;
	padding: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: grab;
	-webkit-tap-highlight-color: transparent;
	touch-action: none;             /* let pointer events drive panning */
	transition: color 0.12s, background-color 0.12s;
	border-radius: 8px;
	z-index: 1;
}
.rmaps-search-form__drag:hover {
	color: var(--rmaps-primary, #2563eb);
	background: rgba(0, 0, 0, 0.05);
}
.rmaps-search-form__drag:active { cursor: grabbing; }

.rmaps-search-form--top-left    > .rmaps-search-form__drag { top: 4px; right: 4px; }
.rmaps-search-form--top-right   > .rmaps-search-form__drag { top: 4px; left:  4px; }
.rmaps-search-form--bottom-left > .rmaps-search-form__drag { bottom: 4px; right: 4px; }
.rmaps-search-form--bottom-right > .rmaps-search-form__drag { bottom: 4px; left:  4px; }

/* When the form has been moved by the user (is-positioned), keep the
 * handle at top-right by default — no further reason to mirror by anchor
 * since the user has chosen a custom location. */
.rmaps-search-form.is-positioned > .rmaps-search-form__drag {
	top: 4px; right: 4px;
	bottom: auto; left: auto;
}

/* Hide drag handle in the mobile in-flow path — the form is `position:
 * static` there, so the inline x/y written by drag have no effect.
 * Better to not advertise a control that does nothing. */
@media (max-width: 768px) {
	.rmaps-search-form__drag { display: none; }
}

.rmaps-search-form--top-left      { top: 50px;    left: 50px; }
.rmaps-search-form--top-right     { top: 50px;    right: 50px; }
.rmaps-search-form--bottom-left   { bottom: 50px; left: 50px; }
.rmaps-search-form--bottom-right  { bottom: 50px; right: 50px; }

/* Adaptive layout — at <=768px the form drops out of the corner overlay
 * and claims its own full-width row above / below the map in normal
 * flow. The wrapper-level rules (sidebar.css) switch the wrapper to
 * height:auto so it grows to fit the stacked form + canvas. The
 * `!important` overrides the inline pixel width React applies from the
 * `search_form_width` admin option.
 *
 * Using `position: relative` (rather than `static`) so the base z-index
 * 700 keeps applying — the form must stack ABOVE canvas-host even
 * after dropping out of corner-overlay mode. Without it, clicks in
 * the form area can be hit-tested against descendants of canvas-host
 * (markers, sidebar listings) when the DOM order paints them on top.
 * Anchor offsets (`top: 50px`, etc. from --top-left/--top-right) are
 * neutralised explicitly so the form sits exactly in its flex slot,
 * not shifted by the desktop anchor amounts. */
@media (max-width: 768px) {
	.rmaps-search-form {
		position: relative;
		top:    auto !important;
		left:   auto !important;
		right:  auto !important;
		bottom: auto !important;
		width: 100% !important;
		max-width: none;
		border-radius: 0;
		box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
		flex: 0 0 auto;
	}

	/* Fullscreen — restructure the fullscreen container as a flex
	 * column so the portaled form occupies its own top row and the
	 * map content / sidebar fill the area BELOW it.
	 *
	 *   fullscreen element   → flex column container.
	 *   > .rmaps-search-form → order 0, flex 0 0 auto (variable
	 *                          height per content).
	 *   > everything else    → order 1, flex 1 1 auto (claims the
	 *                          remaining space).
	 *
	 * Three separate rules — :fullscreen (standard, Chrome 71+ /
	 * Safari 16.4+ / Firefox 64+), :-webkit-full-screen (older
	 * Safari / older Chrome), :-moz-full-screen (older Firefox).
	 * CANNOT be merged into a comma-separated list because each
	 * prefix is unknown to the other browsers — one unknown
	 * selector invalidates the whole rule for that engine. */
	:fullscreen {
		display: flex !important;
		flex-direction: column !important;
	}
	:fullscreen > * {
		order: 1;
		flex: 1 1 auto;
		min-height: 0;
	}
	:fullscreen > .rmaps-search-form {
		order: 0;
		flex: 0 0 auto !important;
		width: 100% !important;
		max-width: none !important;
		border-radius: 0 !important;
		box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08) !important;
	}
	:-webkit-full-screen {
		display: flex !important;
		flex-direction: column !important;
	}
	:-webkit-full-screen > * {
		order: 1;
		flex: 1 1 auto;
		min-height: 0;
	}
	:-webkit-full-screen > .rmaps-search-form {
		order: 0;
		flex: 0 0 auto !important;
		width: 100% !important;
		max-width: none !important;
		border-radius: 0 !important;
		box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08) !important;
	}
	:-moz-full-screen {
		display: flex !important;
		flex-direction: column !important;
	}
	:-moz-full-screen > * {
		order: 1;
		flex: 1 1 auto;
		min-height: 0;
	}
	:-moz-full-screen > .rmaps-search-form {
		order: 0;
		flex: 0 0 auto !important;
		width: 100% !important;
		max-width: none !important;
		border-radius: 0 !important;
		box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08) !important;
	}

	/* Class-based fallback — `SearchForm` adds `.rmaps-fs-host` to the
	 * fullscreen element directly (via JS in the fullscreenchange
	 * handler), bypassing any pseudo-class quirks. Same flex-column
	 * recipe as the :fullscreen rules above. */
	.rmaps-fs-host {
		display: flex !important;
		flex-direction: column !important;
	}
	.rmaps-fs-host > * {
		order: 1;
		flex: 1 1 auto;
		min-height: 0;
	}
	.rmaps-fs-host > .rmaps-search-form {
		order: 0;
		flex: 0 0 auto !important;
		width: 100% !important;
		max-width: none !important;
		border-radius: 0 !important;
		box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08) !important;
	}
}

/* ----- Rows / slots ----- */
.rmaps-search-form__row {
	display: flex;
	gap: 8px;
}
.rmaps-search-form__slot {
	/* Width fixed by the row's column count (--cols-N modifier below).
	 * Without this, slots in a 3-column row that has only 2 visible
	 * children (e.g., a separator dropped from the runtime row) would
	 * split 50/50 instead of staying at 1/3 each. */
	flex: 0 0 auto;
	min-width: 0;
	display: flex;
	align-items: stretch;
}
.rmaps-search-form__slot--cols-1 { flex-basis: 100%; }
/* row gap is 8px → subtract gap share so N slots + (N-1)*8 = 100% width */
.rmaps-search-form__slot--cols-2 { flex-basis: calc(50% - 4px); }
.rmaps-search-form__slot--cols-3 { flex-basis: calc(33.333% - 5.333px); }
.rmaps-search-form__slot.is-empty { visibility: hidden; }
.rmaps-search-form__slot > * { width: 100%; }

/* ----- Inputs (directions-style) ----- */
.rmaps-search-form__input {
	border: 1px solid #e5e7eb;
	background: #fff;
	border-radius: 8px;
	padding: 8px 14px;
	font-size: 13px;
	color: #1f2937;
	outline: none;
	transition: border-color 0.12s, box-shadow 0.12s;
}
.rmaps-search-form__input::-moz-placeholder { color: #9ca3af; }
.rmaps-search-form__input::placeholder { color: #9ca3af; }
.rmaps-search-form__input:focus {
	border-color: var(--rmaps-primary, #2563eb);
	box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

/* Native form controls — checkbox / radio tick colour follows the brand
 * primary so a checked option matches the Search button and slider
 * thumb instead of the browser-default blue. `accent-color` is well-
 * supported on Chrome/Firefox/Safari ≥15.4; older browsers fall back
 * to the OS accent and ignore this rule (graceful degrade). Applies
 * across every checkbox/radio in the form: list field, opening hours,
 * categories/locations multi-select.
 *
 * `appearance: auto !important` + WP-admin overrides reset — needed
 * because the search form is also rendered inside Edit Map's live
 * preview on `?post_type=w2gm_map`, where WP-admin's `forms.css`
 * applies `appearance: none` to every checkbox and re-draws the
 * tick via a `::before` Dashicon. `accent-color` only paints the
 * NATIVE widget, so without forcing appearance back to auto the
 * primary-colour tint silently fails in admin (the rule is
 * harmless on the frontend, where the WP styles aren't loaded —
 * `appearance: auto` is the default there anyway). */
.rmaps-search-form input[type="checkbox"],
.rmaps-search-form input[type="radio"] {
	appearance: auto !important;
	-webkit-appearance: auto !important;
	-moz-appearance: auto !important;
	width: auto;
	height: auto;
	min-width: 0;
	min-height: 0;
	background: initial;
	border: initial;
	border-radius: initial;
	box-shadow: none;
	accent-color: var(--rmaps-primary, #2563eb);
	vertical-align: middle;
}
.rmaps-search-form input[type="checkbox"]::before,
.rmaps-search-form input[type="radio"]::before {
	content: none !important;
}

/* Select-as-placeholder — when the empty option is "selected" (the
 * `<option value="">` whose label IS the field name, e.g. "Methods of
 * Payment") the select should LOOK like a placeholder, not a real
 * choice. Grey text on the closed select tells the user the filter
 * is unset; the same colour on `option[value=""]` makes the dropdown's
 * first row visually distinct from the actual values below it. We
 * also italicise the empty option so admins on systems where
 * `accent-color` is the only differentiator still see the placeholder
 * as a separate kind of row.
 *
 * `.is-placeholder` is added by ListField when `value === ''`; it's
 * removed once the user picks a real option, so the closed select
 * flips back to dark text. */
.rmaps-search-form__input.is-placeholder {
	color: #9ca3af;
}
.rmaps-search-form__input option[value=""] {
	color: #9ca3af;
	font-style: italic;
}
/* Reset for real options — the rule above was inheriting onto siblings
 * because some browsers cascade the parent select's grey to every
 * <option> when the select itself is grey-coloured. Explicit reset
 * keeps the dropdown rows readable. */
.rmaps-search-form__input.is-placeholder option:not([value=""]) {
	color: #1f2937;
	font-style: normal;
}

/* Plain wrapper used by the address input so the clear (×) button can be
 * absolutely positioned on its right edge. The keywords autocomplete
 * uses `.rmaps-search-form__autocomplete` for the same job (it needs the
 * extra ARIA + dropdown DOM); this is the slimmer single-input version.
 *
 * `display: flex` + the input growing to `flex: 1 0 auto` is what
 * propagates the slot's `align-items: stretch` height through to the
 * <input>. Without flex the wrapper stretched but the input inside
 * stayed at its natural ~36px height, leaving the address field shorter
 * than its sibling radius slider on the same row (the clear × then
 * sat at the slot's bottom edge instead of vertically centred). */
.rmaps-search-form__input-wrap {
	position: relative;
	width: 100%;
	display: flex;
	flex-direction: column;
}
.rmaps-search-form__input-wrap > .rmaps-search-form__input {
	flex: 1 0 auto;
	width: 100%;
}
/* (Same height-stretch fix is folded into `.rmaps-search-form__autocomplete`
 * below — see the consolidated rule near the dropdown styles.) */

/* Reserve right padding on inputs that may carry a clear / spinner badge
 * so the user's typed text doesn't run under the icon. Applies to both
 * wrapper variants (autocomplete + plain wrap). */
.rmaps-search-form__input-wrap .rmaps-search-form__input,
.rmaps-search-form__autocomplete .rmaps-search-form__input {
	padding-right: 30px;
}

/* Clear (×) button — appears at the input's right edge when the field is
 * non-empty. Uses absolute positioning so the input layout stays
 * untouched. Subtle hover affordance (gray pill background) signals
 * clickability without screaming for attention. Aria-label set on the
 * button itself for screen readers. */
.rmaps-search-form__clear {
	position: absolute;
	top: 50%;
	right: 6px;
	transform: translateY(-50%);
	width: 20px;
	height: 20px;
	padding: 0;
	border: 0;
	background: transparent;
	color: #9ca3af;
	cursor: pointer;
	border-radius: 50%;
	font-size: 16px;
	line-height: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background 0.12s, color 0.12s;
}
.rmaps-search-form__clear:hover {
	background: #f3f4f6;
	color: #4b5563;
}
.rmaps-search-form__clear:focus {
	outline: none;
	background: #f3f4f6;
	color: #4b5563;
	box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.25);
}

/* ----- Keywords autocomplete dropdown -----
 * Wrapper is positioned so the absolutely-positioned <ul> anchors below the
 * input. z-index sits above the form's own inputs but BELOW any modal /
 * marker popup the runtime might paint on top.
 *
 * `display: flex` + child `flex: 1 0 auto` propagates the parent slot's
 * `align-items: stretch` height down to the <input>. Without it the
 * input stayed at its natural ~36px and the field looked shorter than
 * its row neighbours (e.g. the radius slider). */
.rmaps-search-form__autocomplete {
	position: relative;
	width: 100%;
	display: flex;
	flex-direction: column;
}
.rmaps-search-form__autocomplete > .rmaps-search-form__input {
	flex: 1 0 auto;
	width: 100%;
}
.rmaps-search-form__autocomplete-list {
	position: absolute;
	top: calc(100% + 2px);
	left: 0;
	right: 0;
	z-index: 20;
	margin: 0;
	padding: 4px 0;
	list-style: none;
	background: #fff;
	border: 1px solid #e5e7eb;
	border-radius: 8px;
	box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
	max-height: 280px;
	overflow-y: auto;
	font-size: 13px;
}
.rmaps-search-form__autocomplete-item {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	padding: 7px 12px;
	/* Reset margin explicitly — themes / WP admin frequently set
	 * `li { margin-bottom: ... }` which would inflate the gap below the
	 * last item past the 4px list padding-bottom (visible asymmetry vs
	 * the top of the list). */
	margin: 0;
	cursor: pointer;
	color: #1f2937;
	transition: background-color 0.08s;
}
.rmaps-search-form__autocomplete-item.is-active,
.rmaps-search-form__autocomplete-item:hover {
	background: rgba(37, 99, 235, 0.08);
}
.rmaps-search-form__autocomplete-label {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.rmaps-search-form__autocomplete-count {
	flex: 0 0 auto;
	font-size: 11px;
	color: #6b7280;
	background: #f3f4f6;
	padding: 1px 6px;
	border-radius: 10px;
}
/* Tiny spinner — single-rotation CSS keyframe, no SVG needed. Pinned to
 * the input's right edge so it sits inside the rounded corner. */
.rmaps-search-form__autocomplete-spinner {
	position: absolute;
	top: 50%;
	right: 10px;
	width: 12px;
	height: 12px;
	margin-top: -6px;
	border: 2px solid rgba(37, 99, 235, 0.25);
	border-top-color: var(--rmaps-primary, #2563eb);
	border-radius: 50%;
	animation: rmaps-search-form-spin 0.7s linear infinite;
	pointer-events: none;
}
@keyframes rmaps-search-form-spin {
	to { transform: rotate(360deg); }
}

/* ----- Range / radius slider ----- */
.rmaps-search-form__range {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 12px;
	color: #4b5563;
	padding: 4px 8px;
}
.rmaps-search-form__range > span { font-weight: 500; }
.rmaps-search-form__range > input[type="range"] {
	width: 100%;
	accent-color: var(--rmaps-primary, #2563eb);
}

/* ----- Buttons -----
 * Hover deliberately keeps the SAME palette as the resting state — only a
 * very small darken/brighten via box-shadow inset so the buttons don't
 * look broken when the host theme overrides global `button` styles
 * (themes often re-color text/bg on :hover for non-namespaced buttons).
 * `!important` on color/background-color guards against those overrides. */
.rmaps-search-form__btn {
	border: 1px solid #e5e7eb !important;
	background-color: #fff !important;
	color: #1f2937 !important;
	font-weight: 500;
	font-size: 13px;
	padding: 7px 16px;
	border-radius: 8px;
	cursor: pointer;
	transition: box-shadow 0.12s, border-color 0.12s;
	text-decoration: none;
	box-shadow: none;
}
.rmaps-search-form__btn:hover {
	background-color: #fff !important;
	color: #1f2937 !important;
	border-color: #cbd5e1 !important;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.rmaps-search-form__btn:active {
	box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.08);
}
.rmaps-search-form__btn--primary {
	background-color: var(--rmaps-primary, #2563eb) !important;
	color: #fff !important;
	border-color: var(--rmaps-primary, #2563eb) !important;
}
.rmaps-search-form__btn--primary:hover {
	background-color: var(--rmaps-secondary, var(--rmaps-primary, #1f82a5)) !important;
	color: #fff !important;
	border-color: var(--rmaps-secondary, var(--rmaps-primary, #1f82a5)) !important;
	box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
.rmaps-search-form__btn:disabled,
.rmaps-search-form__btn:disabled:hover {
	opacity: 0.5;
	cursor: not-allowed;
	box-shadow: none;
}

/* ----- Separator (collapsible "more filters") -----
 * Same hover-stability strategy as the Search/Reset buttons: !important on
 * color/background guards against host-theme `button:hover` overrides that
 * would otherwise flip text/bg into something illegible. Full-width pill
 * to match the visual weight of the Search/Reset buttons stacked above. */
.rmaps-search-form__separator {
	display: flex;
	margin: 4px 0;
}
.rmaps-search-form__separator-btn {
	width: 100%;
	border: 1px solid #e5e7eb !important;
	background-color: #fff !important;
	color: var(--rmaps-primary, #2563eb) !important;
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	padding: 7px 16px;
	border-radius: 8px;
	box-shadow: none;
	text-decoration: none;
	transition: box-shadow 0.12s, border-color 0.12s;
}
.rmaps-search-form__separator-btn:hover {
	background-color: #fff !important;
	color: var(--rmaps-primary, #2563eb) !important;
	border-color: #cbd5e1 !important;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.rmaps-search-form__separator-btn:active {
	box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.08);
}
.rmaps-search-form__separator-btn .rmaps-fa { transition: transform 0.18s ease; }
.rmaps-search-form__separator-btn.is-open .rmaps-fa { transform: rotate(90deg); }

/* ----- Number / Price / DateTime pair (From / To inputs side-by-side) ----- */
.rmaps-search-form__pair {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 6px;
	min-width: 0;
}
.rmaps-search-form__pair > .rmaps-search-form__input {
	min-width: 0;
}

/* ----- Number / Price as dual-thumb range slider ----- */
.rmaps-search-form__rangepair {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 12px;
	color: #4b5563;
	padding: 4px 8px;
}
.rmaps-search-form__rangepair-label { font-weight: 500; }
/* Dual-thumb slider — visible track is drawn ONCE via a gradient on the
 * parent (`::before`), with the active span between the two thumbs in
 * the brand primary colour and the rest in light grey. The two range
 * inputs themselves are transparent (no native track / fill / thumb)
 * and only contribute hit-areas for their thumbs. The thumb is
 * re-styled via the vendor pseudo-elements so it visually matches.
 *
 * The two CSS custom properties --rmaps-rp-lo and --rmaps-rp-hi are set
 * by React on the track div to position the active span (percentages
 * from `min`..`max`). */
.rmaps-search-form__rangepair-track {
	position: relative;
	height: 28px;
}
.rmaps-search-form__rangepair-track::before {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 4px;
	transform: translateY(-50%);
	background: linear-gradient(
		to right,
		#e5e7eb 0%,
		#e5e7eb var(--rmaps-rp-lo, 0%),
		var(--rmaps-primary, #2563eb) var(--rmaps-rp-lo, 0%),
		var(--rmaps-primary, #2563eb) var(--rmaps-rp-hi, 100%),
		#e5e7eb var(--rmaps-rp-hi, 100%)
	);
	border-radius: 2px;
	pointer-events: none;
}
.rmaps-search-form__rangepair-track > input[type="range"] {
	position: absolute;
	inset: 0;
	width: 100%;
	margin: 0;
	background: transparent;
	-webkit-appearance: none;
	-moz-appearance: none;
	     appearance: none;
	/* Track doesn't catch events — pointer events live on the thumb
	 * pseudo-element below so dragging the lower thumb still works
	 * even when the upper input is layered on top. */
	pointer-events: none;
}
/* Native track — hidden, gradient on parent provides the visual. */
.rmaps-search-form__rangepair-track > input[type="range"]::-webkit-slider-runnable-track {
	background: transparent;
	border: none;
	height: 4px;
}
.rmaps-search-form__rangepair-track > input[type="range"]::-moz-range-track {
	background: transparent;
	border: none;
	height: 4px;
}
.rmaps-search-form__rangepair-track > input[type="range"]::-moz-range-progress {
	background: transparent;
}
/* Thumb — re-skinned to match the primary palette + restored
 * hit-testing so the user can grab and drag it. */
.rmaps-search-form__rangepair-track > input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	pointer-events: auto;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--rmaps-primary, #2563eb);
	border: 2px solid #fff;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
	cursor: pointer;
	margin-top: -6px; /* (thumb 16 - track 4) / 2 */
}
.rmaps-search-form__rangepair-track > input[type="range"]::-moz-range-thumb {
	pointer-events: auto;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--rmaps-primary, #2563eb);
	border: 2px solid #fff;
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);
	cursor: pointer;
}

/* ----- List (checkbox / radio grid) ----- */
.rmaps-search-form__optgrid {
	display: grid;
	gap: 4px 10px;
}
.rmaps-search-form__opt {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 12.5px;
	cursor: pointer;
}
.rmaps-search-form__opt input { margin: 0; }

/* ----- Opening hours (single checkbox) ----- */
.rmaps-search-form__checkbox {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	/* Vertical padding only — horizontal padding caused the option to
	 * sit indented relative to other rows in the form. */
	padding: 6px 0;
	font-size: 12.5px;
	cursor: pointer;
}
.rmaps-search-form__checkbox input { margin: 0; }

/* ----- Multi-select checklist (categories / locations with multiple = true) ----- */
.rmaps-search-form__checklist {
	display: flex;
	flex-direction: column;
	gap: 2px;
	max-height: 180px;
	overflow-y: auto;
	border: 1px solid #e5e7eb;
	border-radius: 8px;
	background: #fff;
	padding: 6px 4px;
	font-size: 12.5px;
}
.rmaps-search-form__checklist-item {
	display: flex;
	align-items: center;
	gap: 6px;
	padding: 3px 6px;
	border-radius: 4px;
	cursor: pointer;
}
.rmaps-search-form__checklist-item:hover { background: #f3f4f6; }
.rmaps-search-form__checklist-item input[type="checkbox"] { margin: 0; }
.rmaps-search-form__checklist-item span { flex: 1 1 auto; min-width: 0; }

/* ----- Placeholders for not-yet-implemented field types ----- */
.rmaps-search-form__placeholder {
	font-size: 12px;
	color: #9ca3af;
	font-style: italic;
	padding: 6px 10px;
	background: #f9fafb;
	border: 1px dashed #d1d5db;
	border-radius: 6px;
	text-align: center;
}

/* =========================================================================
 * Standalone mode — when [webmap-search] renders outside the map (its own
 * place in the page flow). Cancels the absolute corner positioning so the
 * form behaves as a regular block element. The drag handle has no meaning
 * in static layout, so it's hidden too. Width still comes from inline
 * style (config.search_form_width) but reads as the form's natural max
 * because the host is a normal block.
 * ========================================================================= */
.rmaps-react-search-standalone {
	width: 100%;
}
.rmaps-react-search-standalone .rmaps-search-form {
	position: static;
	top: auto;
	left: auto;
	right: auto;
	bottom: auto;
	max-width: 100%;
}
.rmaps-react-search-standalone .rmaps-search-form__drag {
	display: none;
}

/* ----- Searchable single-select dropdown (categories / locations with
 *       multiple = false) — custom replacement for the native <select>.
 *       Adds a type-to-filter search box and remembers the list's scroll
 *       position between opens; a native <select> popup is browser-owned,
 *       so its scroll can be neither read nor restored from JS. ----- */
.rmaps-search-form__taxdd { position: relative; width: 100%; display: flex; }
.rmaps-search-form__taxdd,
.rmaps-search-form__taxdd * { box-sizing: border-box; }
.rmaps-search-form__taxdd-trigger {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	cursor: pointer;
	text-align: left;
	font-family: inherit;
	-webkit-appearance: none;
	-moz-appearance: none;
	     appearance: none;
	/* Guard against host themes that repaint `button:hover` with their
	 * accent colour — the trigger must keep its plain input look. */
	background-color: #fff !important;
	color: #1f2937 !important;
}
.rmaps-search-form__taxdd-trigger.is-placeholder { color: #9ca3af !important; }
/* Hold the resting border on hover too — themes' `button:hover` often
 * drop it. `:hover` (0,2,0) outranks the theme's `button:hover` (0,1,1)
 * without !important, so the :focus glow border is left untouched. */
.rmaps-search-form__taxdd-trigger:hover { border: 1px solid #e5e7eb; }
.rmaps-search-form__taxdd-value {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.rmaps-search-form__taxdd-caret {
	flex: 0 0 auto;
	color: #9ca3af;
	font-size: 10px;
	line-height: 1;
}
/* Small reset (x) — shown in place of the caret while a value is
 * selected; clears the filter back to "Any" without opening the list. */
.rmaps-search-form__taxdd-clear {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 16px;
	height: 16px;
	border-radius: 50%;
	color: #9ca3af;
	font-size: 14px;
	line-height: 1;
	cursor: pointer;
	transition: background-color 0.12s, color 0.12s;
}
.rmaps-search-form__taxdd-clear:hover {
	background: #f3f4f6;
	color: #4b5563;
}
.rmaps-search-form__taxdd-panel {
	position: absolute;
	top: calc(100% + 2px);
	left: 0;
	right: 0;
	z-index: 20;
	background: #fff;
	border: 1px solid #e5e7eb;
	border-radius: 8px;
	box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
	overflow: hidden;
}
.rmaps-search-form__taxdd-search {
	width: 100%;
	border: 0;
	border-bottom: 1px solid #e5e7eb;
	padding: 8px 12px;
	font-size: 13px;
	font-family: inherit;
	color: #1f2937;
	outline: none;
}
.rmaps-search-form__taxdd-search::-moz-placeholder { color: #9ca3af; }
.rmaps-search-form__taxdd-search::placeholder { color: #9ca3af; }
.rmaps-search-form__taxdd-list {
	max-height: 260px;
	overflow-y: auto;
	font-size: 13px;
}
/* Virtual-scroll spacer — full list height; only the windowed option
 * rows (absolutely positioned by their index) are actually mounted. */
.rmaps-search-form__taxdd-spacer {
	position: relative;
	width: 100%;
}
.rmaps-search-form__taxdd-option {
	position: absolute;
	left: 0;
	right: 0;
	height: 32px;
	line-height: 32px;
	padding: 0 12px;
	cursor: pointer;
	color: #1f2937;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	transition: background-color 0.08s;
}
.rmaps-search-form__taxdd-option:hover { background: rgba(37, 99, 235, 0.08); }
.rmaps-search-form__taxdd-option.is-selected {
	background: rgba(37, 99, 235, 0.12);
	font-weight: 600;
}
.rmaps-search-form__taxdd-empty {
	padding: 10px 12px;
	color: #9ca3af;
	font-style: italic;
	text-align: center;
}

/* Auto-popup layer — DOM popups auto-placed around viewport markers. */

.rmaps-autopopups-layer {
	position: absolute;
	inset: 0;
	overflow: hidden;
	pointer-events: none; /* only the cards themselves are interactive */
	/* Above the canvas marker overlay (engine panes z 5-6) but below
	   the click-popup. Click-popup's `OverlayView` container is moved
	   OUT of floatPane and APPENDED DIRECTLY to mapDiv with z-index
	   1500 (see `Popup.tsx::onAdd`), so it sits above this layer
	   regardless of the layer's own z. Earlier this was lowered to
	   z 3 to let floatPane's z 4 win, but that put auto-popups BELOW
	   the canvas marker layer too — cluster bubbles painted on top of
	   the popup cards (the user reported "канва выше попапов?"). The
	   "move click-popup to mapDiv level" approach is the architectural
	   fix; this layer stays at z 600 (the original value), safely
	   above canvas markers. */
	z-index: 600;
}

/* Wrapper around each popup card + its tail, owns the SHARED shadow.
   `filter: drop-shadow` follows the COMBINED alpha shape of both
   children — the white Paper body and the white diamond tail merge
   into one outline (their overlap at the card edge is white-on-
   white), and the shadow traces the merged perimeter.

   Replaces the previous per-element `box-shadow` setup where the
   Paper's outward elevation 4 shadow painted OVER the tail's outer
   half (tail "barely visible under the shadow") and the tail's own
   box-shadow leaked INSIDE the card body. `filter: drop-shadow` is
   the only CSS tool that lets two shapes share one shadow outline.

   Zero-sized container: the children position themselves via
   `transform` in layer coordinates (the RAF loop sets it every
   frame). The browser's filter input region tracks the painted
   descendants no matter where they land, so drop-shadow renders
   correctly regardless of the wrapper's declared `width` / `height`.
   Using `inset: 0` would force the filter to compute over the entire
   layer area for every popup.

   `pointer-events: none` lets clicks reach the card (which has
   `pointer-events: auto` set in PopupCard's autoLayout sx); the
   wrapper itself never claims input. `filter` also creates a new
   stacking context per wrapper — `.rmaps-autopopup-tail` uses
   `z-index: 6` to paint over the Paper (z 5) INSIDE its group;
   cross-group stacking falls back to DOM order, which is fine
   because the layout solver doesn't let popups overlap. */
.rmaps-autopopup-group {
	position: absolute;
	left: 0;
	top: 0;
	width: 0;
	height: 0;
	pointer-events: none;
	filter: drop-shadow(0 2px 5px rgba(0, 0, 0, 0.25));
}

/* One DOM tail per popup — an elongated RHOMBUS clipped from a
   14×8 white box, positioned SYMMETRICALLY around its centre on the
   card-edge intersection of the card-centre→marker ray.

   The RAF loop in `AutoPopupLayer.tsx → tailTransform()` writes the
   element's `transform` every frame:
     - `translate(...)` puts the rhombus's geometric centre on the
       card-edge intersection point (ex, ey),
     - `rotate(...)` aligns the long diagonal with the
       card-centre→marker ray,
     - `scaleX(...)` stretches the natural 14-px reference length to
       `2 × edgeToTip`, so the rhombus extends `edgeToTip` outside
       the card (outer long-axis vertex sits on the marker) AND the
       same distance INSIDE the card body (inner long-axis vertex
       hidden under the white Paper).

   `transform-origin: 50% 50%` keeps the rotate AND scaleX pivots at
   the rhombus's geometric centre, so the centre point stays on the
   card-edge anchor regardless of rotation or stretch.

   `clip-path: polygon(0% 50%, 50% 0%, 100% 50%, 50% 100%)`:
     - (0%,   50%) → outer-left vertex   (inner long-axis tip, ends
                                          up INSIDE the card body
                                          after rotate aligns long
                                          axis with the marker ray
                                          — hidden by Paper)
     - (50%,  0%)  → top vertex          (short-axis end)
     - (100%, 50%) → outer-right vertex  (outer long-axis tip, on
                                          the marker pixel)
     - (50%,  100%) → bottom vertex      (short-axis end)
   After `scaleX(s)` around 50% 50%, the outer-left/right vertices
   stretch symmetrically outward; the top/bottom vertices keep their
   x at the centre and y at the box edges. The two short-axis
   vertices stay at the card-edge line; for diagonal-direction
   markers one of them lands OUTSIDE the card (visible) while the
   opposite one lands INSIDE (hidden by Paper). Net: the user sees
   the outer long-axis tip on the marker + one short-axis vertex
   visible to the side = 2 visible vertices.

   No own `box-shadow` — the parent `.rmaps-autopopup-group` applies
   `filter: drop-shadow` over the merged card+tail alpha, producing
   one continuous outline around the rounded card plus its rhombus.
   Half of the rhombus is overlaid on the card body (white on white
   — invisible seam), so the drop-shadow contour just adds the
   visible outer half as a tear-drop protrusion. */
.rmaps-autopopup-tail {
	position: absolute;
	left: 0;
	top: 0;
	width: 14px;
	height: 8px;
	background: #ffffff;
	/* Classic rhombus tail. Tried softening it to ellipse / lens
	 * shapes — at long stretches both read worse than the sharp
	 * rhombus (ellipse became a fat sausage, lens looked like a
	 * leaf). Reverted to the original. */
	clip-path: polygon(0% 50%, 50% 0%, 100% 50%, 50% 100%);
	opacity: 0;
	pointer-events: none;
	transform-origin: 50% 50%;
	will-change: transform, opacity;
	/* BELOW the Paper (z 5) within the `.rmaps-autopopup-group`
	   stacking context, so the inner half of the rhombus (which
	   overlaps the card body after the inward-shift positioning
	   in `tailTransform()`) is OBSCURED by the Paper. Without this
	   the white rhombus painted OVER the Paper's content (title,
	   chips, etc.) — visually the rhombus extended INTO the popup
	   rather than behind it.
	   `filter: drop-shadow` lives on `.rmaps-autopopup-group` and
	   operates on the combined Paper+tail alpha output, so it
	   outlines only the visible (protruding) outer half of the
	   rhombus regardless of which child paints on top. Paper here
	   uses `elevation={0}` (see `PopupCard.tsx` autoLayout branch)
	   so it has no `box-shadow` of its own — that was the original
	   reason we'd bumped the tail to z 6 in an earlier revision;
	   with the wrapper drop-shadow taking over the shadow job, the
	   tail can sit safely under the Paper. */
	z-index: 4;
}


