/* Property Card Widget (#822 templates)
 * Self-contained card styling, driven by the `--hfse-*` vars
 * PropertyCardWidgetContent plumbs from the saved color settings. */
.hr-property-card {
  box-sizing: border-box;
  /* The stretched link (z-index: 1) and slideshow controls (z-index: 2) are
     implementation details — contain them so they never compete with host
     overlays outside the card (searchbar dropdowns, sticky headers on
     embedding pages). */
  isolation: isolate;
  /* Raise via customCss to let the card grow past the mock proportions; the
     width setting on the wrapper still caps it from above. */
  --hr-pc-max-width: 420px;
  --hr-pc-radius: 12px;
}

.hr-property-card *,
.hr-property-card *::before,
.hr-property-card *::after {
  box-sizing: border-box;
}

/* ── Card shell ─────────────────────────────────────────────── */

.hr-property-card .hr-pc-card {
  display: block;
  width: 100%;
  max-width: var(--hr-pc-max-width);
  margin: 0 auto;
  position: relative;
  overflow: hidden;
  text-decoration: none;
  color: var(--hfse-foreground);
  background: var(--hfse-card-bg);
  border: 1px solid var(--hfse-border);
  border-radius: var(--hr-pc-radius);
  box-shadow: 0 1px 3px rgba(20, 24, 18, 0.07), 0 8px 22px rgba(20, 24, 18, 0.06);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.hr-property-card .hr-pc-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 2px 6px rgba(20, 24, 18, 0.09), 0 14px 30px rgba(20, 24, 18, 0.1);
}

/* Stretched link: the whole card is one click target, while the slideshow
   buttons stay valid HTML by stacking ABOVE it (z-index 2) instead of nesting
   inside it. */
.hr-property-card .hr-pc-card__link {
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: var(--hr-pc-radius);
}

/* Inset ring: the card clips at its border (overflow: hidden), so a positive
   outline-offset on the inset-0 link would be entirely clipped away. */
.hr-property-card .hr-pc-card__link:focus-visible {
  outline: 2px solid var(--hfse-accent);
  outline-offset: -2px;
  border-radius: var(--hr-pc-radius);
}

/* Visually-hidden accessible name for the stretched link. */
.hr-property-card .hr-pc-sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ── Media ──────────────────────────────────────────────────── */

.hr-property-card .hr-pc-media {
  position: relative;
  overflow: hidden;
  background: var(--hfse-border);
}

.hr-property-card .hr-pc-media__track {
  position: relative;
  width: 100%;
  height: 100%;
}

.hr-property-card .hr-pc-media__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  opacity: 0;
  transition: opacity 0.4s ease, transform 0.5s ease;
}

.hr-property-card .hr-pc-media__img.is-active {
  opacity: 1;
}

.hr-property-card .hr-pc-card:hover .hr-pc-media__img.is-active {
  transform: scale(1.04);
}

.hr-property-card .hr-pc-media__nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  width: 28px;
  height: 28px;
  margin-top: -14px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  cursor: pointer;
  /* Hidden means inert: while invisible the arrows must not sit as touch
     targets above the stretched link. */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}

/* Keyed off the card root, not the media: the stretched link overlays the
   media, so pointer hover lands on the link (a sibling) and .hr-pc-media:hover
   would never fire. */
.hr-property-card .hr-pc-card:hover .hr-pc-media__nav,
.hr-property-card .hr-pc-media__nav:focus-visible {
  opacity: 1;
  pointer-events: auto;
}

/* No hover to reveal them on touch devices — keep the arrows always visible
   and tappable there. */
@media (hover: none) {
  .hr-property-card .hr-pc-media__nav {
    opacity: 1;
    pointer-events: auto;
  }
}

.hr-property-card .hr-pc-media__nav:focus-visible,
.hr-property-card .hr-pc-media__dot:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

.hr-property-card .hr-pc-media__nav::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 7px;
  height: 7px;
  border-top: 2px solid #1c2024;
  border-right: 2px solid #1c2024;
}

.hr-property-card .hr-pc-media__nav--prev {
  left: 8px;
}

.hr-property-card .hr-pc-media__nav--prev::before {
  transform: translate(-30%, -50%) rotate(-135deg);
}

.hr-property-card .hr-pc-media__nav--next {
  right: 8px;
}

.hr-property-card .hr-pc-media__nav--next::before {
  transform: translate(-70%, -50%) rotate(45deg);
}

.hr-property-card .hr-pc-media__dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  /* Hard single row: dot count is windowed in CardMedia (MAX_DOTS), and any
     residual overflow at extreme narrow widths clips instead of wrapping into
     rows that cover the nav arrows. The window centers the active dot, so the
     clipped edges are never the current slide's indicator. */
  flex-wrap: nowrap;
  overflow: hidden;
  justify-content: center;
  z-index: 2;
  /* The wrapper spans the card's full width — only the dots themselves may
     take clicks, everything between falls through to the stretched link. */
  pointer-events: none;
}

/* 24px minimum touch target; the visible 6px dot is the ::before. flex:none
   so many slides wrap instead of shrinking targets below the minimum. */
.hr-property-card .hr-pc-media__dot {
  flex: none;
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
}

.hr-property-card .hr-pc-media__dot::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.55);
}

.hr-property-card .hr-pc-media__dot.is-active::before {
  background: #fff;
}

.hr-property-card .hr-pc-chip {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  /* Decorative: never steal clicks from the stretched link underneath. */
  pointer-events: none;
  background: rgba(255, 255, 255, 0.92);
  color: #1c2024;
  font-size: var(--hr-pc-fs-chip, 0.7rem);
  font-weight: 600;
  line-height: 1.5;
  padding: 0.18rem 0.55rem;
  border-radius: 999px;
  /* Bounded so the overlay dots' reserved zone (below) is always sufficient. */
  max-width: 42%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Text-only card (no photos / showImage off): the chip moves into the body,
   sitting in the flow above the heading instead of floating over a photo. */
.hr-property-card .hr-pc-body .hr-pc-chip {
  position: static;
  display: inline-block;
  margin-bottom: 0.4rem;
  background: var(--hfse-border);
  color: var(--hfse-card-fg);
}

/* ── Body ───────────────────────────────────────────────────── */

.hr-property-card .hr-pc-body {
  padding: 0.8rem 0.9rem 0.9rem;
}

.hr-property-card .hr-pc-heading {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
}

.hr-property-card .hr-pc-title {
  margin: 0;
  font-size: var(--hr-pc-fs-title, 1rem);
  font-weight: 600;
  line-height: 1.3;
  color: var(--hfse-foreground);
}

.hr-property-card .hr-pc-rating {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  flex: none;
  font-size: var(--hr-pc-fs-location, 0.78rem);
  color: var(--hfse-accent);
}

.hr-property-card .hr-pc-rating__count {
  color: var(--hfse-muted-foreground);
}

.hr-property-card .hr-pc-location {
  margin: 0.12rem 0 0.45rem;
  font-size: var(--hr-pc-fs-location, 0.78rem);
  color: var(--hfse-muted-foreground);
}

/* Central excerpts run to a full paragraph; cap the card at the mock's blurb
   height so a long description can't dwarf the rest of the card. */
.hr-property-card .hr-pc-excerpt {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: 0.1rem 0 0.55rem;
  font-size: var(--hr-pc-fs-excerpt, 0.8rem);
  line-height: 1.45;
  color: var(--hfse-card-fg);
}

.hr-property-card .hr-pc-price {
  margin: 0 0 0.55rem;
  font-size: var(--hr-pc-fs-price, 0.86rem);
  color: var(--hfse-card-fg);
}

/* ── Grid-mount extras (explorer bridge): quote pricing + favorites ── */

/* Multi-line quote price: the container may be a div holding line + note. */
.hr-property-card .hr-pc-price--quote .hr-pc-price__line {
  margin: 0;
}

.hr-property-card .hr-pc-price__strike {
  margin-right: 0.25em;
  opacity: 0.65;
}

.hr-property-card .hr-pc-price__sep {
  opacity: 0.6;
}

.hr-property-card .hr-pc-price__total {
  white-space: nowrap;
}

.hr-property-card .hr-pc-price__note {
  margin: 0.15rem 0 0;
  font-size: 0.85em;
  opacity: 0.7;
}

.hr-property-card .hr-pc-price--loading svg {
  display: block;
}

/* Muted states where a price would be: a failed full-price quote ("View Full
   Price") and "No dates available" (toolkit lowest-rate-availability, when
   the property has no bookable nights). */
.hr-property-card .hr-pc-price--failed,
.hr-property-card .hr-pc-price--unavailable {
  opacity: 0.75;
}

/* Favorites heart: top-LEFT corner (the type chip owns the top-right).
   Stacks with the slideshow controls above the stretched link. */
.hr-property-card .hr-pc-fav {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.9);
  color: #1c2024;
  cursor: pointer;
  transition: transform 0.15s ease, background-color 0.15s ease;
}

.hr-property-card .hr-pc-fav:hover {
  transform: scale(1.08);
  background: #fff;
}

.hr-property-card .hr-pc-fav.is-active {
  color: #e0245e;
}

.hr-property-card .hr-pc-fav:focus-visible {
  outline: 2px solid var(--hfse-accent);
  outline-offset: 2px;
}

.hr-property-card .hr-pc-price b {
  font-size: 1.19em;
  color: var(--hfse-foreground);
}

.hr-property-card .hr-pc-price__unit {
  color: var(--hfse-muted-foreground);
}

.hr-property-card .hr-pc-pricerow {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem;
}

.hr-property-card .hr-pc-viewlink {
  flex: none;
  margin-bottom: 0.55rem;
  /* Deliberately not knob-driven (#849), but px, not rem — rem resolves
     against the HOST document root, the exact dependency #824 removed. */
  font-size: 13px;
  font-weight: 600;
  color: var(--hfse-accent);
}

.hr-property-card .hr-pc-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.45rem;
  padding-top: 0.55rem;
  border-top: 1px solid var(--hfse-border);
  font-size: var(--hr-pc-fs-meta, 0.78rem);
  color: var(--hfse-card-fg);
}

.hr-property-card .hr-pc-meta span + span::before {
  content: '·';
  margin-right: 0.45rem;
  color: var(--hfse-muted-foreground);
}

/* ── Element order & alignment (#825) ──────────────────────── */

/* Rating on its own row: only rendered once it is moved away from the title
   (adjacent, the pair shares .hr-pc-heading). */
.hr-property-card .hr-pc-ratingrow {
  margin: 0.15rem 0 0.4rem;
  line-height: 1;
}

/* Explicit alignment; `default` emits no class, so an untouched card keeps
   each template's own layout. Text nodes align their text. */
.hr-property-card .hr-pc-al-left { text-align: left; }
.hr-property-card .hr-pc-al-center { text-align: center; }
.hr-property-card .hr-pc-al-right { text-align: right; }
.hr-property-card .hr-pc-al-justify { text-align: justify; }

/* The flex rows (heading, meta, Detailed's pricerow) place their items
   instead — text-align cannot move flex items. `justify` spreads a pair to
   the row's edges, which is what the heading and pricerow do by default. */
.hr-property-card .hr-pc-heading.hr-pc-al-left,
.hr-property-card .hr-pc-meta.hr-pc-al-left,
.hr-property-card .hr-pc-pricerow.hr-pc-al-left {
  justify-content: flex-start;
}

.hr-property-card .hr-pc-heading.hr-pc-al-center,
.hr-property-card .hr-pc-meta.hr-pc-al-center,
.hr-property-card .hr-pc-pricerow.hr-pc-al-center {
  justify-content: center;
}

.hr-property-card .hr-pc-heading.hr-pc-al-right,
.hr-property-card .hr-pc-meta.hr-pc-al-right,
.hr-property-card .hr-pc-pricerow.hr-pc-al-right {
  justify-content: flex-end;
}

.hr-property-card .hr-pc-heading.hr-pc-al-justify,
.hr-property-card .hr-pc-meta.hr-pc-al-justify,
.hr-property-card .hr-pc-pricerow.hr-pc-al-justify {
  justify-content: space-between;
}

/* ── Overlay template ───────────────────────────────────────── */

.hr-property-card .hr-pc-scrim {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  /* Sits at the stretched link's level in DOM order after it — let clicks fall
     through to the link. */
  pointer-events: none;
  padding: 2.2rem 0.9rem 0.8rem;
  color: #fff;
}

.hr-property-card .hr-pc-scrim--soft {
  background: linear-gradient(transparent, rgba(10, 14, 12, 0.78));
}

.hr-property-card .hr-pc-scrim--strong {
  background: linear-gradient(transparent, rgba(10, 14, 12, 0.94));
}

.hr-property-card .hr-pc-scrim .hr-pc-title {
  font-size: calc(var(--hr-pc-fs-title, 1rem) * 1.02);
  color: #fff;
}

.hr-property-card .hr-pc-scrim .hr-pc-price {
  margin: 0.1rem 0 0;
  font-size: calc(var(--hr-pc-fs-price, 0.86rem) * 0.965);
  color: rgba(255, 255, 255, 0.95);
}

.hr-property-card .hr-pc-scrim .hr-pc-price b,
.hr-property-card .hr-pc-scrim .hr-pc-price__unit {
  color: inherit;
}

.hr-property-card .hr-pc-scrim .hr-pc-price b {
  font-size: 1.14em;
}

.hr-property-card .hr-pc-scrim .hr-pc-meta {
  display: block;
  margin: 0.3rem 0 0;
  padding-top: 0;
  border-top: 0;
  font-size: calc(var(--hr-pc-fs-meta, 0.78rem) * 0.95);
  color: rgba(255, 255, 255, 0.85);
}

/* The dots sit under the scrim text on the overlay template. Offsets are
   smaller than the visual position suggests: the 24px hitboxes carry ~9px of
   padding around each 6px dot. padding-right reserves the top-right corner for
   the type chip (capped at 42% width) so wrapped dot rows never paint under it. */
.hr-property-card .hr-pc-card--overlay .hr-pc-media__dots {
  bottom: auto;
  top: 2px;
  justify-content: flex-start;
  left: 4px;
  right: 4px;
  padding-right: 46%;
}

/* ── Skeleton ───────────────────────────────────────────────── */

.hr-property-card .hr-pc-skeleton__media,
.hr-property-card .hr-pc-skeleton__line {
  background: var(--hfse-border);
  animation: hr-pc-pulse 1.6s ease-in-out infinite;
}

.hr-property-card .hr-pc-skeleton__line {
  height: 0.9rem;
  border-radius: 4px;
  margin-bottom: 0.5rem;
}

.hr-property-card .hr-pc-skeleton__line--title {
  height: 1.1rem;
  width: 70%;
}

.hr-property-card .hr-pc-skeleton__line--short {
  width: 45%;
}

.hr-property-card .hr-pc-skeleton__line--price {
  width: 55%;
  margin-bottom: 0;
}

@keyframes hr-pc-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
  .hr-property-card .hr-pc-card,
  .hr-property-card .hr-pc-media__img,
  .hr-property-card .hr-pc-media__nav {
    transition: none;
  }

  .hr-property-card .hr-pc-card:hover {
    transform: none;
  }

  .hr-property-card .hr-pc-card:hover .hr-pc-media__img.is-active {
    transform: none;
  }

  .hr-property-card .hr-pc-skeleton__media,
  .hr-property-card .hr-pc-skeleton__line {
    animation: none;
  }
}
/* ==========================================================================
   Explorer Widget - CSS matching WP plugin markup class names
   ========================================================================== */
/* Card styles (hk-* base utilities + property card + rating) live in the
   shared card module; imported first so cascade order matches the old
   single-file layout. */
/* ==========================================================================
   Shared explorer-look property card (TemplateExplorer)
   ==========================================================================
   Extracted verbatim from widgets/explorer/explorer.css so every consumer of
   the shared card (explorer, related-properties, property-card) can pull in
   just the card styles instead of the whole explorer stylesheet. Internal rule
   order is preserved: hk-* base utilities, then the card block, then the
   rating block (#2516), which intentionally overrides earlier card rules.
   explorer.css @imports this file at its top, so explorer output order keeps
   the base utilities first, exactly where they originally sat. */
/* UIKit-like base classes (hk-*) used by property cards */
.hk-flex { display: flex; }
.hk-flex-column { flex-direction: column; }
.hk-flex-between { justify-content: space-between; }
.hk-flex-middle { align-items: center; }
.hk-flex-top { align-items: flex-start; }
.hk-flex-center { justify-content: center; }
.hk-flex-auto { flex: 1 1 auto; min-width: 0; }
.hk-flex-none { flex: none; }
.hk-card {
  position: relative;
  box-sizing: border-box;
  transition: box-shadow 0.1s ease-in-out;
}
.hk-card-default {
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-card-fg, #666);
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}
.hk-card-hover:hover {
  box-shadow: 0 14px 25px rgba(0, 0, 0, 0.16);
}
.hk-card-small .hk-card-body {
  padding: 15px 20px;
}
.hk-card-body {
  flex: 1 1 auto;
}
.hk-card-media-top {
  overflow: hidden;
}
.hk-card-media-top img {
  width: 100%;
  display: block;
}
.hk-link-toggle {
  text-decoration: none;
  color: inherit;
}
.hk-link-toggle:hover {
  text-decoration: none;
  color: inherit;
}
.hk-h5 {
  margin: 0 0 0;
  font-size: 1rem;
  line-height: 1.4;
  font-weight: 500;
}
.hk-margin-small-top { margin-top: 10px; }
.hk-margin-remove-first-child > :first-child { margin-top: 0; }
.hk-margin-small-bottom { margin-bottom: 10px; }
.hk-text-small { font-size: 0.875rem; }
.hk-position-relative { position: relative; }
.hk-position-center-left {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translateY(-50%);
}
.hk-position-center-right {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translateY(-50%);
}
.hk-position-small {
  margin: 10px;
}
.hk-position-bottom {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
}
.hk-visible-toggle:not(:hover) .hk-hidden-hover {
  opacity: 0;
}
.hk-hidden-hover {
  transition: opacity 0.15s ease;
  cursor: pointer;
}
/* Dot navigation */
.hk-dotnav {
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  list-style: none;
  gap: 6px;
}
.hk-dotnav > li > a,
.hk-dotnav > li > button {
  display: block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.5);
  text-indent: -9999px;
  overflow: hidden;
  border: none;
  padding: 0;
  cursor: pointer;
}
.hk-dotnav > li.hk-active > a,
.hk-dotnav > li:hover > a,
.hk-dotnav > li.hk-active > button,
.hk-dotnav > li:hover > button {
  background: #fff;
}
/* Slideshow nav arrows */
.hfse-property-slideshow-prev-btn,
.hfse-property-slideshow-next-btn {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: rgba(0, 0, 0, 0.3);
  border-radius: 50%;
  z-index: 5;
}
.hfse-property-slideshow-prev-btn::before {
  content: '';
  width: 8px;
  height: 8px;
  border-left: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: rotate(45deg);
  margin-left: 2px;
}
.hfse-property-slideshow-next-btn::before {
  content: '';
  width: 8px;
  height: 8px;
  border-right: 2px solid #fff;
  border-top: 2px solid #fff;
  transform: rotate(45deg);
  margin-right: 2px;
}
/* Explorer-specific dialog card overrides */
.hfse-form-modal {
  max-width: 520px;
}
.hfse-form-modal .hk-modal-body {
  overflow-y: auto;
}
/* ==========================================================================
   Property Card
   ========================================================================== */
.hfse-property-container {
  width: 100%;
  min-width: 0;
}
.hfse-property-card {
  width: 100%;
  height: 100%;
}
.hfse-property-body {
  flex-grow: 1;
}
.hfse-property-meta {
  padding: 0 20px;
}
.hfse-property-meta-primary {
  display: flex;
  margin-top: 10px;
  flex-wrap: nowrap;
  justify-content: space-between;
}
.hfse-property-meta-primary .hfse-property-locations,
.hfse-property-meta-primary .hfse-property-types {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 24px;
  max-width: 80%;
  font-size: 13px;
  line-height: 16px;
  box-sizing: border-box;
  padding: 3px 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hfse-property-meta-primary svg {
  flex-shrink: 0;
  opacity: 0.6;
}
.hfse-property-meta-primary .hfse-property-locations {
  padding-right: 10px;
}
.hfse-property-meta-secondary {
  display: flex;
  margin-top: 10px;
  flex-wrap: nowrap;
  padding: 10px 0 15px;
  border-top: 1px solid var(--hfse-border, #eee);
  justify-content: space-between;
}
.hfse-property-meta-secondary .hfse-property-guests,
.hfse-property-meta-secondary .hfse-property-bedrooms,
.hfse-property-meta-secondary .hfse-property-bathrooms {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 28px;
  font-size: 16px;
  line-height: 20px;
  box-sizing: border-box;
  padding: 4px 0;
}
.hfse-property-meta-secondary svg {
  flex-shrink: 0;
  opacity: 0.6;
  width: 20px;
  height: 20px;
}
.hfse-property-container {
  position: relative;
}
.hfse-property-slideshow-dotnav {
  margin-bottom: 12px;
}
.hfse-property-container .hk-dotnav > * > * {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}
/* Groups / Labels */
.hfse-property-groups, .hfse-property-favorite-toggle-btn {
  z-index: 10;
  position: absolute;
  width: auto !important;
}
.hfse-property-groups {
  top: 6px;
  left: 6px;
}
.hfse-property-group {
  color: #fff;
  padding: 3px 5px;
  margin: 0 5px 5px 0;
  display: inline-block;
  background-color: rgba(0, 0, 0, 0.7);
}
/* Label Designer badges (#1069): inline style carries the cascade; this only
   lays out the optional icon. Unstyled legacy badge above is untouched. */
.hfse-property-group.hfse-label-styled {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  vertical-align: top;
}
.hfse-label-icon {
  width: 1em;
  height: 1em;
  object-fit: contain;
  flex: 0 0 auto;
}
/* Overlay groups live inside .hk-card-media-top, whose `img { width: 100% }`
   (the photo rule) would stretch an icon <img> across its badge; the
   badge-scoped selector out-ranks it so icons stay 1em in both placements. */
.hfse-property-group .hfse-label-icon {
  width: 1em;
  height: 1em;
  display: inline-block;
}
/* Icon recolor (#1370 slice 2; toolkit CssGenerator::build_icon_rule with
   recolor_icon): an .svg icon becomes a mask over currentColor, so it takes
   the badge text colour — set or auto-contrast. The mask URL is inline per
   badge (TemplateExplorer iconMaskStyle); the geometry lives here. */
.hfse-label-icon-tint {
  background-color: currentColor;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
/* Icon-only (toolkit icon_only, font-size:0 on the badge). The text stays in
   the DOM — it is the card link's accessible name — but paints nothing; the
   absolute box leaves the inline-flex flow, so no gap is left beside the icon. */
.hfse-label-icon-only {
  position: relative;
}
.hfse-label-icon-only-text {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
/* Label Designer overlay placement (#1370 slice 1; toolkit CssGenerator
   position / offset_x / offset_y). Overlay badges leave the top-left row and
   pin to a photo corner. The layer lives INSIDE .hfse-property-slideshow
   (position:relative with an explicit aspect-ratio — the box the toolkit's
   labels-frontend.js shim moves its row into), so bottom corners anchor to
   the photo, not to the card. Insets are inline per group (corner + offset);
   pointer-events:none keeps the slideshow arrows and dots clickable. */
.hfse-property-labels-overlay {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 10;
  pointer-events: none;
}
.hfse-label-overlay-group {
  position: absolute;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 5px;
}
.hfse-label-overlay-top-right,
.hfse-label-overlay-bottom-right {
  justify-content: flex-end;
}
.hfse-label-overlay-bottom-left,
.hfse-label-overlay-bottom-right {
  flex-wrap: wrap-reverse;
}
/* The row's per-badge margin (0 5px 5px 0) would push right/bottom-anchored
   badges 5px off their offset; the group gap spaces them instead. */
.hfse-label-overlay-group .hfse-property-group {
  margin: 0;
}
/* Favorite button */
.hfse-property-favorite-toggle-btn {
  top: 10px;
  right: 10px;
}
.hfse-property-favorite-toggle-btn svg {
  color: white;
}
.hfse-property-favorite-toggle-btn svg > path {
  fill: white;
}
.hfse-property-favorite-toggle-btn.favorite svg {
  color: red;
}
.hfse-property-favorite-toggle-btn.favorite svg > * {
  fill: red;
}
/* Rating */
.hfse-property-rating {
  line-height: 20px;
}
.hfse-property-rating-icon polygon {
  fill: var(--hfse-foreground, #333);
  stroke: var(--hfse-foreground, #333) !important;
}
/* Price */
.hfse-property-price-container {
  font-size: 14px;
  color: var(--hfse-card-fg, #666);
}
.hfse-property-price strong {
  font-size: 16px;
  color: var(--hfse-foreground, #333);
}
.hfse-property-price-sep {
  margin: 0 2px;
}
.hfse-property-price-total {
  font-size: 13px;
}
.hfse-property-tax-note {
  font-size: 12px;
  color: var(--hfse-muted-foreground, #999);
}
.hfse-property-price del {
  color: var(--hfse-muted-foreground, #999);
  font-size: 13px;
  margin-right: 4px;
}
.hfse-property-price-loading svg {
  display: inline-block;
  vertical-align: middle;
}
/* "No dates available" (toolkit lowest-rate-availability): a label where a
   price would be, when the property has no bookable nights. */
.hfse-property-price-unavailable {
  opacity: 0.75;
}
.full-price-failed-text {
  color: var(--hfse-muted-foreground, #717171);
  text-decoration: underline;
  cursor: pointer;
  font-size: 13px;
}
.hfse-property-subtitle {
  font-size: 13px;
  color: var(--hfse-muted-foreground, #999);
  margin-top: 4px;
}
/* Favorite Button */
.hfse-property-container {
  position: relative;
}
.hfse-property-favorite-toggle-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  background: none;
  border: none;
  padding: 4px;
  cursor: pointer;
  color: white;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
  transition: transform 0.15s ease;
}
.hfse-property-favorite-toggle-btn:hover {
  transform: scale(1.15);
}
.hfse-property-favorite-toggle-btn.favorite {
  color: red;
}
.hfse-property-favorite-toggle-btn svg {
  display: block;
}
/* Slideshow */
.hfse-property-slideshow {
  overflow: hidden;
}
.hk-slideshow-items {
  margin: 0;
  padding: 0;
  list-style: none;
}
.hfse-property-slideshow-item {
  list-style: none;
}
/* ---------- Property card rating (central #2516) ---------- */
.hfse-property-rating {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    flex: 0 0 auto;
    margin-left: 8px;
    font-size: 0.8125rem;
    color: var(--hfse-foreground, #333);
    white-space: nowrap;
}
.hfse-property-rating svg {
    color: #f5a623;
}
.hfse-property-rating-avg {
    font-weight: 700;
}
.hfse-property-rating-count {
    color: var(--hfse-muted-foreground, #999);
}
/* ==========================================================================
   Filter Form
   ========================================================================== */
/* Filter bar */
.hfse-filter-bar {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 20px;
  margin-bottom: 15px;
}
/* #1276: with the bar hidden, SecondaryRow (count/sort/map) renders
   directly as a child of .hfse-body instead of nested inside
   .hfse-filter-bar. Give it the bar's own box model so the standalone
   header matches pixel-for-pixel, WITHOUT inheriting .hfse-filter-bar's
   sticky-filter whole-block pin (`.sticky-filter .hfse-filter-bar:not(.hfse-sbp)`)
   or the mobile-results-topbar rule (`.hfse-mres-topbar .hfse-filter-bar`) — a
   bare results header is not a filter bar and must not pin/pick up either.
   Dormant whenever the real bar is shown: in that case .hfse-form is nested
   one level inside .hfse-filter-bar, never a direct child of .hfse-body, so
   this selector never matches there. */
.hfse-body > .hfse-form {
  padding: 20px;
  margin-bottom: 15px;
}
/* The legacy `.hfse-form ~ .hfse-properties-container { margin-top: 20px }`
   rule (Grid Container section) never matched in-bar — there .hfse-form is
   nested inside .hfse-filter-bar, not the grid's sibling — but it DOES match
   the standalone mount, and its 20px collapsed against the 15px above to sit
   the standalone header 5px lower than the in-bar one. Zero it here so the
   header-to-grid gap is the bar's 15px in both layouts. */
.hfse-body > .hfse-form ~ .hfse-properties-container {
  margin-top: 0;
}
.hfse-form input::placeholder {
  color: var(--hfse-input-placeholder, #000);
}
.hfse-form input:focus {
  outline: none !important;
}
.hfse-form > div + div {
  margin-top: 15px;
}
.hfse-form-primary-fields, .hfse-form-meta {
  display: flex;
  flex-wrap: wrap;
  margin-left: -8px;
  align-items: center;
}
.hfse-form-primary-fields > *, .hfse-form-meta > * {
  padding-left: 8px;
}
.hfse-form-primary-fields > * + * {
  margin-top: 10px;
}
.hfse-form-primary-fields > * {
  flex: 1 0 100%;
  box-sizing: border-box;
}
@media screen and (min-width: 640px) {
  .hfse-form-primary-fields > * {
    flex: 1;
    margin-top: 0;
    min-width: 1px;
  }
  .hfse-form-primary-fields > .hfse-form-search-btn-container {
    flex: 0 0 auto;
  }
  /* Icon-only filters trigger keeps its fixed square size (WP parity) */
  .hfse-form-primary-fields > .hfse-form-additional-filters-btn {
    flex: 0 0 auto;
  }
}
/* Primary field trigger with icon */
.hfse-form-field-trigger {
  display: flex;
  align-items: center;
  width: 100%;
  height: 50px;
  border: none;
  color: var(--hfse-input-fg, #000);
  font-size: 16px;
  padding: 10px 15px;
  min-height: inherit;
  border-radius: 4px;
  box-sizing: border-box;
  background-color: var(--hfse-input-bg, #DDDFE0);
  cursor: pointer;
  gap: 10px;
}
.hfse-form-field-icon {
  display: flex;
  align-items: center;
  flex-shrink: 0;
  color: var(--hfse-muted-foreground, #555);
}
.hfse-form-field-trigger .hk-input {
  flex: 1;
  height: auto;
  border: none;
  padding: 0;
  background: transparent;
  cursor: pointer;
  min-width: 0;
}
.hfse-form-secondary-fields {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
}
.hfse-form-secondary-fields > div {
  display: flex;
  flex-wrap: wrap;
  position: relative;
  align-items: center;
}
.hfse-form-meta {
  justify-content: center;
  gap: 12px;
}
.hfse-form-primary-fields .hk-input {
  width: 100%;
  height: 50px;
  border: none;
  color: var(--hfse-input-fg, #000);
  font-size: 16px;
  padding: 10px 15px;
  min-height: inherit;
  border-radius: 4px;
  box-sizing: border-box;
  background-color: var(--hfse-input-bg, #DDDFE0);
  cursor: pointer;
}
.hfse-form-primary-fields .hk-input:focus {
  color: var(--hfse-input-fg, #000);
  background-color: var(--hfse-input-bg, #DDDFE0);
}
/* Search button */
.hfse-form-search-btn {
  height: 50px;
  padding: 0 30px;
  font-size: 14px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  border: none;
  border-radius: 4px;
  color: #fff;
  background-color: #b8986a;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color 0.2s;
}
.hfse-form-search-btn:hover {
  background-color: #a6875b;
}
/* Mobile: stacked primary fields → full-width search button (WP parity) */
@media (max-width: 639px) {
  .hfse-form-search-btn {
    width: 100%;
  }
}
/* Filter buttons */
.hfse-form .hfse-form-additional-filters-btn {
  border: 0;
  height: 35px;
  color: var(--hfse-foreground, #000);
  display: flex;
  gap: 6px;
  font-size: 12px;
  letter-spacing: 0.5px;
  padding: 0 12px;
  font-weight: 600;
  line-height: 35px;
  border-radius: 4px;
  align-items: center;
  box-sizing: border-box;
  text-transform: uppercase;
  background-color: var(--hfse-card-bg, #fff);
  cursor: pointer;
}
/* WP parity: icon-only square button, filled accent, same 50px height as the
   search button (WP renders no visible label — ours stays for screen readers). */
.hfse-form .hfse-form-additional-filters-btn {
  color: #fff;
  width: 52px;
  height: 50px;
  /* The row spaces children via their own padding-left gutter; a padded
     icon-only button would render off-center, so trade it for margin. */
  padding: 0;
  margin-left: 8px;
  justify-content: center;
  position: relative;
  background-color: var(--hfse-accent, #b8986a);
  border: 0;
  transition: filter 0.2s;
}
.hfse-form .hfse-form-additional-filters-btn svg {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
}
.hfse-form .hfse-form-additional-filters-btn-text {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.hfse-form .hfse-form-additional-filters-btn:hover,
.hfse-form .hfse-form-additional-filters-btn:active,
.hfse-form .hfse-form-additional-filters-btn:focus {
  filter: brightness(0.9);
}
/* Filter state indicator — corner badge on the icon-only trigger */
.hfse-form-additional-filters-state {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
}
.hfse-form-additional-filters-btn.modified .hfse-form-additional-filters-state {
  background-color: currentColor;
}
/* Property count */
.hfse-form-property-count {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 14px;
  color: var(--hfse-foreground, #333);
  white-space: nowrap;
}
.hfse-form-property-count strong {
  font-weight: 700;
}
/* Field labels */
.hfse-form .field-label {
  width: 100%;
  display: block;
  color: var(--hfse-muted-foreground, #555555);
  font-weight: 500;
  text-align: left;
  margin-bottom: 10px;
  text-transform: capitalize;
}
.hfse-form .field-control {
  position: relative;
}
/* Number controls */
.hfse-number-with-control {
  width: 90px;
  white-space: nowrap;
}
.hfse-number-with-control .reduce-btn,
.hfse-number-with-control .increase-btn {
  width: 20px;
  height: 20px;
  line-height: 1;
  cursor: pointer;
  font-size: 18px;
  box-shadow: none;
  color: var(--hfse-card-bg, #ffffff);
  text-align: center;
  border-radius: 4px;
  display: inline-block;
  vertical-align: middle;
  background-color: var(--hfse-foreground, #000000);
  border: none;
  user-select: none;
}
/* At the party ceiling: the control stays in place, it just stops responding. */
.hfse-number-with-control .hfse-number-control-disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.hfse-number-with-control .number-input {
  padding: 0;
  width: 100%;
  height: 20px;
  color: var(--hfse-foreground, #000);
  border: none;
  line-height: 1;
  max-width: 32px;
  font-size: 14px;
  font-weight: 600;
  box-shadow: none;
  text-align: center;
  display: inline-block;
  vertical-align: middle;
  -webkit-appearance: none;
  background: none !important;
  -moz-appearance: textfield;
  appearance: textfield;
}
/* Checkbox and radio */
.hk-checkbox,
.hk-radio {
  border: 1px solid var(--hfse-border, #cacacf);
  width: 16px;
  height: 16px;
  margin-right: 10px;
  vertical-align: middle;
}
.hk-radio {
  margin-right: 5px;
}
/* Form label */
.hk-form-label {
  font-size: 13px;
  font-style: normal;
  letter-spacing: 0;
}
.hk-text-meta {
  font-size: 12px;
  color: var(--hfse-muted-foreground, #999);
}
.hk-h4 {
  font-size: 1.25rem;
  font-weight: 500;
  margin: 0;
}
.hk-h6 {
  font-size: 0.875rem;
  font-weight: 500;
  margin: 0;
}
/* Width utilities for guest filter */
.hk-width-3-5 { width: 60%; }
.hk-width-2-5 { width: 40%; }
.hk-margin { margin-top: 20px; }
/* Base input */
.hk-input {
  display: block;
  width: 100%;
  padding: 8px 12px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--hfse-input-fg, #333);
  background-color: var(--hfse-input-bg, #fff);
  border: 1px solid var(--hfse-border, #ddd);
  border-radius: 4px;
  outline: none;
  box-sizing: border-box;
}
.hk-input:focus {
  border-color: var(--hfse-muted-foreground, #aaa);
}
.hk-input::placeholder {
  color: var(--hfse-input-placeholder, #b1b1b1);
}
/* Modal footer buttons */
.hk-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 6px 16px;
  font-size: 13px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  text-transform: uppercase;
  font-weight: 600;
  background: transparent;
}
.hk-button.bg-accent {
  color: #fff;
}
.hk-button-primary:hover {
  opacity: 0.9;
}
.hk-button-link {
  color: var(--hfse-foreground, #000);
  background: transparent;
  text-decoration: underline;
}
.hk-button-small {
  padding: 10px 20px;
  font-size: 12px;
  line-height: 1;
}
.hk-margin-bottom {
  margin-bottom: 16px;
}
.hk-margin-auto-left {
  margin-left: auto;
}
/* Zone/Location modal styles */
.hfse-form-zone-input {
  border-radius: 4px;
  background-color: var(--hfse-input-bg, #DDDFE0);
  padding: 10px 15px 5px 15px;
}
.hfse-form-zone-input-fields {
  display: flex;
  flex-wrap: wrap;
}
.hfse-form-zone-selections {
  display: inline-flex;
  flex-wrap: wrap;
}
.hfse-form-zone-selection {
  color: var(--hfse-card-bg, #fff);
  line-height: 13px;
  font-size: 12px;
  padding: 6px 12px;
  margin: 0 5px 5px 0;
  border-radius: 13px;
  display: inline-block;
  background-color: var(--hfse-foreground, #000);
  cursor: pointer;
}
.hfse-form-zone-keyword {
  padding: 0;
  width: 120px;
  border: none;
  height: 25px;
  line-height: 25px;
  margin-bottom: 5px;
  background-color: transparent;
  font-size: 14px;
  color: var(--hfse-input-fg, inherit);
}
.hfse-form-zone-keyword:focus {
  outline: none;
}
.hfse-form-zone-subfield {
  margin-bottom: 20px;
}
.hfse-form-zone-subfield-locations {
  display: flex;
  flex-wrap: wrap;
}
.hfse-form-zone-label {
  font-size: 14px;
  font-weight: 500;
  margin-bottom: 10px;
}
.hfse-form-zone-btn {
  width: 100%;
  color: var(--hfse-foreground, #333);
  border: 2px solid transparent;
  padding: 8px;
  text-align: left;
  box-sizing: border-box;
  border-radius: 30px;
  margin-bottom: 10px;
  box-shadow: none;
  background-color: transparent;
  cursor: pointer;
}
@media screen and (min-width: 640px) {
  .hfse-form-zone-btn {
    margin-right: 10px;
    min-width: calc(50% - 10px);
    max-width: calc(50% - 10px);
  }
}
.hfse-form-zone-btn:hover, .hfse-form-zone-btn.hfse-selected {
  border-color: var(--hfse-border, #ddd);
}
.hfse-form-zone-btn .name {
  font-size: 14px;
}
.hfse-form-zone-btn .subheading {
  color: var(--hfse-muted-foreground, #333);
  font-size: 12px;
}
.hfse-form-zone-city {
  padding-left: 15px;
}
.hfse-form-zone-no-results {
  padding: 20px;
  text-align: center;
  color: var(--hfse-muted-foreground, #999);
}
/* Responsive filter layout */
@media only screen and (max-width: 980px) {
  .hfse-form-secondary-fields > div + div {
    margin-top: 10px;
  }
  .hfse-form-secondary-fields-center {
    order: 5;
    width: 100%;
    justify-content: center;
  }
}
/* ==========================================================================
   Grid Container
   ========================================================================== */
.hfse-form ~ .hfse-properties-container {
  margin-top: 20px;
}
.hfse-properties {
  display: grid;
  grid-template-columns: repeat(var(--hfse-grid-columns, 1), 1fr);
  gap: var(--hfse-grid-gap, 16px);
  padding: 20px;
}
@media (min-width: 600px) {
  .hfse-properties {
    grid-template-columns: repeat(var(--hfse-grid-columns-780, 2), 1fr);
  }
}
@media (min-width: 960px) {
  .hfse-properties {
    grid-template-columns: repeat(var(--hfse-grid-columns-960, 3), 1fr);
  }
}
.hfse-property-container.property-loading .hfse-property-meta-primary .terms {
  background-image: none !important;
}
/* ==========================================================================
   Responsive Grid (matching WP plugin breakpoints)
   Default: 3 columns on desktop, 2 on tablet, 1 on mobile
   ========================================================================== */
/* Grid column sizing is handled by CSS Grid on .hfse-properties */
/* ==========================================================================
   No items
   ========================================================================== */
.hfse-no-items {
  /* The empty state renders inside the .hfse-properties grid; without spanning
     every column it only fills the first track, so the "centered" text sat in
     the left third of the widget. */
  grid-column: 1 / -1;
  width: 100%;
  padding: 40px 20px;
  text-align: center;
  color: var(--hfse-muted-foreground, #999);
  font-size: 16px;
}
/* ==========================================================================
   Load more
   ========================================================================== */
/* Mirrored (scoped) by buildPreviewCss in common/property-card/skin-preview.tsx
   for the dashboard's Card Template preview — keep the copies in sync. */
.hfse-load-more-container {
  text-align: center;
  margin-top: 20px;
}
.hfse-load-more-btn {
  padding: 10px 30px;
  font-size: 14px;
  border: 1px solid var(--hfse-border, #ddd);
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, inherit);
  cursor: pointer;
  border-radius: 4px;
  transition: background 0.2s;
}
.hfse-load-more-btn:hover {
  filter: brightness(0.95);
}
.hfse-load-more-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
/* ==========================================================================
   Slider Layout
   ========================================================================== */
.hfse-slider-container {
  position: relative;
  overflow: hidden;
}
.hfse-slider-track {
  display: flex;
  gap: var(--hfse-grid-gap, 16px);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.hfse-slider-track::-webkit-scrollbar {
  display: none;
}
.hfse-slider-card {
  flex: 0 0 calc((100% - (var(--hfse-grid-columns, 1) - 1) * var(--hfse-grid-gap, 16px)) / var(--hfse-grid-columns, 1));
  scroll-snap-align: start;
  min-width: 0;
}
@media (min-width: 600px) {
  .hfse-slider-card {
    flex: 0 0 calc((100% - (var(--hfse-grid-columns-780, 2) - 1) * var(--hfse-grid-gap, 16px)) / var(--hfse-grid-columns-780, 2));
  }
}
@media (min-width: 960px) {
  .hfse-slider-card {
    flex: 0 0 calc((100% - (var(--hfse-grid-columns-960, 3) - 1) * var(--hfse-grid-gap, 16px)) / var(--hfse-grid-columns-960, 3));
  }
}
.hfse-slider-nav {
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 10;
  width: 48px;
  border-radius: 0;
  border: none;
  background: transparent;
  color: var(--hfse-foreground, #333);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s, width 0.2s;
}
.hfse-slider-nav:hover {
  width: 64px;
  background: rgba(255, 255, 255, 0.6);
}
.dark .hfse-slider-nav:hover {
  background: rgba(0, 0, 0, 0.4);
}
.hfse-slider-nav-prev {
  left: 0;
}
.hfse-slider-nav-next {
  right: 0;
}
/* Slider dots */
.hfse-slider-dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: 16px;
}
.hfse-slider-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: none;
  padding: 0;
  cursor: pointer;
  background: var(--hfse-border, #ccc);
  transition: background 0.2s;
}
.hfse-slider-dot.active {
  background: var(--hfse-foreground, #333);
}
.hfse-slider-dot:hover {
  background: var(--hfse-muted-foreground, #999);
}
/* ==========================================================================
   Map Layout (matching WP plugin)
   ========================================================================== */
/* Root layout: sidebar (map) + body (filters + grid) */
.hfse {
  position: relative;
}
.hfse .hfse-body {
  padding: 0;
  box-sizing: border-box;
}
.hfse.with-map.map-hidden .hfse-sidebar,
.hfse.without-map .hfse-sidebar {
  display: none;
}
.hfse.without-map .hfse-body {
  width: 100%;
}
/* Map container — mobile default: stacked, 400px */
.hfse.with-map .hfse-sidebar {
  padding: 20px;
  box-sizing: border-box;
}
.hfse.with-map .hfse-map-container {
  width: 100%;
  height: 400px;
  position: relative;
  overflow: hidden;
  border-radius: 8px;
  background-color: var(--hfse-background, #eee);
}
.hfse-map {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  /* Toolkit mobile-map-gestures port (#1046 Wave A). Touch handling is the
     PROVIDER's: Leaflet's own CSS sets touch-action:none on .leaflet-container
     and Google's gestureHandling:greedy preventDefaults inside the canvas —
     a pane-level touch-action here would only add a dead band over the
     "Loading map…" placeholder (and the inline mobile map) where nothing yet
     consumes the touches. user-select keeps a map drag or a long-press from
     highlighting badges, pins and attribution; popup text and any inputs
     stay selectable. */
  -webkit-user-select: none;
  user-select: none;
}
.hfse-map .hfse-map-tooltip,
.hfse-map input,
.hfse-map textarea {
  -webkit-user-select: text;
  user-select: text;
}
/* Drag-past-edge guard (mapDragGuard.ts): while a pointer that went down on
   the map is held, nothing in the explorer is selectable, so a drag spilling
   past the map edge cannot paint selection across the property cards. Lifted
   on pointerup/cancel — cards stay copyable the rest of the time. */
.hfse.hfse-map-drag,
.hfse.hfse-map-drag * {
  -webkit-user-select: none;
  user-select: none;
}
/* Leaflet tile fix — prevent CSS resets from breaking tile layout */
.leaflet-container {
  width: 100% !important;
  height: 100% !important;
}
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
  position: absolute;
  left: 0;
  top: 0;
}
.leaflet-tile {
  -webkit-user-select: none;
  user-select: none;
  -webkit-user-drag: none;
}
.leaflet-tile-container img {
  max-width: none !important;
  max-height: none !important;
  width: 256px;
  height: 256px;
  padding: 0;
  margin: 0;
  border: 0;
}
/* Override Leaflet default icon styles */
.leaflet-div-icon {
  border: none !important;
  background: transparent !important;
}
/* Map marker wrapper */
.hfse-map-marker-wrapper {
  border: none !important;
  background: transparent !important;
}
/* Map badge (marker) styles */
.hfse-map-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--hfse-card-bg, #fff);
  border-radius: 20px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.18);
  cursor: pointer;
  transition: transform 0.1s ease, background 0.15s ease, color 0.15s ease;
  white-space: nowrap;
  transform: translate(-50%, -50%);
  position: relative;
}
.hfse-map-badge-price {
  font-weight: 600;
  font-size: 14px;
  padding: 8px 14px;
  color: var(--hfse-foreground, #222);
}
.hfse-map-badge-price:hover,
.hfse-map-badge-focus {
  background: var(--hfse-foreground, #222);
  color: var(--hfse-card-bg, #fff);
  transform: translate(-50%, -50%) scale(1.08);
}
.hfse-map-badge-icon {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  padding: 0;
}
.hfse-map-badge-icon svg {
  width: 16px;
  height: 16px;
}
.hfse-map-badge-parent-focus {
  z-index: 9999 !important;
}
.hfse-map-badge-parent-focus .hfse-map-badge {
  background: var(--hfse-foreground, #222);
  color: var(--hfse-card-bg, #fff);
  transform: translate(-50%, -50%) scale(1.08);
}
/* ── Map stacking / clustering (toolkit map-stacking port, #854) ──────────
   Colors ride CSS custom properties set inline on .hfse-map-container from
   the widget's map.stacking config (toolkit defaults when absent). */
/* Stacked badge: [price range][count bubble] pill for co-located pins */
.hfse-stack-wrapper {
  border: none !important;
  background: transparent !important;
  overflow: visible !important;
}
.hfse-map-badge-stacked {
  gap: 4px;
  background: var(--hfse-stack-badge-bg, #1a1a2e);
  color: var(--hfse-stack-badge-text, #fff);
  padding: 6px 10px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
}
.hfse-map-badge-stacked.hfse-stack-count-only {
  /* No price text (price display "none"): shrink to a circle around the count */
  padding: 4px;
  border-radius: 50%;
}
.hfse-stack-count {
  background: var(--hfse-stack-count-bg, #058ef9);
  color: var(--hfse-stack-count-text, #fff);
  border-radius: 50%;
  min-width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
  font-weight: 700;
  padding: 0 2px;
}
.hfse-stack-wrapper.hfse-map-badge-parent-focus .hfse-map-badge-stacked {
  background: var(--hfse-stack-focus, #3b82f6);
  color: #fff;
}
/* Spiderfy: center dot, fanned leaves, connector legs */
.hfse-spider-center-wrap {
  border: none !important;
  background: transparent !important;
}
.hfse-spider-center {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--hfse-stack-center-dot, #1a1a2e);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
  cursor: pointer;
}
.hfse-spider-leaf {
  border: none !important;
  background: transparent !important;
}
.hfse-spider-leaf.hfse-map-badge-parent-focus .hfse-map-badge {
  background: var(--hfse-stack-focus, #3b82f6);
  color: #fff;
}
.hfse-spider-animating {
  transition: transform 0.3s ease-out !important;
}
/* Google provider (#1203): the fan chrome is one overlay at the anchor — a
   0×0 box holding the center dot and the legs as rotated dashed lines, so
   the fan needs no repositioning per zoom (Leaflet draws polylines). */
.hfse-spider-chrome {
  position: relative;
  width: 0;
  height: 0;
}
.hfse-spider-chrome .hfse-spider-center {
  position: absolute;
  left: 0;
  top: 0;
  transform: translate(-50%, -50%);
}
.hfse-spider-leg-line {
  position: absolute;
  left: 0;
  top: 0;
  height: 0;
  border-top: 1.5px dashed var(--hfse-stack-connector, #1a1a2e);
  opacity: 0.4;
  transform-origin: 0 0;
  pointer-events: none;
}
/* Cluster bubbles (Leaflet.markercluster). The bundled halo-ring marker is a
   CSS MASK — only its alpha is read; --hfse-cluster-N supplies the visible
   tint, so one hex recolors the solid core and all halo rings per tier. The
   mask ships as an inline data: URI (--hfse-cluster-mask), never a second
   request a blocked/404 response could turn into invisible clusters. */
.hfse-cluster-wrap {
  border: none !important;
  background: transparent !important;
}
.hfse-cluster {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--hfse-stack-count-text, #fff);
  font-weight: 700;
  font-size: 14px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  cursor: pointer;
  /* Round geometry declared here AS WELL as carried by the mask: losing the
     mask (stripped inline style) costs the halo rings, not the shape. */
  border-radius: 50%;
  -webkit-mask-image: var(--hfse-cluster-mask);
  mask-image: var(--hfse-cluster-mask);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-position: center;
  -webkit-mask-size: contain;
  mask-size: contain;
}
.hfse-cluster--t1 { background: var(--hfse-cluster-1, #058ef9); }
.hfse-cluster--t2 { background: var(--hfse-cluster-2, #0b7fd4); }
.hfse-cluster--t3 { background: var(--hfse-cluster-3, #7a5cd6); }
.hfse-cluster--t4 { background: var(--hfse-cluster-4, #d1568a); }
.hfse-cluster--t5 { background: var(--hfse-cluster-5, #e2603f); }
/* Leaflet.markercluster ships its animation rules in MarkerCluster.css; the
   widget inlines the needed subset (the vendor stylesheet is not part of the
   asset pipeline). */
.leaflet-cluster-anim .leaflet-marker-icon,
.leaflet-cluster-anim .leaflet-marker-shadow {
  transition: transform 0.3s ease-out, opacity 0.3s ease-in;
}
.leaflet-cluster-spider-leg {
  transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
}
/* ── All-pins mode (toolkit map-all-pins port, #855) ──────────────────────
   Dot markers for beyond-the-loaded-page homes + their compact click card.
   The dot reuses the stacking badge color var so palettes apply to both. */
.hfse-allpins-marker {
  border: none !important;
  background: transparent !important;
}
.hfse-allpins-dot {
  width: 14px;
  height: 14px;
  margin: 1px;
  border-radius: 50%;
  background: var(--hfse-stack-badge-bg, #1a1a2e);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
  box-sizing: border-box;
  cursor: pointer;
  transition: transform 0.15s ease;
}
.hfse-allpins-marker:hover .hfse-allpins-dot {
  transform: scale(1.35);
}
.hfse-allpins-tooltip {
  position: relative;
  width: 220px;
  z-index: 1000002;
}
.hfse-allpins-card {
  display: block;
  padding: 10px 12px;
  text-decoration: none;
  color: var(--hfse-foreground, #333);
}
.hfse-allpins-card-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.hfse-allpins-card-price {
  margin-top: 2px;
  font-size: 13px;
  opacity: 0.7;
}
/* Map tooltip (popup) */
.hfse-map-tooltip {
  position: relative;
  width: 300px;
  z-index: 1000002;
}
.hfse-map-tooltip-content {
  border-radius: 10px;
  overflow: hidden;
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #333);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
}
.hfse-map-tooltip-content a {
  text-decoration: none;
  color: var(--hfse-foreground, #333);
  display: block;
}
.hfse-map-tooltip-close-btn {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 1;
  transition: background 0.15s;
}
.hfse-map-tooltip-close-btn:hover {
  background: rgba(0, 0, 0, 0.7);
}
.hfse-map-tooltip-close-btn svg {
  width: 12px;
  height: 12px;
}
/* Tooltip content sections */
.hfse-property-infowindow-header {
  width: 100%;
  height: 160px;
  position: relative;
  overflow: hidden;
}
.hfse-property-infowindow-header-overlay {
  background: linear-gradient(to bottom, rgba(0,0,0,0.1), transparent);
}
.hfse-property-infowindow-body {
  padding: 12px 15px;
  color: var(--hfse-foreground, #333);
}
.hfse-property-infowindow-body .hfse-property-title {
  font-size: 14px;
  font-weight: 600;
  line-height: 1.3;
  margin: 0 0 4px;
  color: var(--hfse-foreground, #222);
}
.hfse-property-infowindow-body .hfse-property-subtitle {
  font-size: 12px;
  color: var(--hfse-muted-foreground, #555);
  margin: 0 0 6px;
}
.hfse-property-infowindow-price {
  font-size: 14px;
  color: var(--hfse-foreground, #333);
  margin-bottom: 6px;
}
.hfse-property-infowindow-price strong {
  font-weight: 600;
  color: var(--hfse-foreground, #222);
}
/* Map controls container */
.hfse-map-controls {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  pointer-events: none;
}
.hfse-map-controls > * {
  pointer-events: auto;
}
/* ==========================================================================
   Map chrome (slice E, #928) — toolkit "Map Controls" port (PR #428).
   Hide-map + fullscreen stacked on the grid-adjacent top corner, zoom as a
   single pill stack on the opposite corner; the show tab (MapShowTab.tsx)
   is fixed to the window edge while the map is hidden. Corner sides mirror
   on map-left. Zoom + collapse are desktop-only (below 960px the stacked
   mobile map keeps pinch-zoom and the results-header text toggle);
   fullscreen shows at every width.
   ========================================================================== */
.hfse-mapctl-btn {
  appearance: none;
  -webkit-appearance: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: var(--hfse-map-control-bg, var(--hfse-card-bg, #fff));
  color: var(--hfse-map-control-color, var(--hfse-foreground, #222));
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.18);
  transition: box-shadow 0.15s ease;
}
.hfse-mapctl-btn:hover {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 4px 12px rgba(0, 0, 0, 0.24);
}
.hfse-mapctl-btn svg {
  display: block;
  width: 20px;
  height: 20px;
}
.hfse-mapctl-corner {
  position: absolute;
  top: 16px;
  left: 16px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.hfse.map-left .hfse-mapctl-corner {
  left: auto;
  right: 16px;
}
.hfse-mapctl-corner .hfse-mapctl-btn {
  position: relative; /* anchors the aria-label tooltip */
}
/* Chevrons point INTO the map — the direction it will fold away. */
.hfse.map-left .hfse-mapctl-collapse svg {
  transform: scaleX(-1);
}
.hfse-mapctl-collapse,
.hfse-mapctl-zoom {
  display: none;
}
@media (min-width: 960px) {
  .hfse-mapctl-collapse {
    display: flex;
  }
  /* Zoom: one pill, + over −, in the top corner AWAY from the results.
     Buttons lose their individual shadow; the pill carries it. */
  .hfse-mapctl-zoom {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 16px;
    right: 16px;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.18);
  }
  .hfse.map-left .hfse-mapctl-zoom {
    right: auto;
    left: 16px;
  }
  .hfse-mapctl-zoom .hfse-mapctl-btn {
    border-radius: 0;
    box-shadow: none;
  }
  .hfse-mapctl-zoom .hfse-mapctl-btn:hover {
    box-shadow: none;
    filter: brightness(0.96);
  }
  .hfse-mapctl-zoom .hfse-mapctl-btn + .hfse-mapctl-btn {
    border-top: 1px solid var(--hfse-border, rgba(0, 0, 0, 0.08));
  }
  /* The header HIDE MAP text button leaves the desktop layout — the on-map
     collapse and the edge show-tab replace it. It stays the only map toggle
     at mobile widths, where the map is stacked. */
  .hfse.with-map .hfse-form-map-toggle-btn {
    display: none;
  }
}
/* "Show map" edge tab — flush to the window edge the map collapsed toward,
   rounded away from the edge only so it reads as a tab. Display is gated by
   the in-view class (IntersectionObserver in MapShowTab.tsx) plus desktop
   width; the component itself only mounts while the map is hidden. */
.hfse-mapctl-showtab {
  display: none;
  position: fixed;
  right: 0;
  z-index: 990;
  width: auto;
  height: 40px;
  padding: 0 12px;
  gap: 5px;
  border-radius: 8px 0 0 8px;
}
.hfse.map-left .hfse-mapctl-showtab {
  right: auto;
  left: 0;
  border-radius: 0 8px 8px 0;
}
/* Chevrons point back toward the results (opposite of the hide arrows); the
   map glyph beside them never flips. */
.hfse-mapctl-showtab svg:first-child {
  transform: scaleX(-1);
}
.hfse.map-left .hfse-mapctl-showtab svg:first-child {
  transform: none;
}
@media (min-width: 960px) {
  .hfse-mapctl-showtab.hfse-mapctl-showtab-inview {
    display: flex;
    animation: hfse-mapctl-tab-in 0.25s ease-out;
  }
  .hfse.map-left .hfse-mapctl-showtab.hfse-mapctl-showtab-inview {
    animation-name: hfse-mapctl-tab-in-left;
  }
}
@keyframes hfse-mapctl-tab-in {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(0);
  }
}
@keyframes hfse-mapctl-tab-in-left {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0);
  }
}
/* Combined query on purpose: the slide-in is only ever assigned at 960px+,
   and the datepicker's own reduced-motion kill list must stay the file's
   first bare prefers-reduced-motion block (searchbar-datepicker.test.tsx
   anchors on it). */
@media (min-width: 960px) and (prefers-reduced-motion: reduce) {
  .hfse-mapctl-showtab {
    animation: none !important;
  }
}
/* Hover/focus tooltip shared by the hide/show/fullscreen controls (zoom stays
   bare — + and − explain themselves), rendered from aria-label so the markup
   stays icon-only. Each control aims it at the free space beside it, mirrored
   on map-left layouts. */
.hfse-mapctl-tip::after {
  content: attr(aria-label);
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  padding: 7px 11px;
  border-radius: 6px;
  background-color: #222;
  color: #fff;
  font-size: 12px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s ease;
}
.hfse-mapctl-tip:hover::after,
.hfse-mapctl-tip:focus-visible::after {
  opacity: 1;
}
/* Corner controls: into the map. */
.hfse-mapctl-corner .hfse-mapctl-tip::after {
  left: calc(100% + 10px);
}
.hfse.map-left .hfse-mapctl-corner .hfse-mapctl-tip::after {
  left: auto;
  right: calc(100% + 10px);
}
/* Show tab: toward the results. */
.hfse-mapctl-showtab::after {
  right: calc(100% + 10px);
}
.hfse.map-left .hfse-mapctl-showtab::after {
  right: auto;
  left: calc(100% + 10px);
}
/* Map control base (search-as-move checkbox pill still renders on it) */
.map-control {
  background: var(--hfse-map-control-bg, var(--hfse-card-bg, #fff));
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
}
/* Infowindow term icons (#567) */
.hfse-infowindow-term-icon {
  width: 14px;
  height: 14px;
  margin-right: 6px;
  vertical-align: -2px;
  display: inline-block;
}
/* Search-as-move checkbox, restyled as the module's top-center white pill
   (slice F / SBP-10, #929 — toolkit map-controls .hrtk-mapctl-search port) */
.map-control.control-search {
  position: absolute;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  padding: 9px 16px;
  z-index: 1000;
  border-radius: 999px;
  font-size: 13px;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.18);
}
.map-control-input-container {
  display: flex;
  align-items: center;
  gap: 6px;
}
.map-control-checkbox {
  margin: 0;
  cursor: pointer;
}
.map-control-label {
  font-size: 13px;
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  color: var(--hfse-foreground, #333);
}
/* Tooltip infowindow meta */
.hfse-property-infowindow-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 8px;
  font-size: 12px;
  color: var(--hfse-muted-foreground, #555);
}
.hfse-property-infowindow-meta span:not(:last-child)::after {
  content: '·';
  margin-left: 8px;
}
/* Map toggle button */
.hfse-form-map-toggle-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 35px;
  padding: 0 12px;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, inherit);
  border: 2px solid var(--hfse-border, #ccc);
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s;
}
.hfse-form-map-toggle-btn:hover {
  filter: brightness(0.95);
}
.hfse-form-map-toggle-btn-icon {
  display: flex;
  align-items: center;
}
.hfse-form-map-toggle-btn-icon svg {
  width: 20px;
  height: 20px;
}
/* ==========================================================================
   Map Responsive
   ========================================================================== */
/* Desktop (960px+): side-by-side flex layout */
@media (min-width: 960px) {
  .hfse.with-map.map-visible {
    display: flex;
    flex-wrap: wrap;
    overflow: visible;
  }
  /* Section header spans the full width above the map+grid row (#455), rather than
     becoming a flex item competing for width inside the side-by-side layout. */
  .hfse.with-map.map-visible > .hr-widget-section {
    flex: 0 0 100%;
    width: 100%;
    order: -1;
  }
  .hfse.with-map.map-visible .hfse-body {
    width: 55%;
    box-sizing: border-box;
  }
  .hfse.with-map.map-visible.map-right .hfse-body {
    padding-right: 10px;
  }
  .hfse.with-map.map-visible.map-right .hfse-sidebar {
    padding-left: 10px;
  }
  .hfse.with-map.map-visible.map-left .hfse-body {
    padding-left: 10px;
  }
  .hfse.with-map.map-visible.map-left .hfse-sidebar {
    padding-right: 10px;
  }
  .hfse.with-map.map-visible .hfse-sidebar {
    width: 45%;
    overflow: visible;
    box-sizing: border-box;
  }
  .hfse.with-map.map-visible .hfse-map-container {
    top: 0;
    height: 100vh;
    position: sticky;
    margin-bottom: 0;
  }
  .hfse.map-visible.map-left .hfse-sidebar {
    order: 0;
  }
  .hfse.map-visible.map-right .hfse-sidebar {
    order: 2;
  }
}
/* Dark mode map shadow override */
.hfse.dark .hfse-map-badge {
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
}
/* ==========================================================================
   Date Range Picker Calendar (react-day-picker v9)
   ========================================================================== */
.hfse-form-date-options.hr-dialog-content {
  max-width: 640px;
  max-height: none;
  overflow: visible;
}
.hfse-date-calendar-body {
  overflow-x: auto;
  padding: 8px 0;
}
.hfse-rdp {
  /* Range palette transcribed from the toolkit datepicker
     (searchbar-pro.debug.css:2694-2707). The in-range fill is deliberately a
     flat neutral gray rather than the brand accent — that is a design choice
     in the reference, not an oversight, so it is ported as-is.

     These are the LIGHT values. The reference renders on WordPress themes and
     has no dark mode, so parity has nothing to say about one: useExplorerCss
     inverts the neutrals for `resolvedTheme === 'dark'`, where a #222 endpoint
     on the #1a1a1a dialog background would be invisible (~1.08:1). Every
     neutral a rule below paints must come from one of these tokens so that
     override reaches it — do not hardcode a hex in the rules. */
  --dp-range-bg: #f3f4f6;
  --dp-hover-range-bg: #f3f4f6;
  --dp-endpoint-bg: #222222;
  --dp-endpoint-color: #ffffff;
  --dp-range-color: #222222;
  --dp-cell-hover-bg: #f0f0f0;
  --dp-nav-border: rgba(0, 0, 0, 0.12);
  --dp-nav-disabled-color: #cccccc;
  --dp-nav-disabled-border: #e5e5e5;
  /* 8/6 a11y fix (Eli decision): weekday header + disabled-day numerals get
     their own tokens instead of riding --hfse-muted-foreground (2.85:1 light)
     and --hfse-border (1.26:1 light). #5f6368 = 6.05:1, #757575 = 4.61:1 on
     the white dialog; dark overrides in useExplorerCss (#9a9a9a / #8c8c8c). */
  --dp-weekday-color: #5f6368;
  --dp-disabled-color: #757575;
  /* The module declares 50% here (searchbar-pro.css:1889) and spends it on
     the week-edge caps of FULL-TRACK range cells — in a ≤960px sheet those
     cells render wider than tall (99×38 measured at 768px) and a percentage
     radius draws the caps as stretched ellipses (Eli r10 report, 8/8). The
     module's own bottom sheet carries the same latent artifact, so literal
     parity would port a bug. 999px engages the CSS overlapping-radii
     reduction instead: caps scale to half the cell HEIGHT — semicircular at
     any cell width, identical to 50% on square cells. */
  --dp-cell-radius: 999px;
  --rdp-accent: #333;
  --rdp-accent-fg: #fff;
  /* 44px = the module's --dp-cell-size (searchbar-pro.css:1888, same value in
     its mobile block) — the circle centered in each flexible-width cell.
     A MAXIMUM, not a fixed size (#1360): the circle was rigid, so a week row's
     min-content was a hard 7 × 44 = 308px, and since the weekday header shares
     the month's table the WHOLE grid stretched to 308 and OVERFLOWED any pane
     narrower than that instead of shrinking. Measured at a 534px months
     wrapper (a 584px bar, i.e. a 1280 desktop): 255px panes, 308px grids, the
     second month starting 29px before the first one ended — colliding day
     numerals, an "S S" weekday header, and 53px of silent horizontal scroll
     inside .hfse-date-calendar-body. The `min(100%, …)` under
     `.hfse-rdp-day-btn` keeps the circle at 44 wherever the pane can afford it
     and lets it ride the pane's 1/7 track where it cannot. */
  --rdp-cell: 44px;
  font-size: 14px;
  position: relative;
}
/* Nights badge row (toolkit: templates/search-bar.php:526-531, CSS 1868-1882).
   min-height holds the nav-button height so the grid below does not shift as
   the badge text changes length. */
.hfse-rdp-badge-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 32px;
  margin-bottom: 16px;
  padding: 0 4px;
}
.hfse-rdp-nights-badge {
  font-size: 14px;
  font-weight: 600;
  color: var(--hfse-foreground, #111827);
}
.hfse-rdp-months {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
}
.hfse-rdp-month {
  flex: 1;
  min-width: 250px;
}
/* react-day-picker's month table shrink-wraps to its content otherwise, and a
   shrink-wrapped table inside a flexed pane is exactly the squeezed-centred
   calendar the 8/7 parity strip flagged (#930). Stretched to the pane, the
   flex:1 day cells spread across the available width — the module's
   repeat(7, 1fr) week rows (searchbar-pro.css:2064-2066), whose day visual is
   likewise a FIXED circle centered in a flexible cell (css:2100-2108). */
.hfse-rdp-month-grid {
  width: 100%;
  border-collapse: collapse;
}
/* Week rows in a flex column with the module's 2px row gap (css:2058-2062). */
.hfse-rdp-weeks {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.hfse-rdp-caption {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 0;
  font-weight: 600;
  font-size: 14px;
}
/* Month-nav pair, grouped at the right of the badge header row (decision 26).
   The toolkit's .hrtk-sbp-datepicker__header holds the badge LEFT and the
   arrow pair RIGHT of one space-between row (searchbar-pro.css:1819-1841);
   here the badge row is the DayPicker root's previous sibling, so the pair is
   lifted into it: -48px = the row's 32px min-height + its 16px margin-bottom,
   all three values pinned, and the buttons are 32px like the row, so the pair
   sits flush on the row's box. right: 4px mirrors the row's own side padding. */
.hfse-rdp-nav {
  display: flex;
  align-items: center;
  gap: 4px;
  position: absolute;
  top: -48px;
  right: 4px;
  left: auto;
  padding: 0;
}
/* Button treatment from .hrtk-sbp-datepicker__nav-btn (searchbar-pro.css:
   1843-1871): 32px circle, hairline border, muted disabled state — the
   disabled rule matters here because react-day-picker disables the previous
   arrow at the startMonth boundary. */
.hfse-rdp-nav-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  background: transparent;
  border: 1px solid var(--dp-nav-border);
  border-radius: 50%;
  cursor: pointer;
  color: var(--hfse-foreground, #222222);
  transition: background 0.12s ease, color 0.12s ease;
  padding: 0;
}
.hfse-rdp-nav-btn:hover {
  background: var(--dp-cell-hover-bg);
}
.hfse-rdp-nav-btn:disabled {
  color: var(--dp-nav-disabled-color);
  border-color: var(--dp-nav-disabled-border);
  cursor: not-allowed;
  background: transparent;
  pointer-events: none;
}
.hfse-rdp-weekdays {
  display: flex;
}
.hfse-rdp-weekday {
  flex: 1;
  text-align: center;
  /* 11px/600, the module's weekday metrics (toolkit css:2043-2047). No
     border: the module draws no rule under the weekday row (#924 polish —
     the widget's underline was the visible seam in the 8/7 side-by-side). */
  font-size: 11px;
  font-weight: 600;
  /* Own token, not --hfse-muted-foreground: the muted token measured 2.85:1
     on the light dialog (3.89:1 dark) — under WCAG AA for the only label
     telling columns apart. Light value on the .hfse-rdp token block, dark
     override in useExplorerCss. (8/6 a11y fix, Eli decision; the toolkit
     module ships the same gap — this COLOR deliberately diverges.) */
  color: var(--dp-weekday-color);
  padding: 8px 0;
}
/* Results header, pro variant (#924 / SBP-7, toolkit css:2433-2445): count
   heading left, controls right, min-height pinned to the select so the count
   popping in cannot jump the row. */
.hfse-sbp-results-header {
  display: flex;
  /* wrap + the min-width/max-width guards below: at a 390px viewport the rigid
     row put the controls 132px past the right edge of the screen — the sort
     select rendered half off-viewport and the Start Over label stacked
     letter-over-letter. Caught by the parity harness overflow tripwire on its
     first armed run (2026-08-08); wrap never engages while space suffices, so
     desktop is untouched. */
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 16px;
  min-height: 38px;
}
.hfse-sbp-results-count {
  font-size: 16px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--hfse-foreground, #222);
}
.hfse-sbp-results-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  min-width: 0;
  /* Keeps the controls on the right when the count line is toggled off
     (#1102) — a lone flex child under space-between would sit left. No-op
     while the count renders. */
  margin-left: auto;
}
.hfse-sbp-results-controls .hk-button {
  white-space: nowrap;
}
/* Sort pill — module "Sort by: Featured ▾" (r8 #937; searchbar-pro.css:
   2478-2523, js:4568-4635): the label wrapper IS the control chrome, the
   select inside is borderless with a hand-drawn chevron so the whole thing
   reads as one intentional piece, and the focus ring rides :focus-within on
   the wrapper (the select's own outline is off below). Shared by both
   SecondaryRow variants — the pill has no popover/sheet dependency. */
.hfse-sbp-results-sort {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  max-width: 100%;
  padding: 8px 14px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  border-radius: var(--hfse-sbp-shape-max, 999px);
  background: var(--hfse-card-bg, #fff);
  cursor: pointer;
  transition: border-color 0.12s ease;
}
.hfse-sbp-results-sort:hover {
  border-color: rgba(0, 0, 0, 0.38);
}
.hfse-sbp-results-sort:focus-within {
  border-color: var(--hfse-sbp-accent, #ff385c);
  box-shadow: 0 0 0 1px var(--hfse-sbp-accent, #ff385c);
}
.hfse-sbp-results-sort-prefix {
  color: var(--hfse-muted-foreground, #6b7280);
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  white-space: nowrap;
}
.hfse-sbp-results-sort select {
  appearance: none;
  -webkit-appearance: none;
  min-width: 0;
  max-width: 240px;
  border: 0;
  outline: none;
  /* Hand-drawn chevron (module css:2517) — the native select arrow can't be
     styled. Stroke is a literal because tokens can't reach a data URI. */
  background: transparent url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23111827' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat right center / 10px 6px;
  /* The 18px right pad is the chevron zone; SORT_CHEVRON_PAD_PX in
     SortDropdown.tsx restates it for the selected-option width pin. */
  padding: 0 18px 0 0;
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  font-weight: 600;
  color: var(--hfse-foreground, #111827);
  cursor: pointer;
}
/* Datepicker footer parity (#924, toolkit css:2245-2287): sentence-case
   underlined "Clear dates" left, accent PILL primary right (8px 20px,
   shape-token radius). Scoped to the date dialog — the hk-button base is
   uppercase/4px-radius and the other popovers keep it; the widget's primary
   KEEPS its Apply label and stage-until-Apply semantics (Eli-confirmed 8/5
   divergence) — only the button's dress matches the module's Close. */
.hfse-form-date-options .hfse-modal-reset-button {
  text-transform: none;
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  color: var(--hfse-foreground, #111827);
}
.hfse-form-date-options .hfse-modal-next-button {
  text-transform: none;
  font-size: 13px;
  font-weight: 600;
  padding: 8px 20px;
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
}
.hfse-rdp-week {
  display: flex;
}
.hfse-rdp-day {
  flex: 1;
  /* Cancels the flex item's automatic minimum size: `auto` floors the cell at
     the button's own min-content width, which is what let 7 rigid 44px
     circles push the row past its pane (#1360). */
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.hfse-rdp-day-btn {
  /* 44px until the cell is narrower than that, then the cell's full 1/7 track
     (#1360). aspect-ratio is load-bearing, not decoration: a shrunk width
     against the old fixed height would paint the border-radius: 50% below as
     a 36 × 44 ELLIPSE. */
  width: min(100%, var(--rdp-cell));
  height: auto;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: none;
  border-radius: 50%;
  cursor: pointer;
  /* 14px/600: the module day numerals' measured metrics (searchbar-pro.css:
     2087 + live computed 2026-08-07 — every module day renders 600, and the
     weight gap was the visible "smaller font" in Eli's r3 strip note). */
  font-size: 14px;
  font-weight: 600;
  color: var(--hfse-foreground, #333);
  transition: background 0.15s;
}
.hfse-rdp-day-btn:hover {
  background: var(--hfse-input-bg, #f0f0f0);
}
/* Today */
/* Today is deliberately UNSTYLED (#924): the module declares --dp-today-dot
   but never applies it — today reads as an ordinary cell in the reference,
   and the widget's accent-blue today was the loudest delta in the 8/7
   side-by-side. The .hfse-rdp-today class stays on the cell for tests and
   future use. */
/* Endpoints — solid #222 circle with white numerals (toolkit css:2090-2098).
   The circle lives on the button; the ribbon fill lives on the cell, so the
   cell keeps its full-width hit area. */
.hfse-rdp-range-start .hfse-rdp-day-btn,
.hfse-rdp-range-end .hfse-rdp-day-btn {
  background: var(--dp-endpoint-bg);
  color: var(--dp-endpoint-color);
  font-weight: 600;
}
.hfse-rdp-range-start .hfse-rdp-day-btn:hover,
.hfse-rdp-range-end .hfse-rdp-day-btn:hover {
  background: var(--dp-endpoint-bg);
}
/* A lone applied check-in re-opens the picker as {from, to: undefined}, and
   react-day-picker only sets range-start/range-end when BOTH endpoints
   exist — the seed surfaced as bare `selected` and painted NOTHING, so the
   visitor completing a check-out could not see which check-in they were
   completing (2026-08-05 audit, confirmed live). Same endpoint circle. The
   :not guards keep full-range selections on the dedicated rules above. */
.hfse-rdp-selected:not(.hfse-rdp-range-start):not(.hfse-rdp-range-end):not(.hfse-rdp-range-middle) .hfse-rdp-day-btn,
.hfse-rdp-selected:not(.hfse-rdp-range-start):not(.hfse-rdp-range-end):not(.hfse-rdp-range-middle) .hfse-rdp-day-btn:hover {
  background: var(--dp-endpoint-bg);
  color: var(--dp-endpoint-color);
  font-weight: 600;
}
/* In-range — flat neutral fill, square, rounded only at week edges
   (toolkit css:2106-2118). */
.hfse-rdp-range-middle {
  background: var(--dp-range-bg);
  border-radius: 0;
}
.hfse-rdp-range-middle .hfse-rdp-day-btn {
  border-radius: 0;
  color: var(--dp-range-color);
}
.hfse-rdp-week > .hfse-rdp-range-middle:first-child,
.hfse-rdp-week > .hfse-rdp-hover-range:first-child {
  border-radius: var(--dp-cell-radius) 0 0 var(--dp-cell-radius);
}
.hfse-rdp-week > .hfse-rdp-range-middle:last-child,
.hfse-rdp-week > .hfse-rdp-hover-range:last-child {
  border-radius: 0 var(--dp-cell-radius) var(--dp-cell-radius) 0;
}
/* Hover-range preview while picking check-out (toolkit css:2120-2131). */
.hfse-rdp-hover-range {
  background: var(--dp-hover-range-bg);
  border-radius: 0;
}
/* ---- Declared AFTER in-range/hover-range on purpose --------------------
   These overlays have equal specificity to the two blocks above, so source
   order is what makes them win the tie. The toolkit carries the same warning
   at searchbar-pro.debug.css:2133-2136 — do not hoist them. */
/* Half-fills bridging an endpoint circle to the adjacent ribbon. These are
   driven by explicit modifiers rather than by range-start/range-end, because
   an endpoint only earns a bridge when there is a ribbon on that side: a
   lone check-in, and a same-day range, must stay a bare circle. The toolkit
   makes the same distinction with --range-after / --range-before. */
.hfse-rdp-range-after {
  background: linear-gradient(to right, transparent 50%, var(--dp-range-bg) 50%);
}
.hfse-rdp-range-before,
.hfse-rdp-checkout-preview {
  background: linear-gradient(to right, var(--dp-range-bg) 50%, transparent 50%);
}
.hfse-rdp-checkout-preview .hfse-rdp-day-btn {
  background: var(--dp-endpoint-bg);
  color: var(--dp-endpoint-color);
}
/* Month-boundary ribbon fades — the two panes are separated by a gap, so a
   span crossing the boundary fades out instead of ending abruptly
   (toolkit css:2143-2151). */
.hfse-rdp-range-fade-left {
  background: linear-gradient(to right, transparent, var(--dp-range-bg));
}
.hfse-rdp-range-fade-right {
  background: linear-gradient(to right, var(--dp-range-bg), transparent);
}
/* Outside days are not rendered (#618) — crossover dates of the adjacent
   month stay blank and a selection only ever paints once. The td still
   carries range modifiers, so strip the td-level fill on the empty cells. */
.hfse-rdp-day[data-hidden="true"] {
  background: none;
}
/* Disabled days. Text colored by the BORDER token measured 1.26:1 on the
   light dialog (1.79:1 dark) — effectively invisible numerals. The token's
   light value (4.61:1 on white) still reads as dimmed next to full-strength
   text; cursor + the hover no-op below keep the disabled affordance. Light
   value on the .hfse-rdp token block, dark override in useExplorerCss.
   (8/6 a11y fix, Eli decision; the toolkit module ships the same gap.) */
.hfse-rdp-disabled .hfse-rdp-day-btn {
  color: var(--dp-disabled-color);
  cursor: not-allowed;
}
.hfse-rdp-disabled .hfse-rdp-day-btn:hover {
  background: none;
}
/* #1338/#1339: booking-window / advance-notice / min-stay gated days.
   React-day-picker's own `disabled` modifier already covers these (see the
   DateFilter `disabled` array), so this rule only needs to look distinct
   from a plain past day; same token, same not-allowed affordance as the
   rule above. Toolkit parity: hrtk-sbp-datepicker__day--blocked. */
.hfse-rdp-blocked .hfse-rdp-day-btn {
  color: var(--dp-disabled-color);
  cursor: not-allowed;
}
.hfse-rdp-blocked .hfse-rdp-day-btn:hover {
  background: none;
}
/* --- Narrow viewport: 6 months in one scrolling column -------------------
   Toolkit parity (searchbar-pro.js:823 picks 6 vs 2; CSS 3314-3339 stacks
   them). The month COUNT is a React prop — CSS alone cannot change it — so
   this block only handles the layout half. */
.hfse-rdp-narrow .hfse-rdp-months {
  flex-direction: column;
  flex-wrap: nowrap;
  gap: 28px;
  /* 38vh is the reference value (searchbar-pro.debug.css:3318), not a guess —
     the column has to leave the sheet's other stages reachable below it. */
  max-height: 38vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  /* r8 #937: NO visible rail. r7 ported the module's thin dark scrollbar
     here; Eli's local pass overrode that parity point — the scroll stays,
     the rail goes (and with it the 4px rail-lane padding). */
  scrollbar-width: none;
}
.hfse-rdp-narrow .hfse-rdp-months::-webkit-scrollbar {
  display: none;
}
.hfse-rdp-narrow .hfse-rdp-month {
  width: 100%;
  min-width: 0;
}
/* Stacked months are scrolled, not paged — the nav arrows would only be able to
   move the first one, so they come off (toolkit css:3305-3308). Six render at a
   time and DateFilter appends the next six as the column is scrolled, so the
   whole 24-month horizon stays reachable without them. */
.hfse-rdp-narrow .hfse-rdp-nav {
  display: none;
}
/* --- Month navigation slide ---------------------------------------------
   Toolkit `animateMonthSlide` (searchbar-pro.js:516-611): 200ms
   cubic-bezier(.4,0,.2,1) translateX by the grid's measured PIXEL width
   (calendarsEl.offsetWidth), with the weekday header rows counter-transformed
   by the same distance so they read as stationary while the grid travels.
   DateFilter writes that measurement to --hfse-rdp-slide-px right before
   navigation; pixels matter because a percentage counter-transform resolves
   against the CHILD row's own width and can never cancel the parent's move.
   Transform-only, no opacity — the reference does not fade.

   DIVERGENCE, deliberate: the toolkit clones the outgoing grid and slides the
   two panes past each other. react-day-picker owns this subtree and re-renders
   it on navigation, so the outgoing month is gone before an animation could
   start. This is the incoming half only — the new grid slides in from the
   direction of travel. Same duration, easing, and travel; one pane, not two. */
@keyframes hfse-rdp-slide-in-next {
  from { transform: translateX(var(--hfse-rdp-slide-px, 100%)); }
  to   { transform: translateX(0); }
}
@keyframes hfse-rdp-slide-in-prev {
  from { transform: translateX(calc(-1 * var(--hfse-rdp-slide-px, 100%))); }
  to   { transform: translateX(0); }
}
@keyframes hfse-rdp-weekday-hold-next {
  from { transform: translateX(calc(-1 * var(--hfse-rdp-slide-px, 100%))); }
  to   { transform: translateX(0); }
}
@keyframes hfse-rdp-weekday-hold-prev {
  from { transform: translateX(var(--hfse-rdp-slide-px, 100%)); }
  to   { transform: translateX(0); }
}
/* The animation rides the MONTH PANES, not the months wrapper: RDP renders
   its nav INSIDE the wrapper, so animating the wrapper visibly drags the
   arrows along with the grid (codex fresh pass). The panes' weekday rows
   still counter-hold; the nav, a sibling of the panes, never moves.
   overflow: hidden for the slide's duration keeps the shifted pane from
   flashing a scrollbar — desktop only by construction (narrow hides the nav,
   so a slide can never start there). */
.hfse-rdp-slide-next,
.hfse-rdp-slide-prev {
  overflow: hidden;
}
.hfse-rdp-slide-next .hfse-rdp-month {
  animation: hfse-rdp-slide-in-next 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hfse-rdp-slide-prev .hfse-rdp-month {
  animation: hfse-rdp-slide-in-prev 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hfse-rdp-slide-next .hfse-rdp-weekdays {
  animation: hfse-rdp-weekday-hold-next 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.hfse-rdp-slide-prev .hfse-rdp-weekdays {
  animation: hfse-rdp-weekday-hold-prev 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
/* The toolkit returns from animateMonthSlide before cloning anything when
   reduced motion is requested; the React port has no clone to skip, so the
   equivalent is simply not running the animation. */
@media (prefers-reduced-motion: reduce) {
  .hfse-rdp-slide-next .hfse-rdp-month,
  .hfse-rdp-slide-prev .hfse-rdp-month,
  .hfse-rdp-slide-next .hfse-rdp-weekdays,
  .hfse-rdp-slide-prev .hfse-rdp-weekdays {
    animation: none !important;
  }
  .hfse-rdp-day-btn,
  .hfse-rdp-nav-btn {
    transition: none !important;
  }
}
/* ==========================================================================
   Flexible dates (#870 slice 6)
   --------------------------------------------------------------------------
   Ported from the toolkit's flex bridge inside the SBP picker
   (searchbar-pro.debug.css:3457-3654). Like the date range palette above, the
   flexible panel is deliberately quiet and only the SELECTED chip picks up the
   accent.

   THEMING: every painted surface reads a `--hfse-*` token with the reference's
   own literal as the fallback, the same pattern the rest of the `.hfse-sbp-*`
   family uses. Both mount points — the picker dialog (`.hr-dialog-content`) and
   the under-bar strip (`.hfse-explorer-container`) — are inside the scope
   `useExplorerCss` writes those tokens onto, so a dark palette reaches this
   panel instead of floating white furniture on a dark dialog. The literals are
   NOT dead: they are what renders wherever the token scope is absent. Do not
   mint `--hfse-flex-*` tokens here — dark comes solely from `useExplorerCss`
   swapping palettes into `--hfse-*`, and a second token family would install a
   divergent theming path this widget has no mechanism to keep in sync.
   ========================================================================== */
/* Exact / Flexible tab pair. Shrink-wrapped and centred rather than spanning
   the popover (reference comment, css:3461). */
.hfse-sbp-flex-toggle {
  display: flex;
  justify-content: center;
  gap: 4px;
  width: fit-content;
  max-width: 100%;
  margin: 4px auto 12px;
  padding: 4px;
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-input-bg, #f0f0f0);
}
.hfse-sbp-flex-mode {
  border: 0;
  background: transparent;
  padding: 7px 18px;
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--hfse-foreground, #444);
  cursor: pointer;
}
.hfse-sbp-flex-mode-active {
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #111);
  font-weight: 600;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}
.hfse-sbp-flex-panel {
  padding: 4px 8px 12px;
}
.hfse-sbp-flex-heading {
  font-size: 0.9rem;
  font-weight: 600;
  margin: 12px 0 8px;
  text-align: center;
}
.hfse-sbp-flex-stays {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 8px;
}
/* The month strip scrolls horizontally; its scrollbar is hidden in both
   engines so the chips read as a clean track. */
.hfse-sbp-flex-months {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 4px 2px;
  scrollbar-width: none;
}
.hfse-sbp-flex-months::-webkit-scrollbar {
  display: none;
}
.hfse-sbp-flex-chip {
  flex: 0 0 auto;
  padding: 9px 16px;
  border: 1px solid var(--hfse-border, #ddd);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  font-size: 0.85rem;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
/* Scoped off the active chip: at (0,2,0) this would otherwise beat
   `.hfse-sbp-flex-chip-active`'s (0,1,0) accent border and strip it under
   the cursor. `--hfse-muted-foreground` matches the token the pre-existing
   `.hfse-sbp-chip:hover` (quick-filter chips, css:2842) already uses for the
   same neutral hover border, so this follows dark instead of the old
   unthemed `#999` literal. */
.hfse-sbp-flex-chip:hover:not(.hfse-sbp-flex-chip-active) {
  border-color: var(--hfse-muted-foreground, #999);
}
.hfse-sbp-flex-chip-active {
  color: var(--hfse-sbp-accent, #ff385c);
  border-color: var(--hfse-sbp-accent, #ff385c);
  background: color-mix(in srgb, var(--hfse-sbp-accent, #ff385c) 7%, var(--hfse-card-bg, #fff));
  font-weight: 600;
}
/* In-panel suggested dates — secondary to the stay/month groups above: a
   divider sets it apart, the heading is smaller and muted, and its chips are
   lighter (reference css:3549-3592). */
.hfse-sbp-flex-suggested {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--hfse-border, #ececec);
}
.hfse-sbp-flex-suggested .hfse-sbp-flex-heading {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--hfse-muted-foreground, #8a8f98);
  margin: 0 0 8px;
}
.hfse-sbp-flex-suggested-track {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
}
.hfse-sbp-flex-suggested-track .hfse-sbp-flex-chip {
  padding: 6px 12px;
  font-size: 0.8125rem;
  border-color: var(--hfse-border, #e6e6e6);
  color: var(--hfse-foreground, #444);
}
.hfse-sbp-flex-suggested-track .hfse-sbp-flex-chip-active {
  border-color: var(--hfse-sbp-accent, #ff385c);
  color: var(--hfse-sbp-accent, #ff385c);
}
/* Alternative-dates strip under the bar (reference css:3598-3654). Centred to
   line up with the quick-filter chip row it sits above. */
.hfse-sbp-flex-alts {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin: 12px 0 2px;
}
/* The one flex element rendered OUTSIDE the dialog, on the host page's own
   background: on the dark defaults `#444` on `#1e1e1e` measured 1.71:1, a
   genuine AA failure. The token is what fixes it; the literal stays as the
   unthemed fallback. */
.hfse-sbp-flex-alts-heading {
  flex: 0 0 auto;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--hfse-foreground, #444);
}
.hfse-sbp-flex-alts-track {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  overflow-y: hidden;
  padding: 2px;
  scrollbar-width: none;
}
.hfse-sbp-flex-alts-track::-webkit-scrollbar {
  display: none;
}
.hfse-sbp-flex-alts-chip {
  flex: 0 0 auto;
  padding: 6px 12px;
  border: 1px solid var(--hfse-border, #e2e2e2);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #333);
  font-size: 0.8125rem;
  line-height: 1;
  cursor: pointer;
  white-space: nowrap;
  transition: border-color 0.15s ease;
}
/* Same specificity trap and same fix as `.hfse-sbp-flex-chip:hover` above:
   scoped off the active alt-dates chip, and reading the shared muted-
   foreground token instead of the unthemed `#999` literal. */
.hfse-sbp-flex-alts-chip:hover:not(.hfse-sbp-flex-alts-chip-active) {
  border-color: var(--hfse-muted-foreground, #999);
}
.hfse-sbp-flex-alts-chip-active {
  color: var(--hfse-sbp-accent, #ff385c);
  border-color: var(--hfse-sbp-accent, #ff385c);
  background: color-mix(in srgb, var(--hfse-sbp-accent, #ff385c) 7%, var(--hfse-card-bg, #fff));
  font-weight: 600;
}
/* ==========================================================================
   Additional Filters Modal Layout
   ========================================================================== */
.hfse-form-additional-filters-options.hr-dialog-content {
  max-width: 680px;
}
/* Modal header with icon + title */
.hk-modal-header-title {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Grid layout */
.hfse-af-grid {
  display: flex;
  gap: 0;
}
.hfse-af-col {
  padding: 0 20px;
  box-sizing: border-box;
  min-width: 0;
  overflow: hidden;
}
.hfse-af-col:first-child {
  padding-left: 0;
}
.hfse-af-col:last-child {
  padding-right: 0;
}
/* Grid with vertical divider */
.hfse-af-grid-divider > .hfse-af-col + .hfse-af-col {
  border-left: 1px solid var(--hfse-border, #e5e5e5);
}
/* Column widths */
.hfse-af-col-1-2 { flex: 0 0 50%; max-width: 50%; }
.hfse-af-col-1-3 { flex: 0 0 33.333%; max-width: 33.333%; }
.hfse-af-col-2-3 { flex: 0 0 66.667%; max-width: 66.667%; }
/* When a row's sibling column is hidden, the remaining one spans full width (#554) */
.hfse-af-col-full { flex: 0 0 100%; max-width: 100%; }
/* Section label */
.hfse-af-label {
  margin-bottom: 12px;
}
/* Section dividers */
.hfse-af-divider {
  border: none;
  border-top: 1px solid var(--hfse-border, #e5e5e5);
  margin: 20px 0;
}
.hfse-af-divider-thin {
  border: none;
  border-top: 1px solid var(--hfse-border, #e5e5e5);
  margin: 0 0 12px;
}
/* Search input with icon */
.hfse-af-search-input-wrap {
  position: relative;
}
.hfse-af-search-icon {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--hfse-muted-foreground, #999);
  pointer-events: none;
  display: flex;
  align-items: center;
}
.hfse-af-search-input {
  padding-left: 34px !important;
}
/* Room groups (bedrooms/bathrooms) */
.hfse-af-room-group {
  margin-bottom: 20px;
}
.hfse-af-room-group:last-child {
  margin-bottom: 0;
}
/* Checkbox grid: 2 columns on mobile, configurable from 640px up (#555) */
.hfse-af-checkbox-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px 16px;
}
@media screen and (min-width: 640px) {
  .hfse-af-checkbox-grid {
    grid-template-columns: repeat(var(--hfse-af-columns, 2), 1fr);
  }
}
.hfse-af-more-amenities {
  margin-top: 12px;
}
.hfse-af-checkbox-label {
  display: flex;
  align-items: center;
  gap: 0;
  cursor: pointer;
  font-size: 14px;
  line-height: 1.4;
}
/* Price Range Slider */
.hfse-price-slider {
  padding: 10px 10px;
}
.hfse-price-slider-track {
  position: relative;
  height: 4px;
  background: var(--hfse-border, #aaa);
  border-radius: 2px;
}
.hfse-price-slider-range {
  position: absolute;
  top: 0;
  height: 100%;
  background: var(--hfse-foreground, #000);
  border-radius: 2px;
}
.hfse-price-slider-handle {
  position: absolute;
  top: 50%;
  width: 20px;
  height: 20px;
  background: var(--hfse-foreground, #333);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  cursor: grab;
  touch-action: none;
  z-index: 1;
}
.hfse-price-slider-handle:active {
  cursor: grabbing;
}
/* Responsive: stack on mobile */
@media (max-width: 639px) {
  .hfse-af-grid {
    flex-direction: column;
  }
  .hfse-af-col {
    padding: 0;
    max-width: 100% !important;
    flex: 0 0 100% !important;
  }
  .hfse-af-grid-divider > .hfse-af-col + .hfse-af-col {
    border-left: none;
    border-top: 1px solid var(--hfse-border, #e5e5e5);
    padding-top: 16px;
    margin-top: 16px;
  }
  .hfse-form-additional-filters-options.hr-dialog-content {
    max-width: 100%;
  }
}
/* ----------------------------------------------------------------------------
 * Section heading (shared across content widgets)
 * Bold title on the left + horizontal divider line filling remaining width.
 * -------------------------------------------------------------------------- */
.hr-widget-section {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-bottom: 2rem;
  width: 100%;
}
.hr-widget-section-title {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--foreground);
  white-space: nowrap;
  flex-shrink: 0;
}
.hr-widget-section-line {
  flex: 1;
  height: 1px;
  background-color: currentColor;
  opacity: 0.18;
  display: block;
}
@media (max-width: 640px) {
  .hr-widget-section-title { font-size: 1.25rem; }
  .hr-widget-section { gap: 1rem; margin-bottom: 1.5rem; }
}
/* ---------- Sticky filter bar (WP plugin sticky_filter parity) ---------- */
/* LEGACY VARIANT ONLY (#1092): Searchbar Pro opts out via :not(.hfse-sbp) —
   its stickyFilter pins BAR-ONLY through the refine sticky anatomy (end of
   this file), so this whole-block pin with its opaque theme background (the
   284px grey slab Eli reported on the GAW demo) never applies to the pro
   bar, at any viewport. Module parity: SBP sticky is desktop-only and the
   mobile trigger never pins (searchbar-pro.js:4774-4776). */
.hfse-explorer-container.sticky-filter .hfse-filter-bar:not(.hfse-sbp) {
    position: sticky;
    top: 0;
    z-index: 500;
    background: var(--hfse-background, inherit);
}
/* Recommendations fallback (#436 §2.9) — shown under the no-results message */
.hfse-recommendations {
    margin-top: 24px;
    width: 100%;
}
.hfse-recommendations-heading {
    margin: 0 0 16px;
    text-align: center;
    color: var(--hfse-foreground, #333);
}
/* ==========================================================================
   Zero-results rescue (#1265) — toolkit flexible-search half (b)
   The empty-state box with Central-verified alternative windows (module
   .hrtk-fs-empty, flexible-search.css:438-493) and the adjusted-dates notice
   above a grid that has results (.hrtk-fs-adjusted-notice, :497-546). Paint
   reads --hfse-* tokens with the module's own literals as fallbacks; the
   "available" green is a --hfse-success token tinted against the card
   background, so a theme can retune it in one place.
   ========================================================================== */
.hfse-flex-rescue {
    /* Same grid trap as .hfse-no-items: span every column or the box sits in
       the first track. Border-box: the sheet sets it per rule, not globally,
       and 100% + 48px of padding would overflow a host without its own reset. */
    box-sizing: border-box;
    grid-column: 1 / -1;
    width: 100%;
    margin: 16px 0;
    padding: 32px 24px;
    text-align: center;
    border: 1px solid var(--hfse-border, #e5e7eb);
    border-radius: 12px;
    background: var(--hfse-card-bg, #f9fafb);
    color: var(--hfse-foreground, #111827);
}
.hfse-flex-rescue-title {
    margin: 0 0 6px;
    font-size: 18px;
    font-weight: 600;
    color: var(--hfse-foreground, #111827);
}
.hfse-flex-rescue-subtitle {
    margin: 0 0 16px;
    font-size: 14px;
    /* Foreground, not the muted token: the theme's muted default (#999999,
       card-colors.ts) measures 2.85:1 on white — under WCAG AA for the one
       line that tells the visitor what the chips mean. Same call as the
       weekday label above (explorer.css "Own token" note). */
    color: var(--hfse-foreground, #111827);
}
.hfse-flex-rescue-subtitle:last-child {
    margin-bottom: 0;
}
.hfse-flex-rescue-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 8px;
}
.hfse-flex-rescue-chip {
    padding: 8px 16px;
    border: 1px solid var(--hfse-border, #d1d5db);
    border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
    background: var(--hfse-card-bg, #fff);
    color: var(--hfse-foreground, inherit);
    font-size: 13px;
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
    transition: border-color 0.15s ease, background 0.15s ease;
}
.hfse-flex-rescue-chip:hover {
    border-color: var(--hfse-sbp-accent, #2c5282);
    background: color-mix(in srgb, var(--hfse-sbp-accent, #2c5282) 7%, var(--hfse-card-bg, #fff));
}
/* Availability-checked chip: a window Central confirmed bookable (module
   .is-available). The check is CSS-generated; the button's aria-label carries
   the same fact for assistive tech. */
.hfse-flex-rescue-chip-available {
    /* Plain-token fallback first: a browser without color-mix() keeps a
       visible confirmed border instead of dropping the declaration. */
    border-color: var(--hfse-success, #2f7c3f);
    border-color: color-mix(in srgb, var(--hfse-success, #2f7c3f) 50%, var(--hfse-card-bg, #fff));
}
.hfse-flex-rescue-chip-available::before {
    content: "\2713\00a0";
    color: var(--hfse-success, #2f7c3f);
    font-weight: 600;
}
/* "Dates adjusted" notice above the results grid after a rescue-chip pivot. */
.hfse-flex-adjusted {
    box-sizing: border-box;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin: 0 0 16px;
    padding: 14px 16px;
    /* Plain-token fallbacks precede each color-mix() (no-support browsers
       keep a bordered card instead of an unbordered one). */
    border: 1px solid var(--hfse-border, #e5e7eb);
    border: 1px solid color-mix(in srgb, var(--hfse-success, #2f7c3f) 35%, var(--hfse-card-bg, #fff));
    border-radius: 12px;
    background: var(--hfse-card-bg, #fff);
    background: color-mix(in srgb, var(--hfse-success, #2f7c3f) 8%, var(--hfse-card-bg, #fff));
    color: var(--hfse-foreground, #1f2937);
}
.hfse-flex-adjusted-main {
    flex: 1 1 auto;
    min-width: 0;
}
.hfse-flex-adjusted-text {
    margin: 0;
    font-size: 14px;
    color: var(--hfse-foreground, #1f2937);
}
.hfse-flex-adjusted-back {
    margin-top: 6px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--hfse-sbp-accent, #2c5282);
    font-size: 13px;
    text-decoration: underline;
    cursor: pointer;
}
.hfse-flex-adjusted-dismiss {
    flex: 0 0 auto;
    padding: 2px 6px;
    border: 0;
    background: none;
    color: var(--hfse-foreground, #111827);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    opacity: 0.75;
}
.hfse-flex-adjusted-dismiss:hover {
    opacity: 1;
}
.hfse-flex-adjusted-alts {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
}
.hfse-flex-adjusted-alts-heading {
    font-size: 13px;
    /* Foreground for the same AA reason as .hfse-flex-rescue-subtitle. */
    color: var(--hfse-foreground, #1f2937);
}
/* Build marker: harmless custom property that survives minification. Bump the
   number to force a content-hash change (first bump exercises S5 retention). */
.hfse-explorer-container {
    --hr-asset-generation: 1;
}
/* ==========================================================================
   "Search this area" pill (toolkit map-controls port, #852)
   ========================================================================== */
.hfse-map-search-area-btn {
  position: absolute;
  /* Directly under the search-as-move pill (module: top 60px) — it only ever
     shows while that checkbox is visible and unchecked. */
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1000001;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 16px;
  border: none;
  border-radius: 999px;
  background: var(--hfse-map-control-bg, var(--hfse-card-bg, #fff));
  color: var(--hfse-map-control-color, var(--hfse-foreground, #222));
  font-size: 13px;
  font-weight: 500;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 2px 8px rgba(0, 0, 0, 0.18);
  transition: box-shadow 0.15s ease;
}
.hfse-map-search-area-btn svg {
  display: block;
  width: 14px;
  height: 14px;
}
.hfse-map-search-area-btn:hover {
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 4px 12px rgba(0, 0, 0, 0.24);
}
/* Leaflet attribution inside the widget shadow root (#852) */
.hfse .leaflet-control-attribution {
  font-size: 10px;
  padding: 1px 6px;
  background: rgba(255, 255, 255, 0.75);
  color: #333;
}
.hfse .leaflet-control-attribution a {
  color: inherit;
  text-decoration: underline;
}
.hfse.dark .leaflet-control-attribution {
  background: rgba(0, 0, 0, 0.6);
  color: #ddd;
}
/* Official Mapbox logo (required unaltered by Mapbox ToS alongside text
   attribution, #858). The data URI is the untouched asset mapbox-gl ships in
   mapbox-gl.css (a.mapboxgl-ctrl-logo); the SVG halos itself, so one variant
   covers light and dark tiles. */
.hfse-mapbox-logo {
  position: absolute;
  bottom: 4px;
  left: 8px;
  z-index: 1000001;
  display: block;
  width: 88px;
  height: 23px;
  overflow: hidden;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' fill-rule='evenodd' viewBox='0 0 88 23'%3E%3Cdefs%3E%3Cpath id='logo' d='M11.5 2.25c5.105 0 9.25 4.145 9.25 9.25s-4.145 9.25-9.25 9.25-9.25-4.145-9.25-9.25 4.145-9.25 9.25-9.25zM6.997 15.983c-.051-.338-.828-5.802 2.233-8.873a4.395 4.395 0 013.13-1.28c1.27 0 2.49.51 3.39 1.42.91.9 1.42 2.12 1.42 3.39 0 1.18-.449 2.301-1.28 3.13C12.72 16.93 7 16 7 16l-.003-.017zM15.3 10.5l-2 .8-.8 2-.8-2-2-.8 2-.8.8-2 .8 2 2 .8z'/%3E%3Cpath id='text' d='M50.63 8c.13 0 .23.1.23.23V9c.7-.76 1.7-1.18 2.73-1.18 2.17 0 3.95 1.85 3.95 4.17s-1.77 4.19-3.94 4.19c-1.04 0-2.03-.43-2.74-1.18v3.77c0 .13-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V8.23c0-.12.1-.23.23-.23h1.4zm-3.86.01c.01 0 .01 0 .01-.01.13 0 .22.1.22.22v7.55c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V15c-.7.76-1.69 1.19-2.73 1.19-2.17 0-3.94-1.87-3.94-4.19 0-2.32 1.77-4.19 3.94-4.19 1.03 0 2.02.43 2.73 1.18v-.75c0-.12.1-.23.23-.23h1.4zm26.375-.19a4.24 4.24 0 00-4.16 3.29c-.13.59-.13 1.19 0 1.77a4.233 4.233 0 004.17 3.3c2.35 0 4.26-1.87 4.26-4.19 0-2.32-1.9-4.17-4.27-4.17zM60.63 5c.13 0 .23.1.23.23v3.76c.7-.76 1.7-1.18 2.73-1.18 1.88 0 3.45 1.4 3.84 3.28.13.59.13 1.2 0 1.8-.39 1.88-1.96 3.29-3.84 3.29-1.03 0-2.02-.43-2.73-1.18v.77c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V5.23c0-.12.1-.23.23-.23h1.4zm-34 11h-1.4c-.13 0-.23-.11-.23-.23V8.22c.01-.13.1-.22.23-.22h1.4c.13 0 .22.11.23.22v.68c.5-.68 1.3-1.09 2.16-1.1h.03c1.09 0 2.09.6 2.6 1.55.45-.95 1.4-1.55 2.44-1.56 1.62 0 2.93 1.25 2.9 2.78l.03 5.2c0 .13-.1.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.8 0-1.46.7-1.59 1.62l.01 4.68c0 .13-.11.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.85 0-1.54.79-1.6 1.8v4.5c0 .13-.1.23-.23.23zm53.615 0h-1.61c-.04 0-.08-.01-.12-.03-.09-.06-.13-.19-.06-.28l2.43-3.71-2.39-3.65a.213.213 0 01-.03-.12c0-.12.09-.21.21-.21h1.61c.13 0 .24.06.3.17l1.41 2.37 1.4-2.37a.34.34 0 01.3-.17h1.6c.04 0 .08.01.12.03.09.06.13.19.06.28l-2.37 3.65 2.43 3.7c0 .05.01.09.01.13 0 .12-.09.21-.21.21h-1.61c-.13 0-.24-.06-.3-.17l-1.44-2.42-1.44 2.42a.34.34 0 01-.3.17zm-7.12-1.49c-1.33 0-2.42-1.12-2.42-2.51 0-1.39 1.08-2.52 2.42-2.52 1.33 0 2.42 1.12 2.42 2.51 0 1.39-1.08 2.51-2.42 2.52zm-19.865 0c-1.32 0-2.39-1.11-2.42-2.48v-.07c.02-1.38 1.09-2.49 2.4-2.49 1.32 0 2.41 1.12 2.41 2.51 0 1.39-1.07 2.52-2.39 2.53zm-8.11-2.48c-.01 1.37-1.09 2.47-2.41 2.47s-2.42-1.12-2.42-2.51c0-1.39 1.08-2.52 2.4-2.52 1.33 0 2.39 1.11 2.41 2.48l.02.08zm18.12 2.47c-1.32 0-2.39-1.11-2.41-2.48v-.06c.02-1.38 1.09-2.48 2.41-2.48s2.42 1.12 2.42 2.51c0 1.39-1.09 2.51-2.42 2.51z'/%3E%3C/defs%3E%3Cmask id='clip'%3E%3Crect x='0' y='0' width='100%25' height='100%25' fill='white'/%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/mask%3E%3Cg id='outline' opacity='0.3' stroke='%23000' stroke-width='3'%3E%3Ccircle mask='url(%23clip)' cx='11.5' cy='11.5' r='9.25'/%3E%3Cuse xlink:href='%23text' mask='url(%23clip)'/%3E%3C/g%3E%3Cg id='fill' opacity='0.9' fill='%23fff'%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/g%3E%3C/svg%3E");
  background-repeat: no-repeat;
  cursor: pointer;
}
/* ==========================================================================
   Searchbar Pro variant (#853 — toolkit SBP port)
   Tokens are threaded by buildSearchbarCss (accent trio + shape clamp);
   every radius is written as min(<literal>, var(--hfse-sbp-shape-max, 999px))
   so one token clamps the bar, buttons, chips, and popovers uniformly
   (pure circles stay circles in all three shapes). The functional
   mobile/desktop swap is 932/933px — the toolkit's REAL breakpoint.
   ========================================================================== */
.hfse-sbp {
  position: relative;
  isolation: isolate; /* keeps the scrim ::before (z-index:-1) inside */
  /* Lift the whole bar subtree above later sibling sections. The WHERE
     listbox's z-index: 9999 only competes INSIDE this isolated context;
     without a z-index here the DOM-later property grid (positioned cards
     and their internals) paints over anything that escapes the bar's
     bounds. Port of the toolkit host rule (searchbar-pro.debug.css
     .hrtk-sbp-search-bar-host, v3.124.3). */
  z-index: 20;
}
/* Spring easing token (#870 motion parity). Verbatim port of the toolkit's
   `--hrtk-sbp-spring` (searchbar-pro.debug.css:216-219): a linear() curve
   approximating a damped spring. Declared here rather than in
   buildSearchbarCss because it never varies by config; it is mirrored onto
   the portaled mobile sheet selector because that node lives OUTSIDE
   .hfse-sbp's variable scope.

   The base value is `ease` and linear() arrives only via @supports: a custom
   property is syntax-valid with ANY value, so on a browser without linear()
   an unconditional declaration would not fall back — it would make every
   consuming transition invalid and kill it entirely (codex r1). */
/* .hfse-elevated-scope (#1259): the sticky shells pinned through the body
   portal and the Where listbox portal have no .hfse-sbp ancestor; without the
   scope on both spring blocks their transitions fell back to `ease`. Tokens
   only — the scope class stays layout-free (explorer-elevated-token-scope). */
.hfse-sbp,
.hr-dialog-content.hfse-sbp-mobile-sheet,
.hfse-elevated-scope {
  --hfse-sbp-spring: ease;
}
@supports (transition-timing-function: linear(0, 1)) {
  .hfse-sbp,
  .hr-dialog-content.hfse-sbp-mobile-sheet,
  .hfse-elevated-scope {
    --hfse-sbp-spring: linear(
      0, 0.186 7.7%, 0.466 15.5%, 0.682 23.3%, 0.823 31%,
      0.905 38.8%, 0.951 46.5%, 0.976 54.3%, 0.99 62%, 0.996 69.7%, 1
    );
  }
}
/* Desktop pill bar */
.hfse-sbp-bar {
  position: relative; /* containing block for the sliding indicator pills */
  display: flex;
  align-items: stretch;
  /* Hero width. The toolkit hardcodes 850px (searchbar-pro.css:241-245); the
     widget reads it from a token so the settings lane can expose it without a
     second editor in this file (#870 QA item 7). */
  max-width: var(--hfse-sbp-max-width, 850px);
  /* SBP-1 (#922): explicit width, exactly the module's (css:243). Without it
     the bar sits in a column flexbox where `margin: 0 auto` cancels the
     stretch and shrink-wraps it to content — so the submit button's 250ms
     morph re-sized the OUTER bar (measured 669→805px) instead of only the
     internal field split. */
  width: 100%;
  margin: 0 auto;
  padding: 6px;
  gap: 6px;
  box-sizing: border-box;
  background-color: var(--hfse-card-bg, #fff);
  border: 1px solid var(--hfse-border, #e5e5e5);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.12);
  transition:
    background-color 300ms var(--hfse-sbp-spring, ease),
    box-shadow 300ms var(--hfse-sbp-spring, ease);
}
.hfse-sbp-bar:focus-within {
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.18);
}
/* Active-state bar darkens to the inactive-pill color, so inactive fields
   dissolve into the bar surface and only the white sliding active pill reads
   as a distinct shape (toolkit css:262-268). Gated on -indicators like the
   field-transparency rules below — without the pills mounted, the fields
   still paint their own backgrounds and a darkened bar would just dim them. */
.hfse-sbp-bar-indicators.hfse-sbp-bar-has-active {
  background-color: var(--hfse-input-bg, #ebebeb);
}
.hfse-sbp-bar-slot {
  display: contents;
}
.hfse-sbp-divider {
  align-self: center;
  width: 1px;
  height: 32px;
  flex: 0 0 auto;
  background-color: var(--hfse-border, #e5e5e5);
  opacity: 1;
  pointer-events: none;
  transition: opacity 180ms var(--hfse-sbp-spring, ease);
}
/* Every divider hides while a field is open — the active pill and bar
   darkening carry the structure, lines would compete
   (toolkit: searchbar-pro.debug.css:431-433). */
.hfse-sbp-bar-has-active .hfse-sbp-divider {
  opacity: 0;
}
/* Dividers flanking the HOVERED field hide, but only while nothing is open
   (toolkit: searchbar-pro.debug.css:423-427). The toolkit matches them with
   adjacent-sibling selectors on a flat bar; the widget wraps each field in a
   `display: contents` slot span, so the same pair is expressed as
   "the slot holding the hovered field" + "the slot after it". */
.hfse-sbp-bar:not(.hfse-sbp-bar-has-active) .hfse-sbp-bar-slot:has(.hfse-sbp-field:hover, .hfse-sbp-field-btn:hover) > .hfse-sbp-divider,
.hfse-sbp-bar:not(.hfse-sbp-bar-has-active) .hfse-sbp-bar-slot:has(.hfse-sbp-field:hover, .hfse-sbp-field-btn:hover) + .hfse-sbp-bar-slot > .hfse-sbp-divider {
  opacity: 0;
}
/* Fields: label line + value line. Idle transparent, hover dim, open white
   pill with the two-layer active shadow. */
.hfse-sbp-field {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* `auto` basis, not 0: the fields must re-flex around the submit button as
     it morphs 52px to pill, and a 0 basis distributes the reclaimed space
     evenly instead of letting each field keep its content width first
     (toolkit .hrtk-sbp-search-bar__field is flex 1 1 auto, css:276-300).
     There is no width rule keyed to the active field anywhere in the toolkit —
     "fields resize on click" (Eli QA 2026-08-05 item 6) is entirely this
     basis plus the submit widen. */
  flex: 1 1 auto;
  min-width: 0;
  min-height: 52px;
  padding: 8px 16px 8px 20px;
  gap: 2px;
  border: none;
  text-align: left;
  background-color: transparent;
  color: var(--hfse-foreground, #222);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  cursor: pointer;
  z-index: 1; /* field text sits above the sliding pills (z-index: 0) */
  /* flex-grow/basis/min-width ride the same spring as the surface layers so
     the active-field widen (#922) animates instead of snapping; the sliding
     pills track the continuous resize because the bar's ResizeObserver snaps
     them each frame (toolkit css:293-299 + searchbar-pro.js:2406-2423). */
  transition:
    background-color 300ms var(--hfse-sbp-spring, ease),
    box-shadow 300ms var(--hfse-sbp-spring, ease),
    flex-grow 300ms var(--hfse-sbp-spring, ease),
    flex-basis 300ms var(--hfse-sbp-spring, ease),
    min-width 300ms var(--hfse-sbp-spring, ease);
}
/* Per-field basis (toolkit css:322-331). Who and What are content-shaped
   rather than equal thirds, so the widen reclaims space from Where/When
   first — the same redistribution the reference produces. */
.hfse-sbp-guests-field {
  flex: 0 1 170px;
  min-width: 140px;
}
.hfse-sbp-filters-field {
  flex: 0 1 200px;
  min-width: 160px;
}
/* Promoted BEDROOMS segment (#922, toolkit #461 + css:358-366): content-stable
   like Who/What — fixed-ish basis so stepping the value cannot re-flex the
   bar. The segment only renders when searchbar.barPromotedFilter="bedrooms",
   so nothing here touches the default 4-field layout. */
.hfse-sbp-bedrooms-field {
  flex: 0 1 150px;
  min-width: 118px;
}
/* Mid-desktop 5-field squeeze (toolkit css:380-390): Bedrooms and What both
   give some basis back so five fields + the CTA fit 933-1280px. The module
   uses `--bedrooms ~ --what` on its flat bar; the widget's fields sit inside
   display:contents slots, so the same pair reads as "the slot after the
   bedrooms slot". `:where()` keeps this at (0,3,0) so the active-state rules
   below outrank it exactly as the module's three-class selectors do. */
@media (min-width: 933px) and (max-width: 1280px) {
  .hfse-sbp-bedrooms-field {
    flex-basis: 128px;
    min-width: 104px;
  }
  .hfse-sbp-bar-slot:where(:has(.hfse-sbp-bedrooms-field)) ~ .hfse-sbp-bar-slot .hfse-sbp-filters-field {
    flex-basis: 170px;
    min-width: 140px;
  }
}
/* v3.181 port (#922 / SBP-4): the active field widens at its neighbors'
   expense. Two levers, exactly the module's (toolkit css:414-441): (1) the
   active field's claim on leftover space jumps to 2.4 (vs 1 for the
   auto-basis growers, 0 for the content-stable fields) plus a hard min-width
   floor — without the floor the submit button's widen could squeeze an
   active When down to a truncated label; (2) the content-stable fields
   (Who / What / Bedrooms) hand back part of their fixed basis while
   INACTIVE — their flex-grow stays 0, so the freed space flows
   deterministically to the active field. Animated by the flex entries in the
   field's base transition; the pills track via the bar's ResizeObserver.
   The give-back selectors carry `.hfse-sbp-field-btn` purely for specificity
   (0,4,0): they must outrank the mid-desktop media overrides above, the
   same relation the module's three-class selectors have to its media block.
   The active rule sits LAST at (0,3,0) so its min-width beats the media
   rule's on the open field itself (source order breaks the tie). */
.hfse-sbp-bar-has-active .hfse-sbp-guests-field.hfse-sbp-field-btn:not([data-state="open"]) {
  flex-basis: 132px;
  min-width: 112px;
}
.hfse-sbp-bar-has-active .hfse-sbp-filters-field.hfse-sbp-field-btn:not([data-state="open"]) {
  flex-basis: 156px;
  min-width: 124px;
}
.hfse-sbp-bar-has-active .hfse-sbp-bedrooms-field.hfse-sbp-field-btn:not([data-state="open"]) {
  flex-basis: 112px;
  min-width: 96px;
}
.hfse-sbp-bar-has-active .hfse-sbp-field-active,
.hfse-sbp-bar-has-active .hfse-sbp-field-btn[data-state="open"] {
  flex-grow: 2.4;
  min-width: 172px;
}
/* Room for the absolutely-positioned clear button so the value text cannot
   slide under it (toolkit css:557-561: 12 right offset + 28 button + 4). */
.hfse-sbp-field-has-value {
  padding-right: 44px;
}
/* A FILLED When pill must fit its whole range: at narrow container widths
   the Where input's intrinsic width otherwise squeezes the date field until
   "Aug 12 – Sep 3" ellipsizes, defeating the year-less format. Deliberate
   divergence from the module, which truncates the same way at these widths
   (Eli decision 10, 2026-08-05 audit). 190px = widest short-format range
   plus the 20px left pad and the 44px clear-button reserve. Sits AFTER the
   bare has-value rule: the css test's rule() helper is first-substring-match
   and `.hfse-sbp-field-has-value {` occurs inside this selector too. */
.hfse-sbp-date-field.hfse-sbp-field-has-value {
  min-width: 190px;
}
/* Hover dim — scoped to the desktop bar, the only surface it belongs to.
   The toolkit never had to state this: its hover rule is already a descendant
   of `.hrtk-sbp-search-bar` (searchbar-pro.css:379-385) and its mobile sheet is
   built from a separate `__mobile-*` class family, so the field surface simply
   cannot reach the sheet. The widget instead re-renders the SAME field
   components inside `.hfse-sbp-mobile-stage` (ProFilterBar.tsx:401-413), so an
   element-level rule leaks straight in — and the desktop neutraliser below is
   keyed to `.hfse-sbp-bar-indicators`, a class that only ever lands on the
   desktop <form> (ProFilterBar.tsx:345), so it never covers the sheet.
   On touch, `:hover` latches onto the last-tapped element (the field qualifies:
   it has a hover rule and `cursor: pointer`) and stays until the next tap
   elsewhere. Unscoped, that painted `--hfse-input-bg` across the sheet field's
   `width: 100%; min-height: 60px` box with the inherited pill radius, and since
   `.hfse-sbp-mobile-stage .hfse-sbp-listbox` is `position: static` (below) the
   open panel flows INSIDE that box — the grey half of the pale rounded blob in
   Eli's QA 2026-08-05 item 2. The open-state override further down had fixed
   only the white half. */
.hfse-sbp-bar .hfse-sbp-field:hover {
  background-color: var(--hfse-input-bg, #ebebeb);
}
.hfse-sbp-field-active,
.hfse-sbp-field-btn[data-state="open"] {
  background-color: var(--hfse-card-bg, #fff);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.10), 0 2px 4px rgba(0, 0, 0, 0.08);
}
/* Field value/placeholder colour eases on hover ↔ idle
   (toolkit: searchbar-pro.debug.css:397-400). */
.hfse-sbp-field-value,
.hfse-sbp-where-input,
.hfse-sbp-where-input::placeholder {
  transition: color 200ms var(--hfse-sbp-spring, ease);
}
/* Once the bar has mounted its sliding pills, the pills OWN the hover and
   active surfaces and the fields go transparent so the pill is what slides.
   Gated on a class the component only adds after mount (and only on the
   desktop bar), so with JS unavailable — SSR, hydration errors — the fields
   keep painting their own backgrounds exactly as they did before #870. */
/* `.hfse-sbp-bar` is restated here purely for specificity: now that the base
   hover rule is itself bar-scoped, matching only on `-indicators` would tie at
   (0,3,0) and leave the winner decided by source order. Both classes sit on the
   same <form>, so the extra token never changes what this matches. */
.hfse-sbp-bar.hfse-sbp-bar-indicators .hfse-sbp-field:hover {
  background-color: transparent;
}
.hfse-sbp-bar-indicators .hfse-sbp-field-active,
.hfse-sbp-bar-indicators .hfse-sbp-field-btn[data-state="open"] {
  background-color: transparent;
  box-shadow: none;
}
/* Label / value typography (toolkit css:567-590). Two INDEPENDENT sizes, both
   tokenised here with the toolkit's own defaults so this branch works before
   the settings lane emits them. The uppercase is CSS, not the string — the
   components still render title case. */
.hfse-sbp-field-label {
  display: block;
  font-size: var(--hfse-sbp-label-size, 11px);
  font-weight: 700;
  line-height: 1;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--hfse-muted-foreground, #6b7280);
  /* Load-bearing on Where, where the label is a real <label htmlFor>: a click
     on it would otherwise re-fire focus on the input under the one the
     visitor actually pressed (toolkit css:575-576). */
  user-select: none;
  pointer-events: none;
}
.hfse-sbp-field-value {
  display: block;
  font-size: var(--hfse-sbp-input-size, 15px);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hfse-sbp-field-placeholder {
  color: var(--hfse-muted-foreground, #717171);
}
/* Where combobox */
.hfse-sbp-where-input-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.hfse-sbp-where-input {
  width: 100%;
  min-width: 0;
  border: none;
  padding: 0;
  background: transparent;
  font-size: var(--hfse-sbp-input-size, 15px);
  line-height: 1.4;
  color: var(--hfse-foreground, #222);
  cursor: pointer;
}
.hfse-sbp-where-input:focus {
  outline: none;
  cursor: text;
}
.hfse-sbp-where-input::placeholder {
  color: var(--hfse-muted-foreground, #717171);
  opacity: 1;
}
/* Per-field clear (toolkit css:508-561). ONE rule for all four fields; Where's
   22px filled chip was the widget's only clear before this and is reconciled
   onto it (#870 QA, Eli 2026-08-05).
   The toolkit gates visibility with opacity/pointer-events under a
   `--has-value` class because it has no way to unmount; React mounts the node
   only when the field has an applied value, so the entrance is a keyframe
   instead of an opacity gate — and the node stays out of the a11y tree (and
   out of the tab order) entirely while there is nothing to clear.
   The toolkit's `margin-left: 8px` / `flex-shrink: 0` are inert under absolute
   positioning and are deliberately not ported. */
@keyframes hfse-sbp-clear-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.hfse-sbp-field-clear {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--hfse-muted-foreground, #6b7280);
  font-family: inherit;
  cursor: pointer;
  /* Above the field's own text and above the sliding pills. */
  z-index: 2;
  animation: hfse-sbp-clear-in 180ms ease;
  transition:
    background-color 150ms var(--hfse-sbp-spring, ease),
    color 150ms var(--hfse-sbp-spring, ease);
}
/* The hover circle must darken RELATIVE to the pill: the pill itself paints
   --hfse-input-bg, so a plain var() here renders the exact same color and the
   circle never shows (r7 #936). Mixing 6% foreground into the pill token
   lands at ~#e0e0e0 on the default #ebebeb pill — the toolkit's pairing
   (searchbar-pro.css:574-627) — and keeps contrast on themed hosts. */
.hfse-sbp-field-clear:hover {
  background-color: color-mix(
    in srgb,
    var(--hfse-foreground, #111827) 6%,
    var(--hfse-input-bg, #ebebeb)
  );
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-field-clear:focus-visible {
  outline: 2px solid var(--hfse-sbp-accent, #ff385c);
  outline-offset: 2px;
}
.hfse-sbp-field-clear svg {
  display: block;
  width: 14px;
  height: 14px;
}
/* Inside the shared text-entry box (keyword filter / By-name lookup, r8
   #937) the clear is a flex SIBLING of the input, not an absolutely-anchored
   overlay: the box is a padded flex row, so static placement centers it and
   the input's flex-basis absorbs the width — no conditional padding jump.
   Negative vertical margins keep the 28px circle from inflating the
   10px-padded row. */
.hfse-sbp-what-inputbox .hfse-sbp-field-clear {
  position: static;
  transform: none;
  flex-shrink: 0;
  margin: -4px -6px -4px 0;
}
.hfse-sbp-listbox {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  min-width: 280px;
  max-width: 380px;
  max-height: 420px;
  overflow-y: auto;
  padding: 12px 0;
  background-color: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  border-radius: min(16px, var(--hfse-sbp-shape-max, 999px));
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.2);
  z-index: 9999;
}
.hfse-sbp-listbox-heading {
  padding: 6px 20px;
  font-size: var(--hfse-sbp-label-size, 11px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--hfse-muted-foreground, #717171);
}
.hfse-sbp-listbox-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 20px;
  border: none;
  background: transparent;
  color: var(--hfse-foreground, #222);
  font-size: var(--hfse-sbp-input-size, 15px);
  text-align: left;
  cursor: pointer;
}
.hfse-sbp-listbox-item:hover,
.hfse-sbp-listbox-item-active {
  background-color: var(--hfse-input-bg, #f0f0f0);
}
.hfse-sbp-listbox-item-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: min(8px, var(--hfse-sbp-shape-max, 999px));
  background-color: var(--hfse-input-bg, #f0f0f0);
  color: var(--hfse-muted-foreground, #555);
}
.hfse-sbp-listbox-empty {
  padding: 10px 20px;
  font-size: var(--hfse-sbp-input-size, 15px);
  color: var(--hfse-muted-foreground, #717171);
}
/* Destination Filter popup (#1072 D1, toolkit destination-filter): tabs +
   accordion rendered inside the Where listbox. Reuses the listbox's own
   tokens (bg, foreground, muted, input-bg, sbp sizes and shape cap) so the
   panel follows the same theme and dress as the plain suggestion rows. */
.hfse-dest-panel {
  display: flex;
  flex-direction: column;
  /* No min-width on phones: 320px exceeds the mobile stage body after its
     gutters and would clip the popup on 320-390px viewports. The desktop
     popover gets the floor at the shared 640px breakpoint. */
  min-width: 0;
}
@media screen and (min-width: 640px) {
  .hfse-dest-panel {
    min-width: 320px;
  }
}
.hfse-dest-title {
  padding: 2px 20px 10px;
  font-size: var(--hfse-sbp-input-size, 15px);
  font-weight: 700;
  color: var(--hfse-foreground, #222);
}
/* Tabs size to their labels and the strip scrolls. Stretching them (flex: 1)
   wrapped "BY ISLAND" / "BY RESORT" onto two lines as soon as a feed produced
   a fourth tab, inside the 380px popover cap. */
.hfse-dest-tabs {
  display: flex;
  gap: 4px;
  padding: 0 16px 8px;
  border-bottom: 1px solid var(--hfse-border, rgba(0, 0, 0, 0.08));
  overflow-x: auto;
  scrollbar-width: none;
}
.hfse-dest-tabs::-webkit-scrollbar {
  display: none;
}
.hfse-dest-tab {
  flex: 0 0 auto;
  white-space: nowrap;
  padding: 8px 10px;
  border: none;
  border-radius: min(10px, var(--hfse-sbp-shape-max, 999px));
  background: transparent;
  color: var(--hfse-muted-foreground, #717171);
  font: inherit;
  font-size: var(--hfse-sbp-label-size, 11px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  cursor: pointer;
}
.hfse-dest-tab:hover {
  background-color: var(--hfse-input-bg, #f0f0f0);
}
.hfse-dest-tab-active,
.hfse-dest-tab-active:hover {
  background-color: var(--hfse-foreground, #222);
  color: var(--hfse-card-bg, #fff);
}
.hfse-dest-list {
  padding-top: 8px;
}
.hfse-dest-group-heading {
  padding: 8px 20px 4px;
  font-size: var(--hfse-sbp-label-size, 11px);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.6px;
  color: var(--hfse-muted-foreground, #717171);
}
/* Row = the select button plus its own disclosure control. The two are
   separate hit areas on purpose (clicking an island applies that island;
   the chevron only expands), so the hover highlight has to live on the ROW
   rather than on either button, or half the row lights up. */
.hfse-dest-row {
  display: flex;
  align-items: stretch;
}
.hfse-dest-row:hover,
.hfse-dest-row:has(.hfse-dest-item-active) {
  background-color: var(--hfse-input-bg, #f0f0f0);
}
.hfse-dest-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex: 1;
  min-width: 0;
  padding: 9px 20px;
  border: none;
  background: transparent;
  color: inherit;
  font: inherit;
  font-size: var(--hfse-sbp-input-size, 15px);
  text-align: left;
  cursor: pointer;
}
/* :has() fallback — older Safari/Firefox keep the pre-#1246 behaviour of
   painting the button itself, which is visually equivalent for the common
   childless row. */
.hfse-dest-item:hover,
.hfse-dest-item-active {
  background-color: var(--hfse-input-bg, #f0f0f0);
}
.hfse-dest-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  width: 40px;
  padding: 0;
  border: none;
  background: transparent;
  color: var(--hfse-muted-foreground, #717171);
  cursor: pointer;
}
.hfse-dest-toggle svg {
  transition: transform 150ms var(--hfse-sbp-spring, ease);
}
.hfse-dest-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}
.hfse-dest-item-child {
  padding-left: 36px;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
}
.hfse-dest-item-count {
  font-size: var(--hfse-sbp-label-size, 11px);
  color: var(--hfse-muted-foreground, #717171);
  font-variant-numeric: tabular-nums;
}
/* Submit CTA: collapsed icon circle ↔ expanded label pill.
   Collapsed is a SQUARE the size of the field min-height — that is the
   toolkit's invariant (64px circle beside 64px fields in hero,
   48/48 in refine; searchbar-pro.css:656-685 + :300). The widget's field is
   52px, so the circle is 52px. */
.hfse-sbp-submit {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0;
  flex: 0 0 auto;
  align-self: center;
  /* Explicit: the JS width measurement adds padding INTO --hfse-sbp-cta-w,
     which is only correct under border-box. A host stylesheet resetting
     button box-sizing would widen every expanded pill by the padding
     (2026-08-05 audit). */
  box-sizing: border-box;
  width: 52px;
  height: 52px;
  padding: 0;
  overflow: hidden;
  border: none;
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background-color: var(--hfse-sbp-accent, #ff385c);
  color: #fff;
  font-size: var(--hfse-sbp-input-size, 15px);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  /* Above the sliding pills — the active pill's shadow paints in the same
     stacking context and would smear over the CTA without this
     (toolkit: searchbar-pro.debug.css:695-698). */
  position: relative;
  z-index: 4;
  /* Expand/collapse + press micro-interaction
     (toolkit: searchbar-pro.debug.css:700, 707-708). */
  transition:
    width 250ms ease,
    padding 250ms ease,
    gap 250ms ease,
    background-color 0.15s ease,
    transform 0.1s ease;
}
.hfse-sbp-submit:hover {
  background-color: var(--hfse-sbp-accent-hover, #e0314f);
}
.hfse-sbp-submit:active {
  transform: scale(0.97);
}
.hfse-sbp-submit:focus-visible {
  outline: none;
  box-shadow: 0 0 0 4px var(--hfse-sbp-accent-ring, rgba(255, 56, 92, 0.25));
}
.hfse-sbp-submit-icon {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
/* Label reveal (toolkit css:706-730). The 0 → auto width is not an animatable
   pair, so the span's own width transition is decoration — the real motion is
   the BUTTON's width. Both are kept for parity, and the span stays mounted at
   all times so there is something to clip and something to measure. Note the
   deliberate asymmetry: width matches the button's 250ms, opacity lands 50ms
   earlier. */
.hfse-sbp-submit-label {
  display: inline-block;
  width: 0;
  overflow: hidden;
  opacity: 0;
  white-space: nowrap;
  transition: width 250ms ease, opacity 200ms ease;
}
/* EXPANDED === "some field is open", nothing else — the toolkit writes
   `--expanded` from exactly one place, `next !== null` in setActiveField
   (searchbar-pro.js:2464-2470), and never from whether a filter has a value.
   At rest with filters applied the button is a bare icon circle. The widget's
   equivalent signal, `hfse-sbp-bar-has-active`, is already on the form, so
   this is CSS only (Eli QA 2026-08-05 item 4).
   `--hfse-sbp-cta-w` is written inline on the button by the component after
   measuring the label; without it the pill falls back to the toolkit's stock
   130px. Either way it is a length → length transition, so the morph
   animates. */
.hfse-sbp-bar-has-active .hfse-sbp-submit {
  width: var(--hfse-sbp-cta-w, 130px);
  padding: 0 24px;
  gap: 8px;
}
.hfse-sbp-bar-has-active .hfse-sbp-submit-label {
  width: auto;
  opacity: 1;
}
/* Quick-filter chips: horizontally scrollable, single-select, edge fades */
.hfse-sbp-chips {
  position: relative;
  margin-top: 14px;
}
/* Desktop-only by default. The toolkit hides the chip row entirely below
   768px as an explicit product decision (searchbar-pro.debug.css:3939-3943,
   "v1 mobile decision, issue #284") — the mobile search sheet owns filtering
   at that size. The widget shipped them unrestricted, which was a divergence
   rather than a choice; `searchbar.chips.showOnMobile` opts back in.
   NOTE the breakpoint: 768px here, not the 932px bar/sheet cutover. Both
   numbers come from the reference and they are deliberately different. */
@media (max-width: 767px) {
  .hfse-sbp-chips:not(.hfse-sbp-chips-mobile) {
    display: none;
  }
}
.hfse-sbp-chips-track {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.hfse-sbp-chips-track::-webkit-scrollbar {
  display: none;
}
.hfse-sbp-chips-fade-l .hfse-sbp-chips-track {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 40px);
  mask-image: linear-gradient(to right, transparent 0, #000 40px);
}
.hfse-sbp-chips-fade-r .hfse-sbp-chips-track {
  -webkit-mask-image: linear-gradient(to left, transparent 0, #000 40px);
  mask-image: linear-gradient(to left, transparent 0, #000 40px);
}
.hfse-sbp-chips-fade-l.hfse-sbp-chips-fade-r .hfse-sbp-chips-track {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 40px, #000 calc(100% - 40px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 40px, #000 calc(100% - 40px), transparent 100%);
}
.hfse-sbp-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: 0 0 auto;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--hfse-border, #ddd);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background-color: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  /* Tracks the value size two steps down, so the size setting reaches the
     chips too without changing today's 13px default. */
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
  user-select: none;
}
.hfse-sbp-chip:hover {
  border-color: var(--hfse-muted-foreground, #999);
}
.hfse-sbp-chip-active {
  border-color: var(--hfse-sbp-accent, #ff385c);
  color: var(--hfse-sbp-accent, #ff385c);
  box-shadow: inset 0 0 0 1px var(--hfse-sbp-accent, #ff385c);
}
/* Inline <svg> (#871): sized here, colored by the markup's own currentColor
   fill/stroke so it follows the chip text, including the active accent. */
.hfse-sbp-chip-icon {
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
}
/* Mobile trigger pill (two summary lines) */
.hfse-sbp-mobile-trigger {
  display: none;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 16px;
  border: 1px solid var(--hfse-border, #e5e5e5);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background-color: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  text-align: left;
}
.hfse-sbp-mobile-trigger-icon {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.hfse-sbp-mobile-trigger-lines {
  display: flex;
  flex-direction: column;
  min-width: 0;
  gap: 1px;
}
.hfse-sbp-mobile-trigger-primary {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hfse-sbp-mobile-trigger-secondary {
  font-size: calc(var(--hfse-sbp-label-size, 11px) + 1px);
  color: var(--hfse-muted-foreground, #717171);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Mobile staged sheet (rendered in the elevated dialog portal) */
.hr-dialog-content.hfse-sbp-mobile-sheet {
  display: flex;
  flex-direction: column;
  width: 100vw;
  height: 100dvh;
  max-width: none;
  max-height: none;
  border-radius: 0;
  background: var(--hfse-background, #f7f7f7);
  /* r7 #936: the base dialog's 24px padding pushed the whole sheet inward —
     header, body and footer each carry their own gutters (module structure),
     and it was this padding that dropped the title 24px below the absolutely
     positioned header circles. */
  padding: 0;
}
/* Module footer bar (searchbar-pro.css:3051-3059): its own gutter + the top
   hairline — previously the dialog's 24px padding faked the insets. */
.hr-dialog-content.hfse-sbp-mobile-sheet .hk-modal-footer {
  padding: 14px 16px;
  background: var(--hfse-card-bg, #fff);
  box-shadow: 0 -1px 0 var(--hfse-border, #ebebeb);
  margin: 0;
}
.hfse-sbp-mobile-body {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0 16px 20px; /* module __mobile-body (searchbar-pro.css:2817-2825) */
  /* r8 #937 supersedes the r7 thin dark rail: Eli still saw it while
     scrolling across the sheet's sections and wants none at all. */
  scrollbar-width: none;
}
.hfse-sbp-mobile-body::-webkit-scrollbar {
  display: none;
}
.hfse-sbp-mobile-stage {
  background: var(--hfse-card-bg, #fff);
  /* Module card chrome (searchbar-pro.css:2829-2840): 16px radius, a much
     quieter resting shadow, and a soft lift while the stage is active. */
  border-radius: min(16px, var(--hfse-sbp-shape-max, 999px));
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
  transition: box-shadow 0.2s ease;
}
.hfse-sbp-mobile-stage.hfse-sbp-stage-active {
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.06);
}
.hfse-sbp-mobile-stage .hfse-sbp-field,
.hfse-sbp-mobile-stage .hfse-sbp-field-btn {
  width: 100%;
  min-height: 60px;
  padding: 12px 18px;
}
/* Restated at the sheet's specificity: the rule above would otherwise win and
   the value text would run under the clear button. */
.hfse-sbp-mobile-stage .hfse-sbp-field-has-value {
  padding-right: 44px;
}
/* Neutralise the OPEN-field surface inside the sheet.
   Eli QA 2026-08-05 item 2 — "a large pale white rounded blob behind the
   Where panel". Source: the open-state rule further up
   (`.hfse-sbp-field-active, .hfse-sbp-field-btn[data-state="open"]`) is
   unscoped, and the desktop bar cancels it via `.hfse-sbp-bar-indicators` —
   a class that only ever lands on the desktop <form>. Inside the sheet each
   field is still its own Radix trigger, so tapping it stamps
   data-state="open" and the base rule paints `--hfse-card-bg` at
   `width: 100%; min-height: 60px` with the field's inherited
   `border-radius: min(999px, …)`: a full-width white stadium with the
   two-layer shadow, sitting behind the open panel. This block previously
   cancelled only the shadow, which left the white shape.
   Both selector shapes are required: `.hfse-sbp-field-active` is put on a
   plain <div> by ProWhereField, so the `[data-state]` half never matches
   Where. Specificity is (0,2,0) / (0,3,0) against the base rule's
   (0,1,0) / (0,2,0), so this wins without !important. */
.hfse-sbp-mobile-stage .hfse-sbp-field-active,
.hfse-sbp-mobile-stage .hfse-sbp-field-btn[data-state="open"] {
  background-color: transparent;
  box-shadow: none;
}
.hfse-sbp-mobile-stage .hfse-sbp-listbox {
  position: static;
  box-shadow: none;
  max-width: none;
  /* The base popover floor (280px, explorer.css ~2894) exceeds a 320px
     viewport minus the sheet gutters; inline in the sheet the card sets the
     width, so the floor only clips (#1072 D1 tabs made it visible). */
  min-width: 0;
  padding-top: 0;
  /* r7 #936: module architecture — each stage scrolls INSIDE its card
     (suggestions capped at 32vh, searchbar-pro.css:3201-3221) so the stages
     below stay reachable without scrolling the whole sheet body.
     r8 #937: rail hidden along with the other sheet rails — one sheet, one
     rule; a lone visible rail here would read as an oversight. */
  max-height: 32vh;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.hfse-sbp-mobile-stage .hfse-sbp-listbox::-webkit-scrollbar {
  display: none;
}
/* --- Sheet Where dress (#935 item 3): module __mobile-input-wrap + the
   two-line rounded suggestion rows (searchbar-pro.css:2911-2948, 3186-3273).
   All sheet-scoped — the desktop combobox keeps its own shape. --- */
.hfse-sbp-where-input-row-sheet {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--hfse-card-bg, #fff);
  border: 1px solid var(--hfse-border, #ddd);
  border-radius: min(12px, var(--hfse-sbp-shape-max, 999px));
  padding: 0 14px;
  transition: border-color 0.15s ease;
}
.hfse-sbp-where-input-row-sheet:focus-within {
  border-color: var(--hfse-foreground, #222);
  box-shadow: 0 0 0 1px var(--hfse-foreground, #222);
}
.hfse-sbp-where-input-icon {
  display: inline-flex;
  flex: 0 0 auto;
  color: var(--hfse-muted-foreground, #717171);
}
.hfse-sbp-where-input-row-sheet .hfse-sbp-where-input {
  padding: 14px 0; /* module __mobile-input: tall touch target inside the wrap */
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 1px); /* module: 16px */
  border: 0;
  background: transparent;
}
.hfse-sbp-suggestions-label {
  margin: 20px 0 10px;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px); /* module __mobile-suggestions-label: 13px */
  font-weight: 600;
  color: var(--hfse-muted-foreground, #717171);
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
/* r6 item 3 dress: rounded hover/active rows (the widget's were sharp) with
   the module's 48px icon tile and two-line name + dimension subtitle. */
.hfse-sbp-mobile-stage .hfse-sbp-listbox-item {
  gap: 14px;
  padding: 12px 8px;
  border-radius: min(12px, var(--hfse-sbp-shape-max, 999px));
}
.hfse-sbp-mobile-stage .hfse-sbp-listbox-item-icon {
  width: 48px;
  height: 48px;
  border-radius: min(12px, var(--hfse-sbp-shape-max, 999px));
}
.hfse-sbp-mobile-stage .hfse-sbp-listbox-item-icon svg {
  width: 22px;
  height: 22px;
}
.hfse-sbp-listbox-item-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.hfse-sbp-listbox-item-name {
  font-weight: 600; /* module __mobile-suggestion-label: 15px/600 */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hfse-sbp-listbox-item-sub {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px); /* module __mobile-suggestion-sub: 13px */
  color: var(--hfse-muted-foreground, #717171);
  margin-top: 2px;
}
/* --- Sheet accordion (Eli r5): stage headers + inline section bodies -------
   The module sheet expands each section IN PLACE (one active stage, others
   collapsed to label+summary rows); the widget's stage dialogs are gone below
   933px. The header button reuses the field-card classes, so the collapsed
   look is exactly the previous stage card; while its stage is active the
   value/summary line hides (module: the active header keeps only the small
   label) and the body renders inside the same card. */
.hfse-sbp-mobile-stage .hfse-sbp-stage-header {
  border: 0;
  background: transparent;
  text-align: left;
  cursor: pointer;
  /* r6 item 5 (#935): collapsed rows read name LEFT + instruction RIGHT on
     one line (module __mobile-stage-header, css:2842-2856) instead of the
     old stacked caps-label-over-value. r7 (#936): the module row is padded
     16px 20px with no minimum height — the field rule's 12px 18px + 60px
     min-height made collapsed rows read denser and taller than the module's. */
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 20px;
  min-height: 0;
}
.hfse-sbp-mobile-stage .hfse-sbp-stage-header .hfse-sbp-field-label {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px); /* module __mobile-stage-label: 14px/500 */
  font-weight: 500;
  line-height: 1.4;
  text-transform: none;
  letter-spacing: normal;
}
.hfse-sbp-mobile-stage .hfse-sbp-stage-header .hfse-sbp-field-value {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px); /* module __mobile-stage-summary: 14px/600 */
  font-weight: 600;
  max-width: 60%;
}
/* Module instructions render in the summary's own strength ("When | Add
   dates" both read as content, css:2862-2870), not a muted placeholder tone. */
.hfse-sbp-mobile-stage .hfse-sbp-stage-header .hfse-sbp-field-placeholder {
  color: var(--hfse-foreground, #222);
}
.hfse-sbp-stage-active .hfse-sbp-stage-header .hfse-sbp-field-value {
  display: none;
}
.hfse-sbp-stage-active .hfse-sbp-stage-header {
  min-height: 0;
  padding-bottom: 0;
}
.hfse-sbp-mobile-stage .hfse-sbp-stage-body {
  padding: 4px 20px 22px; /* module __mobile-stage-body (css:2872-2875) */
}
/* Stage-advance fade-up (r7 #936): the module animates the incoming stage
   body — 0.28s ease-out fade with a 6px drop-in, plus the shrunk header
   label fading from 40% (hrtk-sbp-stage-fade-in / -label-shrink,
   searchbar-pro.css:2876-2896). The animation rides the active-class flip,
   so the JS stays a pure class toggle. */
@keyframes hfse-sbp-stage-fade-in {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes hfse-sbp-stage-label-fade {
  from { opacity: 0.4; }
  to { opacity: 1; }
}
.hfse-sbp-mobile-stage.hfse-sbp-stage-active .hfse-sbp-stage-body {
  animation: hfse-sbp-stage-fade-in 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}
.hfse-sbp-mobile-stage.hfse-sbp-stage-active .hfse-sbp-stage-header .hfse-sbp-field-label {
  animation: hfse-sbp-stage-label-fade 0.28s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Killed in the file-final reduced-motion block, like every other hfse-sbp
   animation — the QA guard maps each animation selector into that one list. */
/* Sheet header: module centres the title between the back and close circles
   (searchbar-pro.css:2769-2816) — and the absolutely-positioned Back would
   otherwise sit on top of a left-aligned title. */
.hr-dialog-content.hfse-sbp-mobile-sheet .hk-modal-header {
  display: flex;
  justify-content: center;
  align-items: center;
  /* Module header: 14px vertical (css:2760-2768); sides stay 56px so the
     title clears the circular Back/Close buttons. */
  padding: 14px 56px;
}
/* Module __mobile-title: 16px/600 (searchbar-pro.css:2769-2774). */
.hr-dialog-content.hfse-sbp-mobile-sheet .hk-modal-header .hk-h4 {
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 1px);
  font-weight: 600;
}
/* Module Back: circular header icon button, mirror of the close X
   (searchbar-pro.css:2794-2816): 36px circle at left 12px, 1px #ddd border,
   vertically centred on the title line (top 7px lands the 36px circle's
   centre on the 14px-padded 16px title). r7 #936 dressed the border/offsets
   to the module values — the old 16/16 + shadow rode above the title. */
.hfse-sbp-mobile-back-btn {
  position: absolute;
  top: 7px;
  left: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border: 1px solid var(--hfse-border, #ddd);
  border-radius: var(--hfse-sbp-shape-max, 999px);
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  cursor: pointer;
}
.hfse-sbp-mobile-back-btn:hover {
  background: var(--hfse-input-bg, #f3f3f3);
}
/* Module close (searchbar-pro.css:2774-2792): same circle on the right. The
   element carries inline base styles (ui/dialog.tsx closeButtonStyle), so
   the sheet-scoped restyle needs !important to beat them. */
.hr-dialog-content.hfse-sbp-mobile-sheet .hr-dialog-close {
  top: 7px !important;
  right: 12px !important;
  width: 36px !important;
  height: 36px !important;
  border: 1px solid var(--hfse-border, #ddd) !important;
  border-radius: var(--hfse-sbp-shape-max, 999px) !important;
  background: var(--hfse-card-bg, #fff) !important;
  opacity: 1 !important;
  color: var(--hfse-foreground, #222);
}
.hr-dialog-content.hfse-sbp-mobile-sheet .hr-dialog-close:hover {
  background: var(--hfse-input-bg, #f3f3f3) !important;
}
.hr-dialog-content.hfse-sbp-mobile-sheet .hr-dialog-close svg {
  width: 14px;
  height: 14px;
}
.hfse-sbp-mobile-back-btn svg {
  display: block;
}
/* Inline calendar sizing: #930's 44px cells were sized for the 850px desktop
   panel — 7 of them plus border-spacing need 308px, and the stage body offers
   ~282px at a 390px viewport, clipping the Saturday column (measured on the
   first accordion strip). Size cells for the card and let fixed table layout
   split whatever width is actually there. */
.hfse-sbp-mobile-stage .hfse-rdp {
  --rdp-cell: 38px;
}
.hfse-sbp-mobile-stage .hfse-rdp-month-grid {
  width: 100%;
  table-layout: fixed;
}
/* Section question — module __mobile-stage-question ("Where to?" etc.). */
.hfse-sbp-stage-question {
  margin: 2px 0 16px;
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 7px);
  font-weight: 700; /* module __mobile-stage-question: 22px/700 (css:2904-2909) */
  line-height: 1.2;
  color: var(--hfse-foreground, #111827);
}
/* Inline what panes sit inside the padded stage body — swap the dialog pane's
   asymmetric gutters (-4px/+4px left, 12px right) for a symmetric negative-
   margin pair. Net content position is the stage-body edge (the bare
   padding-left:0 of the first pass left the base rule's -4px margin unbalanced,
   shifting the pane 4px left of the question), and the clip edge moves 4px out
   both sides so the 28px price-slider thumbs — which overhang the 12px-inset
   track by 14px at the extremes — paint fully instead of losing 2px to the
   pane's overflow-x:hidden (overflow tripwire catch, 2026-08-08). */
.hfse-sbp-what-inline .hfse-sbp-what-pane {
  margin: 0 -4px;
  padding: 0 4px;
}
/* Footer actions pair (module __mobile-footer-actions): outlined Next beside
   the Search CTA, right-aligned as a unit. */
.hfse-sbp-mobile-footer-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: auto;
}
.hfse-sbp-mobile-next-btn {
  padding: 12px 20px;
  border: 1px solid var(--hfse-border, #d1d5db);
  border-radius: min(10px, var(--hfse-sbp-shape-max, 999px));
  background: transparent;
  color: var(--hfse-foreground, #111827);
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 1px);
  font-weight: 600;
  text-transform: none;
  cursor: pointer;
}
/* Sheet footer CTA. The reference's mobile action button is content-sized and
   ALWAYS labelled — the collapse/expand morph is desktop-only
   (searchbar-pro.css:2836-2880, `__mobile-action`) — so it deliberately
   shares nothing with `.hfse-sbp-submit`. What it does need is to stop
   inheriting the widget's generic `.hk-button` chrome (uppercase, 13px, 4px
   radius), which is where Eli's "SEARCH · 6" casing came from. */
.hfse-sbp-mobile-search-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 22px;
  border-radius: min(10px, var(--hfse-sbp-shape-max, 999px));
  background-color: var(--hfse-sbp-accent, #ff385c) !important;
  color: #fff !important;
  font-size: 16px;
  font-weight: 600;
  text-transform: none;
}
.hfse-sbp-mobile-search-btn svg {
  display: block;
  width: 16px;
  height: 16px;
}
/* r6 item 4 (#935): footer dress. The reset is module __mobile-clear-all —
   sentence case, underlined, ONE line (the generic .hk-button chrome
   uppercased it and let "CLEAR ALL" wrap); Next takes the module's
   foreground outline (css:3070-3078); both action labels refuse to wrap
   like the module's content-sized buttons. */
.hr-dialog-content.hfse-sbp-mobile-sheet .hfse-modal-reset-button {
  font-size: var(--hfse-sbp-input-size, 15px); /* module __mobile-clear-all: 15px/600 */
  font-weight: 600;
  text-transform: none;
  text-decoration: underline;
  color: var(--hfse-foreground, #222);
  white-space: nowrap;
  padding: 8px 4px;
  flex: 0 0 auto;
}
.hr-dialog-content.hfse-sbp-mobile-sheet .hfse-sbp-mobile-next-btn {
  border-color: var(--hfse-foreground, #222); /* module __mobile-next: 1px solid #222 */
  white-space: nowrap;
}
.hr-dialog-content.hfse-sbp-mobile-sheet .hfse-sbp-mobile-search-btn {
  white-space: nowrap;
}
/* Breakpoint swap — 932/933px, matching the toolkit's functional breakpoint */
@media (max-width: 932px) {
  .hfse-sbp-bar {
    display: none;
  }
  .hfse-sbp-mobile-trigger {
    display: flex;
  }
}
/* ==========================================================================
   Searchbar Pro motion system (#870 — toolkit motion parity)
   Durations/easings transcribed from assets/css/searchbar-pro.debug.css and
   assets/js/searchbar-pro.js in homerunner-toolkit; line refs inline.
   ========================================================================== */
/* --- Sliding hover + active indicator pills -------------------------------
   Toolkit css:442-500. Two absolutely-positioned pills share the bar: one
   paints the hovered field, one the open field. JS writes left/width as
   inline styles; CSS springs both so the pill slides laterally between
   adjacent fields instead of cross-fading in place. Both sit at z-index 0,
   under the field text (z-index 1). */
.hfse-sbp-hover-indicator,
.hfse-sbp-active-pill {
  position: absolute;
  top: 6px; /* matches the bar's padding */
  left: 0;
  width: 0;
  height: calc(100% - 12px);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  opacity: 0;
  pointer-events: none;
  z-index: 0;
  transition:
    left 320ms var(--hfse-sbp-spring, ease),
    width 320ms var(--hfse-sbp-spring, ease),
    opacity 180ms ease;
  will-change: left, width;
}
.hfse-sbp-hover-indicator {
  background-color: var(--hfse-input-bg, #ebebeb);
}
.hfse-sbp-active-pill {
  background-color: var(--hfse-card-bg, #fff);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.10), 0 2px 4px rgba(0, 0, 0, 0.08);
}
.hfse-sbp-hover-indicator-visible,
.hfse-sbp-active-pill-visible {
  opacity: 1;
}
/* An open field outranks a hovered one: the active pill takes over rendering
   entirely (toolkit css:466-469). */
.hfse-sbp-bar-has-active .hfse-sbp-hover-indicator {
  opacity: 0 !important;
}
/* --- Popover open/close crossfade -----------------------------------------
   Toolkit css:1786-1807: 180ms opacity + translateY(4px) in, translateY(2px)
   out, symmetric so two popovers overlap during the swap. The toolkit drives
   this with --entering/--leaving classes and a JS setTimeout; Radix already
   exposes the same lifecycle as [data-state], and expressing it as a real
   @keyframes animation (not a transition) is what makes Radix's Presence
   defer unmount until the exit finishes.

   Scoped to .hfse-sbp-popover / .hfse-sbp-popover-overlay — classes the
   filter dialogs add ONLY in their pro variant. The bare .hr-dialog-content
   selector would have replaced common.css's scale-in and added exit
   animations on every dialog in the widget, legacy variant included
   (codex r1 HIGH). The dialogs are portaled, so ancestor scoping under
   .hfse-sbp is not possible; a call-site class is. */
/* ENTRANCE ONLY, by structural constraint, not oversight: Radix's
   DialogPortal wraps each of its DIRECT children in a Presence
   (@radix-ui/react-dialog Portal — React.Children.map(children, child =>
   <Presence>…)), and our portal child is the unanimated .hr-dialog-wrapper
   div, which unmounts the instant `open` flips. A [data-state="closed"]
   animation down here on the content can never render a frame — the first
   cut shipped exactly that dead code (codex fresh pass). Close is therefore
   immediate, as it was before this branch; a real exit needs the shared
   dialog wrapper restructured (follow-up on #870), not more CSS. */
@keyframes hfse-sbp-popover-in {
  from { opacity: 0; transform: translateY(4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.hr-dialog-content.hfse-sbp-popover[data-state="open"] {
  animation: hfse-sbp-popover-in 180ms ease;
}
@keyframes hfse-sbp-overlay-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes hfse-sbp-overlay-out {
  from { opacity: 1; }
  to   { opacity: 0; }
}
.hr-dialog-overlay.hfse-sbp-popover-overlay[data-state="open"] {
  animation: hfse-sbp-overlay-in 180ms ease;
}
.hr-dialog-overlay.hfse-sbp-popover-overlay[data-state="closed"] {
  animation: hfse-sbp-overlay-out 180ms ease;
}
/* --- Desktop popover anchoring (QA item 1) --------------------------------
   The toolkit renders When/Who/Filters as popovers under the bar with NO
   scrim (searchbar-pro.css:887-903 guests, 1054-1071 what, 1780-1796
   datepicker); the port's dialogs are portaled, so useSbpPopover measures
   the bar rect on open and writes it onto the wrapper as fixed coordinates.
   These classes are stamped ONLY while such a measurement is live — the
   legacy explorer, the mobile sheet's staged fields, and the below-933px
   fallback never carry them. */
/* Same trick as the mobile overlay below: the scrim is an INLINE
   rgba(0,0,0,0.6), and only an important author declaration outranks a
   non-important inline style. The node stays (it is Radix's outside-click
   catcher); only its paint goes. */
.hr-dialog-overlay.hfse-sbp-popover-overlay-anchored {
  background-color: transparent !important;
}
/* The wrapper's measured width IS the popover width (full bar, or the
   right-anchored 50% / min 320px) — the centred-modal caps must not
   shrink it. Max height arrives from the hook via custom property: a
   percentage would resolve against the auto-height wrapper and become
   none. Radius/shadow/border transcribed from the toolkit popover tokens
   (--hrtk-sbp-popover-radius 16px, --hrtk-sbp-popover-shadow, css:171-172,
   896-900). */
.hr-dialog-content.hfse-sbp-popover-anchored {
  max-width: none;
  max-height: var(--hfse-sbp-popover-max-h, 85vh);
  border-radius: 16px;
  border: 1px solid var(--hfse-border, rgba(0, 0, 0, 0.08));
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.16);
}
/* Datepicker shell is the one popover with its own tokens in the reference:
   radius 12, softer shadow (searchbar-pro.css:1790-1793). Same specificity
   as the rule above — order in this file is what lets it win. */
.hfse-form-date-options.hfse-sbp-popover-anchored {
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
}
/* The months FILL the full-bar-width panel (#930, Eli 8/7 parity review):
   month panes flex:1 apart (base rule) and .hfse-rdp-month-grid stretches
   each table to its pane, so day cells spread like the module's
   repeat(7, 1fr) rows — ~55px cells around the fixed 44px circles at the
   850px bar, matching the reference at the same viewport. (An earlier port
   deliberately held these content-sized and centred here; that deferral was
   called in by the 8/7 strip review, so no anchored-scope rules remain.) */
/* --- Guests popover: module guest-picker treatment (#931) -----------------
   Transcribed from the toolkit guest picker (searchbar-pro.css:1032-1133 +
   live DOM 2026-08-07): rows padded 20/0 with #ebebeb rules between (first
   row 4px top, last 4px bottom), 16px/600 title over 13px muted hint, 32px
   circular hairline steppers (#b0b0b0 → #222 on hover, 0.4 opacity when
   capped), plain 16px count, and an underlined 13/600 footer affordance in
   a 12px-top row. Scoped to the DRESS class (carried by the pro popover
   dialog AND the sheet accordion's inline guests body — Eli r5) so the
   classic explorer's guests modal keeps its hk form look untouched. The
   DIALOG keeps its stage-until-Apply semantics and Apply label (Eli 8/5
   divergence); the sheet stage live-applies like the module. Light values;
   dark rides useExplorerCss (--gp-* block next to the --dp-* one). */
.hfse-sbp-guests-dress.hfse-form-guests-options {
  --gp-row-border: #ebebeb;
  --gp-btn-border: #b0b0b0;
  --gp-btn-color: #717171;
  --gp-btn-hover: #222222;
  --gp-hint-color: #6b7280;
  padding: 20px;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-modal-body > .hk-flex {
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 0;
  border-bottom: 1px solid var(--gp-row-border);
  margin-top: 0;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-modal-body > .hk-flex:first-child {
  padding-top: 4px;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-modal-body > .hk-flex:last-child {
  border-bottom: 0;
  padding-bottom: 4px;
}
/* The module row is a space-between pair, not a 3/5–2/5 grid — columns go
   content-sized. */
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-width-3-5,
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-width-2-5 {
  width: auto;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-form-label {
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 1px);
  font-weight: 600;
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-text-meta {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  color: var(--gp-hint-color);
}
/* Stepper: minus / plain count / plus (module css:1102-1133). width: auto is
   load-bearing — the base .hfse-number-with-control is 90px wide, which
   flex-squeezed the 32px circles into 21px OVALS (r3 strip finding). */
.hfse-sbp-guests-dress.hfse-form-guests-options .hfse-number-with-control {
  display: flex;
  align-items: center;
  gap: 12px;
  width: auto;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .reduce-btn,
.hfse-sbp-guests-dress.hfse-form-guests-options .increase-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  flex: 0 0 32px; /* a shrinking flex item ovals the circle — never shrink */
  border: 1px solid var(--gp-btn-border);
  border-radius: 50%;
  background: transparent;
  color: var(--gp-btn-color);
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 3px);
  line-height: 1;
  cursor: pointer;
  user-select: none;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .reduce-btn:hover,
.hfse-sbp-guests-dress.hfse-form-guests-options .increase-btn:hover {
  border-color: var(--gp-btn-hover);
  color: var(--gp-btn-hover);
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hfse-number-control-disabled,
.hfse-sbp-guests-dress.hfse-form-guests-options .hfse-number-control-disabled:hover {
  opacity: 0.4;
  cursor: not-allowed;
  border-color: var(--gp-btn-border);
  color: var(--gp-btn-color);
}
/* Count reads as plain text (module <output>, 16px): the readonly input keeps
   its focusability but loses the box. */
.hfse-sbp-guests-dress.hfse-form-guests-options .number-input {
  width: 24px;
  padding: 0;
  border: none;
  background: transparent;
  text-align: center;
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 1px);
  font-weight: 400; /* module count is regular (measured); hk-input bolds it */
  color: var(--hfse-foreground, #111827);
}
/* Pets radio row keeps its radios (feed-config divergence: this feed stores a
   boolean where the module counts pets) but rides the row typography. */
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-grid label {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  color: var(--hfse-foreground, #111827);
}
/* Footer: module close-row — 12px top padding, underlined 13/600 text
   affordance right-aligned. Apply keeps its label; Clear joins the dress. */
.hfse-sbp-guests-dress.hfse-form-guests-options .hk-modal-footer {
  padding: 12px 0 0;
  border-top: 0; /* the row rules end at the last guest row, like the module */
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hfse-modal-next-button {
  /* !important is load-bearing: useExplorerCss paints the .bg-accent fill
     with its own !important (cascade priority for the alpha-accent pair), so
     only an important declaration can undress this one button. */
  background: transparent !important;
  color: var(--hfse-foreground, #111827);
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  font-weight: 600;
  text-transform: none;
  text-decoration: underline;
  padding: 4px 0;
  border-radius: 0;
}
.hfse-sbp-guests-dress.hfse-form-guests-options .hfse-modal-reset-button {
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  font-weight: 600;
  text-transform: none;
  text-decoration: underline;
  color: var(--hfse-foreground, #111827);
  padding: 4px 0;
}
/* Row rhythm for the CLASSIC guests modal (was an inline marginTop on the
   Children/Pets rows; moved to a class so the pro scope above can zero it
   without fighting an inline style). */
.hfse-guest-row-spacing {
  margin-top: 20px;
}
/* --- Mobile sheet: real bottom-sheet slide-up -----------------------------
   Toolkit css:2679 + keyframes 2683-2686. The reference modal is portaled to
   the body, fully opaque, z-index 10000, and has NO backdrop — so the port
   suppresses the shared dark scrim (.hfse-sbp-mobile-overlay) rather than
   flashing it behind a sheet that covers the viewport anyway. No outbound
   animation: the toolkit just sets [hidden] on close, and a closed-state
   animation here would be dead code anyway (see the Presence note above). */
@keyframes hfse-sbp-mobile-slide-up {
  from { transform: translateY(100%); opacity: 0.7; }
  to   { transform: translateY(0); opacity: 1; }
}
.hr-dialog-content.hfse-sbp-mobile-sheet[data-state="open"] {
  animation: hfse-sbp-mobile-slide-up 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
.hr-dialog-overlay.hfse-sbp-mobile-overlay {
  /* !important is load-bearing: DialogOverlay paints its rgba(0,0,0,0.6)
     scrim as an INLINE style, which beats any plain class rule — without it
     this suppression silently does nothing and the sheet gets the very
     backdrop flash it exists to prevent (codex r1). An important author
     declaration is the one thing that outranks a non-important inline style. */
  background-color: transparent !important;
}
/* Reduced motion: strip the pro transitions AND every animation added above.
   Toolkit parity: all four of its keyframes are killed under this query, and
   animateMonthSlide returns early before it ever clones the grid. */
@media (prefers-reduced-motion: reduce) {
  .hfse-sbp-bar,
  .hfse-sbp-field,
  .hfse-sbp-field-value,
  .hfse-sbp-where-input,
  .hfse-sbp-where-input::placeholder,
  .hfse-sbp-divider,
  .hfse-sbp-submit,
  .hfse-sbp-submit-label,
  .hfse-sbp-field-clear,
  .hfse-sbp-chip,
  .hfse-sbp-hover-indicator,
  .hfse-sbp-active-pill,
  .hfse-sbp-what-tab,
  .hfse-sbp-filter-chip,
  .hfse-sbp-stepper-btn,
  .hfse-sbp-price-bar,
  .hfse-sbp-price-thumb,
  .hfse-sbp-hero-shell,
  .hfse-sbp-hero-spacer,
  .hfse-sbp-hero-backdrop,
  .hfse-sbp-refine-shell,
  .hfse-sbp-refine-spacer,
  .hfse-sbp-refine-backdrop,
  .hfse-sbp-refine-pill {
    transition: none !important;
  }
  .hfse-sbp-submit:active {
    transform: none;
  }
  .hr-dialog-content.hfse-sbp-popover[data-state="open"],
  .hr-dialog-overlay.hfse-sbp-popover-overlay[data-state="open"],
  .hr-dialog-overlay.hfse-sbp-popover-overlay[data-state="closed"],
  .hr-dialog-content.hfse-sbp-mobile-sheet[data-state="open"],
  .hfse-sbp-mobile-stage.hfse-sbp-stage-active .hfse-sbp-stage-body,
  .hfse-sbp-mobile-stage.hfse-sbp-stage-active .hfse-sbp-stage-header .hfse-sbp-field-label,
  .hfse-sbp-field-clear {
    animation: none !important;
  }
}
/* ==========================================================================
   Mobile results sheet (#856) — toolkit explorer-mobile-sheet v2 port
   Reference: homerunner-toolkit assets/css/explorer-mobile-sheet.css (line
   refs inline) + assets/js/explorer-mobile-sheet.js. Map-first phone layout:
   the map is a fixed full-bleed backdrop, the results grid lives in a
   draggable bottom sheet (peek / half / full snaps), a floating Map/List
   pill flips between the two, and the search CTA is a fixed top bar pushed
   down by `mobileResults.navOffsetPx` (toolkit below_theme_nav + nav_offset).

   Gated by the `.hfse-mres` class ONLY — MobileResultsLayout renders it
   after hydration when `mobileResults.enabled` and the viewport is at or
   under `mobileResults.breakpointPx`, so there is deliberately no media
   query here: SSR and the first client paint keep the stacked layout (no
   desktop shift) and the class is the single switch tests assert on. The
   breakpoint is capped at 932px, under the 960px desktop map rules, so the
   two never overlap.

   Reduced motion: the layout adds `.hfse-mres-no-motion` from a matchMedia
   read instead of a new @media block — the motion-css contract reads the
   LAST prefers-reduced-motion block in this file (searchbar-motion-css
   test), which must stay the searchbar kill list above.
   ========================================================================== */
/* ---- Map backdrop (toolkit css:64-84): the sidebar fills the viewport. ---- */
.hfse.hfse-mres .hfse-sidebar {
  display: block;
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh; /* fallback */
  height: 100dvh;
  max-width: none;
  margin: 0;
  padding: 0;
  z-index: 1;
}
.hfse.hfse-mres .hfse-map-container {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
}
.hfse.hfse-mres .hfse-map {
  height: 100%;
  min-height: 100%;
}
/* Map chrome collides with the CTA and the sheet and pinch zoom covers it
   (toolkit css:86-95); the search-as-move checkbox goes with it, as in the
   module. The header map toggle and the show-tab have no job here: the map
   is always on. */
.hfse.hfse-mres .hfse-map-controls,
.hfse.hfse-mres .hfse-form-map-toggle-btn,
.hfse.hfse-mres .hfse-mapctl-showtab {
  display: none;
}
/* No slot for the section title while the map owns the viewport. */
.hfse.hfse-mres > .hr-widget-section {
  display: none;
}
/* iOS focus auto-zoom (toolkit css:35-46): any control under 16px triggers
   Safari's zoom-on-focus and there is no max-scale to recover from on a
   full-bleed map with the host page scroll-locked.
   Scoping this to `.hfse.hfse-mres` alone reached almost nothing: every text
   input on this layout lives in an `elevateDom` dialog, which portals to a
   top-level host OUTSIDE the widget subtree. `data-hfse-mres-on` is set on
   <html> for exactly the window the sheet owns the viewport, so it covers the
   portaled controls without leaking to other widgets on other pages. */
.hfse.hfse-mres input,
.hfse.hfse-mres select,
.hfse.hfse-mres textarea,
[data-hfse-mres-on] .hfse-sbp-mobile-sheet input,
[data-hfse-mres-on] .hfse-sbp-mobile-sheet select,
[data-hfse-mres-on] .hfse-sbp-mobile-sheet textarea,
[data-hfse-mres-on] .hr-dialog-content input,
[data-hfse-mres-on] .hr-dialog-content select,
[data-hfse-mres-on] .hr-dialog-content textarea {
  font-size: 16px !important;
}
/* ---- Sticky top: the search CTA (toolkit css:166-289). ---- */
.hfse-mres-topbar {
  position: fixed;
  top: var(--hfse-mres-nav-offset, 0px);
  left: 0;
  right: 0;
  z-index: 30;
  padding: 10px 12px 8px;
  /* Only the pill itself takes taps; the bar's gutters pass through to the map. */
  pointer-events: none;
}
.hfse-mres-topbar > * {
  pointer-events: auto;
}
.hfse-mres-cta {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 14px;
  border: 0;
  border-radius: 30px;
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.hfse-mres-cta-ico,
.hfse-mres-cta-filt {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
}
.hfse-mres-cta-main {
  flex: 1 1 auto;
  min-width: 0;
}
.hfse-mres-cta-title {
  display: block;
  font-weight: 600;
  font-size: 15px;
  line-height: 1.15;
}
.hfse-mres-cta-sub {
  display: block;
  font-size: 12px;
  line-height: 1.2;
  color: var(--hfse-muted-foreground, #717171);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Searchbar Pro: its mobile trigger IS the CTA (the module relocates SBP's
   own trigger into the topbar, js:424-459). The bar's results header moves
   to the sheet head (rendered there by ExplorerContent), the desktop bar and
   the chip row never belong in a fixed pill bar. */
.hfse-mres-topbar .hfse-filter-bar {
  margin: 0;
}
.hfse-mres-topbar .hfse-sbp-mobile-trigger {
  display: flex;
  margin: 0;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
}
/* The results-header selectors are gone from this list (#1251): the sheet's
   bar no longer mounts one at all, so there is nothing left to hide. */
.hfse-mres-topbar .hfse-sbp-bar,
.hfse-mres-topbar .hfse-sbp-hero-sentinel,
.hfse-mres-topbar .hfse-sbp-chips {
  display: none;
}
/* ---- Legacy filter panel (toolkit css:98-116): the filter bar becomes a
   full-screen takeover the CTA reveals; a search closes it. ---- */
.hfse-mres-filters {
  position: fixed;
  /* Sized to the VISUAL viewport (CSS vars published by MobileResultsLayout)
     so an overlay keyboard never hides the panel's bottom controls; the
     fallbacks are the layout viewport for the first paint. */
  left: 0;
  right: 0;
  top: var(--hfse-mres-vv-top, 0px);
  height: 100vh; /* fallback */
  height: var(--hfse-mres-vv-height, 100dvh);
  z-index: 45;
  margin: 0;
  padding: 64px 16px 24px;
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  transform: translateY(-102%);
  transition: transform 0.32s cubic-bezier(0.22, 0.61, 0.36, 1);
  visibility: hidden;
}
.hfse.hfse-mres.hfse-mres-filters-open .hfse-mres-filters {
  transform: translateY(0);
  visibility: visible;
}
/* The results header lives in the sheet head, not the panel — enforced by
   MOUNTING it once there (#1251, FilterBar withSecondaryRow={false}) rather
   than rendering a second copy here and hiding it. */
.hfse-mres-filter-close {
  display: none;
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 47;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.16);
  font-size: 18px;
  line-height: 40px;
  text-align: center;
  padding: 0;
  cursor: pointer;
}
.hfse.hfse-mres.hfse-mres-filters-open .hfse-mres-filter-close {
  display: block;
}
.hfse.hfse-mres.hfse-mres-filters-open .hfse-mres-topbar,
.hfse.hfse-mres.hfse-mres-filters-open .hfse-mres-fab {
  display: none;
}
/* ---- Bottom sheet (toolkit css:297-360). ---- */
.hfse.hfse-mres .hfse-body.hfse-mres-sheet {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  height: 100vh; /* fallback */
  height: var(--hfse-mres-vv-height, 100dvh);
  background: var(--hfse-card-bg, #fff);
  color: var(--hfse-foreground, #222);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.18);
  z-index: 40;
  /* Pre-JS rest position; MobileResultsLayout writes the px value on the
     first frame (js:1531-1533) and thereafter (transform is the hot path). */
  transform: translateY(52%);
  will-change: transform;
  /* pan-y, NOT none: this element is also the list's scroll region, and a
     `none` here won the cascade over the scroll rule and left touch users
     unable to scroll the list at `full` (codex r4). Sheet drags still win —
     the touchmove listener is non-passive and cancels the browser pan; the
     handle alone is `none`. */
  touch-action: pan-y;
  transition: transform 0.34s cubic-bezier(0.22, 0.61, 0.36, 1);
  display: flex;
  flex-direction: column;
}
/* Specificity has to match the compound rule above (`.hfse.hfse-mres
   .hfse-body.hfse-mres-sheet`, 0-4-0) or this never applies and the sheet rests
   at `half` until the rAF animates it down — the visible slide on every phone
   load that this class exists to prevent. */
.hfse.hfse-mres .hfse-body.hfse-mres-sheet.hfse-mres-sheet-init-peek {
  transform: translateY(86%);
}
.hfse-mres-grab {
  flex: 0 0 auto;
  padding: 10px 0 6px;
  display: flex;
  justify-content: center;
  width: 100%;
  border: 0;
  background: transparent;
  cursor: grab;
}
.hfse-mres-grab i {
  width: 36px;
  height: 5px;
  border-radius: 3px;
  background: var(--hfse-border, #d0d0d0);
  display: block;
}
.hfse-mres-head {
  flex: 0 0 auto;
  text-align: center;
  padding: 2px 16px 12px;
  border-bottom: 1px solid var(--hfse-border, #ebebeb);
}
.hfse-mres-count {
  font-weight: 700;
  font-size: 16px;
}
.hfse-mres-sub {
  font-size: 12.5px;
  color: var(--hfse-muted-foreground, #717171);
  margin-top: 3px;
}
/* The results header (count / sort) in the head, compact; the map toggle is
   already killed above. */
.hfse-mres-head .hfse-form {
  margin: 8px 0 0;
}
/* The sheet element IS the scroll region (it is the `.hfse-body` element in
   sheet mode, so the grid inside keeps its React position across the layout
   switch); the handle + head are rendered after the grid and pinned first
   with `order` + sticky. */
.hfse-mres-scroll {
  /* Cards scroll only when fully expanded (touch-action contract, js:1305). */
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  touch-action: pan-y;
  padding: 0 0 96px;
}
.hfse-mres-handle {
  order: -1;
  position: sticky;
  top: 0;
  z-index: 1;
  flex: 0 0 auto;
  background: var(--hfse-card-bg, #fff);
  border-radius: 18px 18px 0 0;
  touch-action: none;
}
/* Slider template on the sheet: the same PropertySlider stays mounted (a
   swap to the grid re-requested every quote) and is laid out as the module's
   vertical card list (toolkit css:361-385) — track as a column, cards full
   width, arrows gone. */
.hfse-mres-scroll .hfse-slider-track {
  display: flex;
  flex-direction: column;
  gap: var(--hfse-grid-gap, 16px);
  overflow: visible;
  scroll-snap-type: none;
  padding: 20px;
}
.hfse-mres-scroll .hfse-slider-card {
  flex: 0 0 auto;
  width: 100%;
  max-width: none;
}
.hfse-mres-scroll .hfse-slider-nav {
  display: none;
}
.hfse.hfse-mres.hfse-mres-snap-full .hfse-mres-scroll {
  overflow-y: auto;
}
/* One clean vertical list (toolkit css:361-385) whatever the grid columns say. */
.hfse-mres-scroll .hfse-properties {
  grid-template-columns: 1fr;
}
.hfse-mres-scroll .hfse-properties-container {
  width: 100%;
  max-width: none;
  margin: 0;
}
/* ---- Floating Map/List toggle (toolkit css:428-451). ---- */
.hfse-mres-fab {
  position: fixed;
  left: 50%;
  bottom: calc(26px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 60;
  background: var(--hfse-foreground, #222);
  color: var(--hfse-card-bg, #fff);
  border: 0;
  border-radius: 24px;
  padding: 13px 20px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  display: flex;
  align-items: center;
  gap: 8px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  transition: opacity 0.25s, transform 0.25s;
}
.hfse-mres-fab-ico {
  display: inline-flex;
  align-items: center;
}
/* Motion kill for the sheet layout (matchMedia-driven, see the header). */
.hfse.hfse-mres.hfse-mres-no-motion .hfse-mres-sheet,
.hfse.hfse-mres.hfse-mres-no-motion .hfse-mres-filters,
.hfse.hfse-mres.hfse-mres-no-motion .hfse-mres-fab {
  transition: none;
}
/* ==========================================================================
   WHAT popover — tabbed Filter / Describe / By-name surface (#870 slice 5)
   Toolkit reference: `hrtk-sbp-search-bar__what-*` in searchbar-pro.debug.css.
   The popover is portaled into the elevated dialog root, so its accent/shape
   tokens are mirrored onto `.hr-dialog-content.hfse-sbp-what` by
   buildSearchbarCss rather than inherited from `.hfse-sbp`.
   ========================================================================== */
/* Max-height is a MIN() OVER THE MEASURED CAP, not a flat viewport cap: this
   selector and `.hr-dialog-content.hfse-sbp-popover-anchored` are both (0,2,0)
   and land on the same node, and this block is later in the file, so it wins
   outright. Ignoring `--hfse-sbp-popover-max-h` here therefore threw away the
   anchored measurement and pushed the pane's footer below the fold (measured
   in Chromium: viewport 800, card bottom 1192, on a position:fixed element
   under a Radix scroll lock). The property is absent on the centred-modal
   path, so the fallback reproduces the plain 680/100vh cap byte-for-byte. */
.hr-dialog-content.hfse-sbp-what {
  display: flex;
  flex-direction: column;
  gap: 0;
  width: min(560px, calc(100vw - 32px));
  max-height: min(680px, var(--hfse-sbp-popover-max-h, calc(100vh - 64px)));
  padding: 20px 12px 12px 20px;
  box-sizing: border-box;
}
/* Segmented tab bar. The active pill lives on the button itself (flex:1) so it
   self-sizes to two or three tabs — the toolkit retired its sliding indicator
   for exactly this reason once "By name" made the tab count variable. */
.hfse-sbp-what-tabs {
  display: flex;
  gap: 2px;
  width: calc(100% - 12px);
  padding: 4px;
  margin: 0 0 16px;
  box-sizing: border-box;
  background: var(--hfse-input-bg, #f0f0f0);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
}
/* Per-tab icon (#925, toolkit 1df0842 css: 14px block svg, non-shrinking). */
.hfse-sbp-what-tab-icon {
  display: inline-flex;
  flex: 0 0 auto;
  margin-right: 6px;
  vertical-align: middle;
}
.hfse-sbp-what-tab-icon svg {
  display: block;
  width: 14px;
  height: 14px;
}
.hfse-sbp-what-tab {
  flex: 1 1 0;
  padding: 8px 18px;
  border: none;
  background: transparent;
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  font-weight: 500;
  color: var(--hfse-muted-foreground, #6b7280);
  cursor: pointer;
  transition: color 120ms ease, background 160ms ease, box-shadow 160ms ease;
}
.hfse-sbp-what-tab:hover:not(.hfse-sbp-what-tab-active) {
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-what-tab-active {
  color: var(--hfse-foreground, #111827);
  font-weight: 600;
  background: var(--hfse-card-bg, #fff);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}
.hfse-sbp-what-tab:focus-visible {
  outline: 2px solid var(--hfse-sbp-accent, #ff385c);
  outline-offset: 2px;
}
/* Only the pane scrolls: the tab bar and the footer stay pinned. */
.hfse-sbp-what-pane {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  margin-left: -4px;
  padding-left: 4px;
  padding-right: 12px;
}
.hfse-sbp-filter-section {
  display: flex;
  flex-direction: column;
  padding: 20px 0;
  border-bottom: 1px solid var(--hfse-border, #ebebeb);
}
.hfse-sbp-filter-section:first-child {
  padding-top: 4px;
}
.hfse-sbp-filter-section:last-child {
  border-bottom: 0;
  padding-bottom: 4px;
}
.hfse-sbp-filter-section-title {
  margin: 0 0 12px;
  font-size: var(--hfse-sbp-input-size, 15px);
  font-weight: 700;
  line-height: 1.3;
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-filter-section-subtitle {
  margin: 0 0 16px;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  line-height: 1.4;
  color: var(--hfse-muted-foreground, #6b7280);
}
/* Stepper row — label left, −/count/+ right, "Any" at zero. */
.hfse-sbp-stepper-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 8px 0;
}
.hfse-sbp-stepper-label {
  font-size: var(--hfse-sbp-input-size, 15px);
  line-height: 1.4;
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-stepper {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
}
.hfse-sbp-stepper-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--hfse-border, #b0b0b0);
  border-radius: 50%;
  background: transparent;
  color: var(--hfse-muted-foreground, #717171);
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) + 3px);
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.hfse-sbp-stepper-btn:hover:not(:disabled) {
  border-color: var(--hfse-foreground, #222);
  color: var(--hfse-foreground, #222);
}
.hfse-sbp-stepper-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.hfse-sbp-stepper-btn:focus-visible {
  outline: 2px solid var(--hfse-sbp-accent, #ff385c);
  outline-offset: 2px;
}
.hfse-sbp-stepper-count {
  min-width: 54px;
  text-align: center;
  font-size: var(--hfse-sbp-input-size, 15px);
  line-height: 1.2;
  color: var(--hfse-foreground, #111827);
}
/* Multi-toggle chips (property type + amenities). Constant font-weight so a
   toggle never reflows the row; the active state is color/border only. */
.hfse-sbp-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.hfse-sbp-filter-chip {
  display: inline-flex;
  align-items: center;
  height: 36px;
  padding: 0 14px;
  border: 1px solid var(--hfse-border, #d1d5db);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background: transparent;
  color: var(--hfse-muted-foreground, #6b7280);
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  font-weight: 600;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease, background 0.12s ease;
}
.hfse-sbp-filter-chip:hover:not(.hfse-sbp-filter-chip-active) {
  border-color: var(--hfse-muted-foreground, #6b7280);
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-filter-chip-active {
  border-color: var(--hfse-foreground, #222);
  background: var(--hfse-input-bg, #f0f0f0);
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-filter-chip:focus-visible {
  outline: 2px solid var(--hfse-sbp-accent, #ff385c);
  outline-offset: 2px;
}
.hfse-sbp-filter-show-more {
  display: inline-flex;
  align-self: flex-start;
  margin-top: 12px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--hfse-foreground, #111827);
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.hfse-sbp-filter-show-more:hover {
  color: var(--hfse-sbp-accent, #ff385c);
}
/* Price histogram + dual-thumb track. Bars set their own height %; the ones
   outside the selected range dim to gray. */
.hfse-sbp-price-histogram {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 64px;
  margin: 8px 0 0;
  padding: 0 12px;
}
.hfse-sbp-price-bar {
  flex: 1 1 0;
  min-width: 2px;
  background: var(--hfse-sbp-accent, #ff385c);
  border-radius: 2px 2px 0 0;
  transition: background 0.15s ease, opacity 0.15s ease;
}
.hfse-sbp-price-bar-dim {
  background: var(--hfse-border, #ddd);
}
.hfse-sbp-price-track {
  position: relative;
  height: 24px;
  margin: 4px 12px 0;
}
.hfse-sbp-price-track-base {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 2px;
  background: var(--hfse-border, #ddd);
  border-radius: 2px;
  transform: translateY(-50%);
}
.hfse-sbp-price-track-fill {
  position: absolute;
  top: 50%;
  height: 2px;
  background: var(--hfse-sbp-accent, #ff385c);
  border-radius: 2px;
  transform: translateY(-50%);
}
.hfse-sbp-price-thumb {
  position: absolute;
  top: 50%;
  width: 28px;
  height: 28px;
  padding: 0;
  margin: 0;
  border: 1px solid var(--hfse-border, #b0b0b0);
  border-radius: 50%;
  background: var(--hfse-card-bg, #fff);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
  transform: translate(-50%, -50%);
  cursor: grab;
  touch-action: none;
  z-index: 2;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.hfse-sbp-price-thumb:hover {
  border-color: var(--hfse-foreground, #222);
}
.hfse-sbp-price-thumb-dragging {
  cursor: grabbing;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.22);
}
.hfse-sbp-price-thumb:focus-visible {
  outline: 2px solid var(--hfse-sbp-accent, #ff385c);
  outline-offset: 2px;
}
.hfse-sbp-price-fields {
  display: flex;
  gap: 12px;
  margin-top: 16px;
}
.hfse-sbp-price-field {
  flex: 0 1 130px;
  max-width: 130px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.hfse-sbp-price-field-label {
  padding-left: 16px;
  font-size: calc(var(--hfse-sbp-label-size, 11px) + 1px);
  line-height: 1.2;
  color: var(--hfse-muted-foreground, #6b7280);
}
.hfse-sbp-price-field-input {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 10px 16px;
  border: 1px solid var(--hfse-border, #d1d5db);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-card-bg, #fff);
  transition: border-color 0.12s ease;
}
.hfse-sbp-price-field-input:focus-within {
  border-color: var(--hfse-foreground, #222);
}
.hfse-sbp-price-field-currency {
  flex-shrink: 0;
  font-size: var(--hfse-sbp-input-size, 15px);
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-price-field-input input {
  flex: 1 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font: inherit;
  font-size: var(--hfse-sbp-input-size, 15px);
  color: var(--hfse-foreground, #111827);
}
/* Shared text-entry box — keyword search and the By-name lookup. */
.hfse-sbp-what-inputbox {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border: 1px solid var(--hfse-border, #d1d5db);
  border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-card-bg, #fff);
  transition: border-color 0.12s ease;
}
.hfse-sbp-what-inputbox:focus-within {
  border-color: var(--hfse-foreground, #222);
}
.hfse-sbp-what-inputbox-icon {
  display: flex;
  flex-shrink: 0;
  color: var(--hfse-muted-foreground, #6b7280);
}
.hfse-sbp-what-inputbox-input {
  flex: 1 1 0;
  min-width: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  font: inherit;
  font-size: var(--hfse-sbp-input-size, 15px);
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-what-byname-results {
  list-style: none;
  margin: 12px 0 0;
  padding: 0;
}
.hfse-sbp-what-byname-result {
  display: block;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-radius: min(10px, var(--hfse-sbp-shape-max, 999px));
  background: transparent;
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  text-align: left;
  color: var(--hfse-foreground, #111827);
  cursor: pointer;
}
.hfse-sbp-what-byname-result:hover {
  background: var(--hfse-input-bg, #f7f7f7);
}
/* Describe pane (dark until the concierge runs for a feed). */
.hfse-sbp-what-describe-box {
  padding: 12px 14px;
  border: 1px solid var(--hfse-border, #d1d5db);
  border-radius: min(16px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-card-bg, #fff);
}
.hfse-sbp-what-describe-input {
  display: block;
  width: 100%;
  border: 0;
  outline: 0;
  resize: none;
  background: transparent;
  font: inherit;
  font-size: var(--hfse-sbp-input-size, 15px);
  line-height: 1.5;
  color: var(--hfse-foreground, #111827);
}
.hfse-sbp-what-suggestions-heading {
  margin: 20px 0 8px;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 2px);
  font-weight: 700;
  color: var(--hfse-muted-foreground, #6b7280);
}
.hfse-sbp-what-suggestions {
  list-style: none;
  margin: 0;
  padding: 0;
}
.hfse-sbp-what-suggestion {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 8px;
  border: 0;
  border-radius: min(12px, var(--hfse-sbp-shape-max, 999px));
  background: transparent;
  font: inherit;
  font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
  font-weight: 600;
  text-align: left;
  color: var(--hfse-foreground, #111827);
  cursor: pointer;
}
.hfse-sbp-what-suggestion:hover {
  background: var(--hfse-input-bg, #f7f7f7);
}
.hfse-sbp-what-suggestion-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: min(8px, var(--hfse-sbp-shape-max, 999px));
  background: var(--hfse-input-bg, #f0f0f0);
  color: var(--hfse-muted-foreground, #6b7280);
}
/* Footer — no Apply button: filters are already applied (live-apply). */
.hfse-sbp-what-footer {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-shrink: 0;
  padding: 12px 12px 0 0;
  border-top: 1px solid var(--hfse-border, #ebebeb);
}
@media (max-width: 932px) {
  .hr-dialog-content.hfse-sbp-what {
    width: 100%;
    max-height: 100%;
  }
}
/* Reduced-motion kills for the WHAT popover live in the shared searchbar
   kill list above (the motion-css contract reads the LAST reduced-motion
   block in this file — keep it single). */
/* ==========================================================================
   Hero / standalone layout (#934) — toolkit refine="0" parity
   `search.heroBar` renders the bar as the whole widget (grid/map/results
   chrome are gated off in ExplorerContent/ProFilterBar). Two surfaces:
   1) hero dress scale — the module's homepage bar is taller than the
      widget's integrated bar (the refine variant slims fields 64px→48px and
      the submit 64px→48px, searchbar-pro.css:3488-3502, so 64 is the hero
      number; the widget's integrated bar sits at 52px);
   2) scroll-detach sticky (module initSticky hero branch,
      searchbar-pro.js:4657-4910 + css:2564-2700): the shell pins to a
      viewport-centered compressed pill, expands to a top-attached panel
      over a dimming backdrop.
   Desktop only (≥933px): below that the mobile trigger replaces the bar and
   useHeroSticky never arms. Transitions only, no keyframes — reduced-motion
   kills live in the SHARED kill list above (motion contract: the LAST
   reduced-motion block in this file is the one true list; do not add one
   here). Sentinel sits outside the media query: it must be layout-neutral
   at every viewport.
   ========================================================================== */
.hfse-sbp-hero-sentinel,
.hfse-sbp-refine-sentinel {
  /* Absolute at the bar area's top edge (.hfse-sbp is position:relative):
     zero layout impact, and its rect keeps meaning "where the bar lives in
     flow" while the pinned shell is out of flow — the spacer holds the
     vacated height, so un-pin fires at the true top. visibility, not
     display: IntersectionObserver needs a layout box. Shared by both sticky
     variants; the refine hook additionally reads this rect on scroll for
     the compress threshold (#1092). */
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
  visibility: hidden;
}
@media (min-width: 933px) {
  /* --- 1) Hero dress scale ------------------------------------------------ */
  .hfse-explorer-hero .hfse-sbp-field {
    min-height: 64px;
  }
  .hfse-explorer-hero .hfse-sbp-submit {
    width: 64px;
    height: 64px;
  }
  /* #942: EXPANDED === "some field is open" applies in hero too. The dress
     pin above ties specificity with the has-active morph (explorer.css
     ~2828) and wins on order, freezing the submit at the icon square while a
     field is open — restate the expanded width under the hero scope so the
     morph wins there as well (height stays the 64px dress height). */
  .hfse-explorer-hero .hfse-sbp-bar-has-active .hfse-sbp-submit {
    width: var(--hfse-sbp-cta-w, 130px);
  }

  /* --- 2) Scroll-detach sticky -------------------------------------------- */
  /* Pinned: viewport-centered compressed pill (module css:2566-2586). */
  .hfse-sbp-hero-shell-sticky {
    position: fixed;
    /* --hfse-sbp-hero-top (search.heroStickyTopPx, inline on the shell)
       shifts both pinned states below a host site's fixed/reveal header;
       0 fallback = module parity. */
    top: calc(16px + var(--hfse-sbp-hero-top, 0px));
    left: 50%;
    transform: translateX(-50%);
    width: calc(100% - 32px);
    max-width: 420px;
    z-index: 9999;
    background: transparent;
    padding: 0;
    border-radius: 0;
    box-shadow: none;
    transition:
      top 0.28s cubic-bezier(0.4, 0, 0.2, 1),
      max-width 0.28s cubic-bezier(0.4, 0, 0.2, 1),
      padding 0.22s cubic-bezier(0.4, 0, 0.2, 1),
      background-color 0.2s ease,
      border-radius 0.22s ease,
      box-shadow 0.22s ease;
  }
  /* Expanded: panel attaches to the viewport top (0 top corners), wraps the
     bar with concentric bottom corners (module css:2589-2604). */
  .hfse-sbp-hero-shell-sticky.hfse-sbp-hero-shell-expanded {
    top: var(--hfse-sbp-hero-top, 0px);
    max-width: 890px;
    background: var(--hfse-card-bg, #fff);
    padding: 14px 20px;
    border-radius: 0 0 min(50px, var(--hfse-sbp-shape-max, 999px)) min(50px, var(--hfse-sbp-shape-max, 999px));
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18), 0 4px 12px rgba(0, 0, 0, 0.08);
  }
  /* Form inside the pinned shell takes the shell's inner width; expanded, the
     shell owns the drop shadow so the bar doesn't double it. */
  .hfse-sbp-hero-shell-sticky .hfse-sbp-bar {
    margin: 0 auto;
    width: 100%;
    max-width: none;
  }
  .hfse-sbp-hero-shell-expanded .hfse-sbp-bar {
    box-shadow: none;
  }

  /* Compressed: bar internals hide, the single pill button shows. The slot
     spans are display:contents, so hiding the slot removes its whole subtree
     (field + divider) in one rule. */
  .hfse-sbp-bar-hero-compressed > .hfse-sbp-bar-slot,
  .hfse-sbp-bar-hero-compressed > .hfse-sbp-submit,
  .hfse-sbp-bar-hero-compressed > .hfse-sbp-hover-indicator,
  .hfse-sbp-bar-hero-compressed > .hfse-sbp-active-pill {
    display: none;
  }
  .hfse-sbp-hero-compressed {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    width: 100%;
    min-height: 52px;
    padding: 6px 8px 6px 22px;
    margin: 0;
    background: transparent;
    border: 0;
    cursor: pointer;
    font: inherit;
    color: inherit;
    border-radius: inherit;
    text-align: left;
    -webkit-appearance: none;
    appearance: none;
  }
  .hfse-sbp-hero-compressed-summary {
    flex: 1 1 auto;
    font-size: calc(var(--hfse-sbp-input-size, 15px) - 1px);
    font-weight: 600;
    color: var(--hfse-foreground, #222);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .hfse-sbp-hero-compressed-icon {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: min(999px, var(--hfse-sbp-shape-max, 999px));
    background: var(--hfse-sbp-accent, #ff385c);
    color: #fff;
  }
  .hfse-sbp-hero-compressed-icon svg {
    width: 16px;
    height: 16px;
  }
  .hfse-sbp-hero-compressed:hover .hfse-sbp-hero-compressed-icon {
    filter: brightness(0.95);
  }
  .hfse-sbp-hero-compressed:focus-visible {
    outline: 2px solid var(--hfse-sbp-accent, #ff385c);
    outline-offset: 2px;
  }

  /* Spacer holds the vacated flow height while the shell is pinned (inline
     height set by useHeroSticky); backdrop dims the page behind the expanded
     panel and click-collapses it. Both stay inside .hfse-sbp's isolated
     stacking context: backdrop under shell, above everything else sbp. */
  .hfse-sbp-hero-spacer {
    height: 0;
    width: 100%;
    pointer-events: none;
    transition: height 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  }
  .hfse-sbp-hero-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.42);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.22s cubic-bezier(0.4, 0, 0.2, 1);
    z-index: 9998;
  }
  .hfse-sbp-hero-backdrop-visible {
    opacity: 1;
    pointer-events: auto;
  }
}
/* ==========================================================================
   SBP refine in-place sticky (#1092) — toolkit initSticky REFINE branch.
   Source of truth: searchbar-pro.js:4771-5029 (v3.67.0 pin-in-place +
   v3.68.1 threshold morph) and searchbar-pro.debug.css:3656-3807. Only the
   BAR pins: position:fixed with left/width copied from the spacer's in-flow
   box by useRefineSticky (position:sticky can't engage — the shell is a
   short wrapper, not the full column), transparent shell, and the scrim
   ::before emitted by buildSearchbarCss onto the pinned shell. The morph is
   SEQUENCED so content is never visible mid-resize: fields fade OUT 120ms →
   the empty bar's width animates 240ms after a 110ms delay → the pill fades
   IN 150ms after 330ms (and the mirror order on expand-back). Content stays
   RENDERED (opacity, never display) so the fade-in cannot re-layout.
   Desktop only (≥933px, hook bails below); the sentinel shares the hero
   rule above; reduced-motion keeps the pin and drops the morph via the
   SHARED kill list (do not add one here). Transitions only, no keyframes.
   ========================================================================== */
/* One flex item for the whole refine anatomy: .hfse-filter-bar's 20px gap
   must not multiply across sentinel/shell/spacer, and the flex-item count
   must not change when the shell goes position:fixed (see ProFilterBar). */
.hfse-sbp-refine-slot {
  width: 100%;
}
/* The shell is a programmatic focus park (tabIndex -1) during the morph —
   never a visible focus stop. */
.hfse-sbp-refine-shell:focus {
  outline: none;
}
@media (min-width: 933px) {
  .hfse-sbp-refine-shell-sticky {
    position: fixed;
    /* --hfse-sbp-refine-top (search.heroStickyTopPx, inline on the shell)
       drops the pinned bar below a host site's fixed header; the 12px base
       is the module's refine top offset (css:3677). left/width are inline
       from useRefineSticky (module positionRefine — zero sideways jump). */
    top: calc(12px + var(--hfse-sbp-refine-top, 0px));
    z-index: 9999;
    background: transparent;
    /* The shell spans the whole column for the scrim, but the bar inside is
       at most 850px/480px — without this, the transparent side gutters
       would swallow clicks on listings scrolling underneath. The bar
       restores its own pointer-events below. */
    pointer-events: none;
  }

  /* The form is the morph stage: centred so the collapse is symmetric, width
     morphs between the concrete bar px (--hfse-sbp-bar-w, set by JS as the
     column width clamped to --hfse-sbp-max-width so pinning never snaps a
     narrower bar to full column width; 100% → 480px does not interpolate
     reliably) and the pill (module css:3695-3716). */
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar {
    margin: 0 auto;
    width: var(--hfse-sbp-bar-w, 100%);
    max-width: none;
    /* The shell is pointer-events:none (gutter clicks pass through) — the
       bar itself is the interactive surface. */
    pointer-events: auto;
    transition: width 240ms cubic-bezier(0.4, 0, 0.2, 1) 110ms, box-shadow 240ms ease;
  }
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar.hfse-sbp-bar-refine-compressed {
    /* min() deviates from the module's hardcoded 480px (css:3714) on
       purpose: the module's results columns are always wide, but the widget
       embeds into arbitrary host columns — a column under 480px would have
       the pill (shadow included) poking past the shell it was measured to.
       --hfse-sbp-bar-w rides in the clamp too: a bar configured narrower
       than 480px (maxWidthPx goes down to 320) must never GROW when it
       compresses. All operands are lengths, so the morph interpolates. */
    width: min(480px, var(--hfse-sbp-bar-w, 100%), 100%);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.12);
  }

  /* Content fade: full state fades IN LAST (330ms delay clears the resize)…
     (module css:3725-3731). The fade rides COMPOSED onto the fields' and
     submit's own transition lists — a bare opacity/visibility list here
     would replace the fields' flex/background springs and the submit's
     width morph for the whole pinned stretch, snapping every normal
     interaction after expand. Dividers have no base list to preserve. */
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar > .hfse-sbp-bar-slot .hfse-sbp-divider {
    opacity: 1;
    visibility: visible;
    transition: opacity 150ms ease 330ms, visibility 0s 330ms;
  }
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar .hfse-sbp-field {
    opacity: 1;
    visibility: visible;
    transition:
      background-color 300ms var(--hfse-sbp-spring, ease),
      box-shadow 300ms var(--hfse-sbp-spring, ease),
      flex-grow 300ms var(--hfse-sbp-spring, ease),
      flex-basis 300ms var(--hfse-sbp-spring, ease),
      min-width 300ms var(--hfse-sbp-spring, ease),
      opacity 150ms ease 330ms,
      visibility 0s 330ms;
  }
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar > .hfse-sbp-submit {
    opacity: 1;
    visibility: visible;
    transition:
      width 250ms ease,
      padding 250ms ease,
      gap 250ms ease,
      background-color 0.15s ease,
      transform 0.1s ease,
      opacity 150ms ease 330ms,
      visibility 0s 330ms;
  }
  /* …compressed state fades OUT FIRST (no delay), before the resize; content
     stays rendered and squishable (min-width:0) so neither fade re-layouts
     (module css:3718-3739). visibility flips AFTER each fade (the delayed
     discrete transition) — unlike the module, the invisible controls drop
     out of the tab order and the accessibility tree while the pill is up;
     opacity+pointer-events alone leave them keyboard-focusable. Scoped
     under the sticky shell so these rules OUTRANK the full-state rules
     above — bare .hfse-sbp-bar-refine-compressed descendants sit at lower
     specificity and would lose, leaving fields visible under the pill (the
     width rules always carried the shell prefix; the fades must too). */
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar.hfse-sbp-bar-refine-compressed .hfse-sbp-field,
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar.hfse-sbp-bar-refine-compressed > .hfse-sbp-bar-slot .hfse-sbp-divider,
  .hfse-sbp-refine-shell-sticky .hfse-sbp-bar.hfse-sbp-bar-refine-compressed > .hfse-sbp-submit {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    min-width: 0;
    transition: opacity 120ms ease 0ms, visibility 0s 120ms;
  }
  /* The sliding indicators are meaningless under the pill (module css:2767
     leaves them display:none in compressed — refine re-shows only
     field/divider/submit). */
  .hfse-sbp-bar-refine-compressed > .hfse-sbp-hover-indicator,
  .hfse-sbp-bar-refine-compressed > .hfse-sbp-active-pill {
    display: none;
  }

  /* Pill: absolute overlay on the bar, mirror-sequenced to the fields —
     IN last on compress, OUT first on expand (module css:3741-3755). Base
     look comes from the shared .hfse-sbp-hero-compressed classes on the
     same element; these declarations win on file order at equal
     specificity. */
  .hfse-sbp-refine-pill {
    position: absolute;
    inset: 0;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 120ms ease 0ms, visibility 0s 120ms;
  }
  .hfse-sbp-bar-refine-compressed > .hfse-sbp-refine-pill {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transition: opacity 150ms ease 330ms, visibility 0s 330ms;
  }

  /* Spacer holds the vacated flow height while the shell is pinned (inline
     height from useRefineSticky); the backdrop stays a click-catcher to
     collapse the expanded bar but is TRANSPARENT — the hero's modal-drawer
     dimming would be wrong for an in-place bar (module css:3688-3693).
     Height applies SYNCHRONOUSLY (no transition): the shell leaves flow the
     same instant, so an animated spacer would let the grid jump up a bar
     height and slide back on every pin (module js:4923 sets it directly). */
  .hfse-sbp-refine-spacer {
    height: 0;
    width: 100%;
    pointer-events: none;
  }
  .hfse-sbp-refine-backdrop {
    position: fixed;
    inset: 0;
    background: transparent;
    pointer-events: none;
    z-index: 9998;
  }
  .hfse-sbp-refine-backdrop-visible {
    pointer-events: auto;
  }
}
/* ==========================================================================
   Marketing (promo) cards in the results grid (#1145, ckit Marketing Cards)
   The wrapper is a plain grid cell (no .hfse-property-container, so the card
   skin never styles it). Colors arrive as --hfse-mc-* custom properties
   baked onto the wrapper by MarketingCard.tsx — operator-chosen, identical
   in light and dark (as in WP), so nothing here is theme-dependent.
   height:100% keeps the card the height of its neighbor listing cards; the
   reserved media aspect-ratio prevents reflow when the image loads (no CLS).
   ========================================================================== */
.hfse-marketing-card .hfse-mc-inner {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 12px;
  overflow: hidden;
  background: var(--hfse-mc-bg, #0A386B);
  color: var(--hfse-mc-text, #ffffff);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
/* Stretched-link overlay: an absolutely-positioned SIBLING anchor covering the
   panel. The visible CTA button sits above it (z-index) so it stays
   independently clickable; valid HTML because the anchors are never nested. */
/* The inner wrapper clips with overflow: hidden, so the browser's default
   outline on the stretched link can vanish — draw an inset ring instead. */
.hfse-marketing-card .hfse-mc-cardlink:focus-visible {
  outline: 2px solid var(--hfse-mc-text, #ffffff);
  outline-offset: -2px;
}
.hfse-marketing-card .hfse-mc-cardlink {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: block;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: inherit;
  background: transparent;
  box-shadow: none;
  font-size: 0;
  text-indent: -9999px;
}
.hfse-marketing-card.hfse-mc-has-cardlink {
  cursor: pointer;
}
.hfse-marketing-card.hfse-mc-has-cardlink .hfse-mc-cta {
  position: relative;
  z-index: 2;
}
/* Cover image: the operator-chosen scrim (--hfse-mc-bg-scrim, an rgba baked
   from the picker color + opacity) is the FIRST background layer, painted
   below all content so it never fights the overlay link or body z-index.
   The solid bg color stays as the fallback behind transparent/loading images. */
.hfse-marketing-card.hfse-mc-has-bg-image .hfse-mc-inner {
  background-image:
    linear-gradient(var(--hfse-mc-bg-scrim, rgba(0, 0, 0, 0.4)), var(--hfse-mc-bg-scrim, rgba(0, 0, 0, 0.4))),
    var(--hfse-mc-bg-image);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.hfse-marketing-card .hfse-mc-media {
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.06);
}
.hfse-marketing-card .hfse-mc-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.hfse-marketing-card .hfse-mc-body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: 8px;
  padding: 20px;
}
.hfse-marketing-card .hfse-mc-eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  opacity: 0.85;
}
.hfse-marketing-card .hfse-mc-title {
  margin: 0;
  font-size: 1.25rem;
  line-height: 1.25;
  color: inherit;
}
.hfse-marketing-card .hfse-mc-copy {
  font-size: 0.95rem;
  line-height: 1.5;
  opacity: 0.95;
  /* pre-line serves both body modes (#1163): plain text keeps authored line
     breaks with no HTML, and a rich-text body keeps them working alongside
     <br> — the inline allowlist has no block tags to conflict with. */
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.hfse-marketing-card .hfse-mc-cta {
  display: inline-block;
  margin-top: auto;
  align-self: flex-start;
  padding: 10px 18px;
  border-radius: 8px;
  background: var(--hfse-mc-btn-bg, #ffffff);
  color: var(--hfse-mc-btn-text, #0A386B);
  font-weight: 600;
  text-decoration: none;
  transition: opacity 0.15s ease;
}
.hfse-marketing-card .hfse-mc-cta:hover,
.hfse-marketing-card .hfse-mc-cta:focus {
  opacity: 0.9;
}
